mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 18:40:40 -05:00
eccf7b105c
Make sure our keyboard accessibility settings structure is all zero initialized, to avoid potential padding issues on some platform when comparing settings. Reported by Daniel van Vugt on IRC. https://gitlab.gnome.org/GNOME/mutter/merge_requests/552
2509 lines
85 KiB
C
2509 lines
85 KiB
C
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
/*
|
|
* Copyright 2014 Red Hat, Inc.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Carlos Garnacho <carlosg@gnome.org>
|
|
*/
|
|
|
|
/**
|
|
* SECTION:input-settings
|
|
* @title: MetaInputSettings
|
|
* @short_description: Mutter input device configuration
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib/gi18n-lib.h>
|
|
#include <string.h>
|
|
|
|
#include "backends/meta-backend-private.h"
|
|
#include "backends/meta-input-settings-private.h"
|
|
#include "backends/meta-input-mapper-private.h"
|
|
#include "backends/meta-logical-monitor.h"
|
|
#include "backends/meta-monitor.h"
|
|
#include "core/display-private.h"
|
|
#include "meta/util.h"
|
|
|
|
static GQuark quark_tool_settings = 0;
|
|
|
|
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
|
|
typedef struct _DeviceMappingInfo DeviceMappingInfo;
|
|
typedef struct _CurrentToolInfo CurrentToolInfo;
|
|
|
|
struct _CurrentToolInfo
|
|
{
|
|
MetaInputSettings *input_settings;
|
|
ClutterInputDevice *device;
|
|
ClutterInputDeviceTool *tool;
|
|
GSettings *settings;
|
|
guint changed_id;
|
|
};
|
|
|
|
struct _DeviceMappingInfo
|
|
{
|
|
MetaInputSettings *input_settings;
|
|
ClutterInputDevice *device;
|
|
GSettings *settings;
|
|
guint changed_id;
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDevice *wacom_device;
|
|
#endif
|
|
guint *group_modes;
|
|
};
|
|
|
|
struct _MetaInputSettingsPrivate
|
|
{
|
|
ClutterDeviceManager *device_manager;
|
|
MetaMonitorManager *monitor_manager;
|
|
guint monitors_changed_id;
|
|
|
|
GSettings *mouse_settings;
|
|
GSettings *touchpad_settings;
|
|
GSettings *trackball_settings;
|
|
GSettings *keyboard_settings;
|
|
GSettings *gsd_settings;
|
|
GSettings *a11y_settings;
|
|
|
|
GHashTable *mappable_devices;
|
|
|
|
GHashTable *current_tools;
|
|
|
|
ClutterVirtualInputDevice *virtual_pad_keyboard;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDeviceDatabase *wacom_db;
|
|
#endif
|
|
|
|
GHashTable *two_finger_devices;
|
|
|
|
/* Pad ring/strip emission */
|
|
struct {
|
|
ClutterInputDevice *pad;
|
|
MetaPadActionType action;
|
|
guint number;
|
|
gdouble value;
|
|
} last_pad_action_info;
|
|
|
|
/* For absolute devices with no mapping in settings */
|
|
MetaInputMapper *input_mapper;
|
|
};
|
|
|
|
typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
gboolean setting);
|
|
typedef void (*ConfigDoubleFunc) (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
gdouble value);
|
|
typedef void (*ConfigUintFunc) (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
guint value);
|
|
|
|
typedef enum
|
|
{
|
|
META_PAD_DIRECTION_NONE = -1,
|
|
META_PAD_DIRECTION_UP = 0,
|
|
META_PAD_DIRECTION_DOWN,
|
|
META_PAD_DIRECTION_CW,
|
|
META_PAD_DIRECTION_CCW,
|
|
} MetaPadDirection;
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT)
|
|
|
|
static GSList *
|
|
meta_input_settings_get_devices (MetaInputSettings *settings,
|
|
ClutterInputDeviceType type)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
const GSList *devices;
|
|
GSList *list = NULL;
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
devices = clutter_device_manager_peek_devices (priv->device_manager);
|
|
|
|
while (devices)
|
|
{
|
|
ClutterInputDevice *device = devices->data;
|
|
|
|
if (clutter_input_device_get_device_type (device) == type &&
|
|
clutter_input_device_get_device_mode (device) != CLUTTER_INPUT_MODE_MASTER)
|
|
list = g_slist_prepend (list, device);
|
|
|
|
devices = devices->next;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_dispose (GObject *object)
|
|
{
|
|
MetaInputSettings *settings = META_INPUT_SETTINGS (object);
|
|
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings);
|
|
|
|
g_clear_object (&priv->virtual_pad_keyboard);
|
|
|
|
g_clear_object (&priv->mouse_settings);
|
|
g_clear_object (&priv->touchpad_settings);
|
|
g_clear_object (&priv->trackball_settings);
|
|
g_clear_object (&priv->keyboard_settings);
|
|
g_clear_object (&priv->gsd_settings);
|
|
g_clear_object (&priv->a11y_settings);
|
|
g_clear_object (&priv->input_mapper);
|
|
g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
|
|
g_clear_pointer (&priv->current_tools, g_hash_table_unref);
|
|
|
|
if (priv->monitors_changed_id && priv->monitor_manager)
|
|
{
|
|
g_signal_handler_disconnect (priv->monitor_manager,
|
|
priv->monitors_changed_id);
|
|
priv->monitors_changed_id = 0;
|
|
}
|
|
|
|
g_clear_object (&priv->monitor_manager);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
if (priv->wacom_db)
|
|
libwacom_database_destroy (priv->wacom_db);
|
|
#endif
|
|
|
|
g_clear_pointer (&priv->two_finger_devices, g_hash_table_destroy);
|
|
|
|
G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
settings_device_set_bool_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ConfigBoolFunc func,
|
|
gboolean enabled)
|
|
{
|
|
func (input_settings, device, enabled);
|
|
}
|
|
|
|
static void
|
|
settings_set_bool_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDeviceType type,
|
|
ConfigBoolFunc func,
|
|
gboolean enabled)
|
|
{
|
|
GSList *devices, *d;
|
|
|
|
devices = meta_input_settings_get_devices (input_settings, type);
|
|
|
|
for (d = devices; d; d = d->next)
|
|
settings_device_set_bool_setting (input_settings, d->data, func, enabled);
|
|
|
|
g_slist_free (devices);
|
|
}
|
|
|
|
static void
|
|
settings_device_set_double_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ConfigDoubleFunc func,
|
|
gdouble value)
|
|
{
|
|
func (input_settings, device, value);
|
|
}
|
|
|
|
static void
|
|
settings_set_double_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDeviceType type,
|
|
ConfigDoubleFunc func,
|
|
gdouble value)
|
|
{
|
|
GSList *devices, *d;
|
|
|
|
devices = meta_input_settings_get_devices (input_settings, type);
|
|
|
|
for (d = devices; d; d = d->next)
|
|
settings_device_set_double_setting (input_settings, d->data, func, value);
|
|
|
|
g_slist_free (devices);
|
|
}
|
|
|
|
static void
|
|
settings_device_set_uint_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ConfigUintFunc func,
|
|
guint value)
|
|
{
|
|
(func) (input_settings, device, value);
|
|
}
|
|
|
|
static void
|
|
settings_set_uint_setting (MetaInputSettings *input_settings,
|
|
ClutterInputDeviceType type,
|
|
ConfigUintFunc func,
|
|
guint value)
|
|
{
|
|
GSList *devices, *d;
|
|
|
|
devices = meta_input_settings_get_devices (input_settings, type);
|
|
|
|
for (d = devices; d; d = d->next)
|
|
settings_device_set_uint_setting (input_settings, d->data, func, value);
|
|
|
|
g_slist_free (devices);
|
|
}
|
|
|
|
static void
|
|
update_touchpad_left_handed (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GDesktopTouchpadHandedness handedness;
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean enabled = FALSE;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
handedness = g_settings_get_enum (priv->touchpad_settings, "left-handed");
|
|
|
|
switch (handedness)
|
|
{
|
|
case G_DESKTOP_TOUCHPAD_HANDEDNESS_RIGHT:
|
|
enabled = FALSE;
|
|
break;
|
|
case G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT:
|
|
enabled = TRUE;
|
|
break;
|
|
case G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE:
|
|
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_left_handed,
|
|
enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
input_settings_class->set_left_handed,
|
|
enabled);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_mouse_left_handed (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean enabled;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_POINTER_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
enabled = g_settings_get_boolean (priv->mouse_settings, "left-handed");
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_left_handed,
|
|
enabled);
|
|
}
|
|
else
|
|
{
|
|
GDesktopTouchpadHandedness touchpad_handedness;
|
|
|
|
settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE,
|
|
input_settings_class->set_left_handed,
|
|
enabled);
|
|
|
|
touchpad_handedness = g_settings_get_enum (priv->touchpad_settings,
|
|
"left-handed");
|
|
|
|
/* Also update touchpads if they're following mouse settings */
|
|
if (touchpad_handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE)
|
|
update_touchpad_left_handed (input_settings, NULL);
|
|
}
|
|
}
|
|
|
|
static void
|
|
do_update_pointer_accel_profile (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device,
|
|
GDesktopPointerAccelProfile profile)
|
|
{
|
|
MetaInputSettingsPrivate *priv =
|
|
meta_input_settings_get_instance_private (input_settings);
|
|
MetaInputSettingsClass *input_settings_class =
|
|
META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
|
|
if (settings == priv->mouse_settings)
|
|
input_settings_class->set_mouse_accel_profile (input_settings,
|
|
device,
|
|
profile);
|
|
else if (settings == priv->trackball_settings)
|
|
input_settings_class->set_trackball_accel_profile (input_settings,
|
|
device,
|
|
profile);
|
|
}
|
|
|
|
static void
|
|
update_pointer_accel_profile (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
GDesktopPointerAccelProfile profile;
|
|
|
|
profile = g_settings_get_enum (settings, "accel-profile");
|
|
|
|
if (device)
|
|
{
|
|
do_update_pointer_accel_profile (input_settings, settings,
|
|
device, profile);
|
|
}
|
|
else
|
|
{
|
|
MetaInputSettingsPrivate *priv =
|
|
meta_input_settings_get_instance_private (input_settings);
|
|
const GSList *devices;
|
|
const GSList *l;
|
|
|
|
devices = clutter_device_manager_peek_devices (priv->device_manager);
|
|
for (l = devices; l; l = l->next)
|
|
{
|
|
device = l->data;
|
|
|
|
if (clutter_input_device_get_device_mode (device) ==
|
|
CLUTTER_INPUT_MODE_MASTER)
|
|
continue;
|
|
|
|
do_update_pointer_accel_profile (input_settings, settings,
|
|
device, profile);
|
|
}
|
|
}
|
|
}
|
|
|
|
static GSettings *
|
|
get_settings_for_device_type (MetaInputSettings *input_settings,
|
|
ClutterInputDeviceType type)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
switch (type)
|
|
{
|
|
case CLUTTER_POINTER_DEVICE:
|
|
return priv->mouse_settings;
|
|
case CLUTTER_TOUCHPAD_DEVICE:
|
|
return priv->touchpad_settings;
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_device_speed (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
GSettings *settings;
|
|
ConfigDoubleFunc func;
|
|
const gchar *key = "speed";
|
|
|
|
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_speed;
|
|
|
|
if (device)
|
|
{
|
|
settings = get_settings_for_device_type (input_settings,
|
|
clutter_input_device_get_device_type (device));
|
|
if (!settings)
|
|
return;
|
|
|
|
settings_device_set_double_setting (input_settings, device, func,
|
|
g_settings_get_double (settings, key));
|
|
}
|
|
else
|
|
{
|
|
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
|
|
settings_set_double_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
|
|
g_settings_get_double (settings, key));
|
|
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
|
|
settings_set_double_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
|
|
g_settings_get_double (settings, key));
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_device_natural_scroll (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
GSettings *settings;
|
|
ConfigBoolFunc func;
|
|
const gchar *key = "natural-scroll";
|
|
|
|
func = META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_invert_scroll;
|
|
|
|
if (device)
|
|
{
|
|
settings = get_settings_for_device_type (input_settings,
|
|
clutter_input_device_get_device_type (device));
|
|
if (!settings)
|
|
return;
|
|
|
|
settings_device_set_bool_setting (input_settings, device, func,
|
|
g_settings_get_boolean (settings, key));
|
|
}
|
|
else
|
|
{
|
|
settings = get_settings_for_device_type (input_settings, CLUTTER_POINTER_DEVICE);
|
|
settings_set_bool_setting (input_settings, CLUTTER_POINTER_DEVICE, func,
|
|
g_settings_get_boolean (settings, key));
|
|
settings = get_settings_for_device_type (input_settings, CLUTTER_TOUCHPAD_DEVICE);
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, func,
|
|
g_settings_get_boolean (settings, key));
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_disable_while_typing (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
GSettings *settings;
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean enabled;
|
|
const gchar *key = "disable-while-typing";
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
enabled = g_settings_get_boolean (priv->touchpad_settings, key);
|
|
|
|
if (device)
|
|
{
|
|
settings = get_settings_for_device_type (input_settings,
|
|
clutter_input_device_get_device_type (device));
|
|
|
|
if (!settings)
|
|
return;
|
|
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_disable_while_typing,
|
|
enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
input_settings_class->set_disable_while_typing,
|
|
enabled);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_tap_enabled (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean enabled;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click");
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_tap_enabled,
|
|
enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
input_settings_class->set_tap_enabled,
|
|
enabled);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_tap_and_drag_enabled (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean enabled;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag");
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_tap_and_drag_enabled,
|
|
enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
input_settings_class->set_tap_and_drag_enabled,
|
|
enabled);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_edge_scroll (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
gboolean edge_scroll_enabled;
|
|
gboolean two_finger_scroll_enabled;
|
|
gboolean two_finger_scroll_available;
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled");
|
|
two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
|
|
two_finger_scroll_available = g_hash_table_size (priv->two_finger_devices) > 0;
|
|
|
|
/* If both are enabled we prefer two finger. */
|
|
if (edge_scroll_enabled && two_finger_scroll_enabled && two_finger_scroll_available)
|
|
edge_scroll_enabled = FALSE;
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_edge_scroll,
|
|
edge_scroll_enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
(ConfigBoolFunc) input_settings_class->set_edge_scroll,
|
|
edge_scroll_enabled);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_two_finger_scroll (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
gboolean two_finger_scroll_enabled;
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
|
|
|
|
/* Disable edge since they can't both be set. */
|
|
if (two_finger_scroll_enabled)
|
|
update_touchpad_edge_scroll (input_settings, device);
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_two_finger_scroll,
|
|
two_finger_scroll_enabled);
|
|
}
|
|
else
|
|
{
|
|
settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
(ConfigBoolFunc) input_settings_class->set_two_finger_scroll,
|
|
two_finger_scroll_enabled);
|
|
}
|
|
|
|
/* Edge might have been disabled because two finger was on. */
|
|
if (!two_finger_scroll_enabled)
|
|
update_touchpad_edge_scroll (input_settings, device);
|
|
}
|
|
|
|
static void
|
|
update_touchpad_click_method (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GDesktopTouchpadClickMethod method;
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
method = g_settings_get_enum (priv->touchpad_settings, "click-method");
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_uint_setting (input_settings, device,
|
|
input_settings_class->set_click_method,
|
|
method);
|
|
}
|
|
else
|
|
{
|
|
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
(ConfigUintFunc) input_settings_class->set_click_method,
|
|
method);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_touchpad_send_events (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
GDesktopDeviceSendEvents mode;
|
|
|
|
if (device &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
mode = g_settings_get_enum (priv->touchpad_settings, "send-events");
|
|
|
|
if (device)
|
|
{
|
|
settings_device_set_uint_setting (input_settings, device,
|
|
input_settings_class->set_send_events,
|
|
mode);
|
|
}
|
|
else
|
|
{
|
|
settings_set_uint_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE,
|
|
input_settings_class->set_send_events,
|
|
mode);
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_trackball_scroll_button (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
guint button;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
|
|
if (device && !input_settings_class->is_trackball_device (input_settings, device))
|
|
return;
|
|
|
|
/* This key is 'i' in the schema but it also specifies a minimum
|
|
* range of 0 so the cast here is safe. */
|
|
button = (guint) g_settings_get_int (priv->trackball_settings, "scroll-wheel-emulation-button");
|
|
|
|
if (device)
|
|
{
|
|
input_settings_class->set_scroll_button (input_settings, device, button);
|
|
}
|
|
else if (!device)
|
|
{
|
|
const GSList *devices;
|
|
|
|
devices = clutter_device_manager_peek_devices (priv->device_manager);
|
|
|
|
while (devices)
|
|
{
|
|
device = devices->data;
|
|
|
|
if (input_settings_class->is_trackball_device (input_settings, device))
|
|
input_settings_class->set_scroll_button (input_settings, device, button);
|
|
|
|
devices = devices->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
update_keyboard_repeat (MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
guint delay, interval;
|
|
gboolean repeat;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
repeat = g_settings_get_boolean (priv->keyboard_settings, "repeat");
|
|
delay = g_settings_get_uint (priv->keyboard_settings, "delay");
|
|
interval = g_settings_get_uint (priv->keyboard_settings, "repeat-interval");
|
|
|
|
delay = MAX (1, delay);
|
|
interval = MAX (1, interval);
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
input_settings_class->set_keyboard_repeat (input_settings,
|
|
repeat, delay, interval);
|
|
}
|
|
|
|
static MetaMonitor *
|
|
logical_monitor_find_monitor (MetaLogicalMonitor *logical_monitor,
|
|
const char *vendor,
|
|
const char *product,
|
|
const char *serial)
|
|
{
|
|
GList *monitors;
|
|
GList *l;
|
|
|
|
monitors = meta_logical_monitor_get_monitors (logical_monitor);
|
|
for (l = monitors; l; l = l->next)
|
|
{
|
|
MetaMonitor *monitor = l->data;
|
|
|
|
if (g_strcmp0 (meta_monitor_get_vendor (monitor), vendor) == 0 &&
|
|
g_strcmp0 (meta_monitor_get_product (monitor), product) == 0 &&
|
|
g_strcmp0 (meta_monitor_get_serial (monitor), serial) == 0)
|
|
return monitor;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_find_monitor (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device,
|
|
MetaMonitor **out_monitor,
|
|
MetaLogicalMonitor **out_logical_monitor)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
MetaMonitorManager *monitor_manager;
|
|
MetaMonitor *monitor;
|
|
guint n_values;
|
|
GList *logical_monitors;
|
|
GList *l;
|
|
gchar **edid;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
edid = g_settings_get_strv (settings, "output");
|
|
n_values = g_strv_length (edid);
|
|
|
|
if (n_values != 3)
|
|
{
|
|
g_warning ("EDID configuration for device '%s' "
|
|
"is incorrect, must have 3 values",
|
|
clutter_input_device_get_device_name (device));
|
|
goto out;
|
|
}
|
|
|
|
if (!*edid[0] && !*edid[1] && !*edid[2])
|
|
goto out;
|
|
|
|
monitor_manager = priv->monitor_manager;
|
|
logical_monitors =
|
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
|
for (l = logical_monitors; l; l = l->next)
|
|
{
|
|
MetaLogicalMonitor *logical_monitor = l->data;
|
|
|
|
monitor = logical_monitor_find_monitor (logical_monitor,
|
|
edid[0], edid[1], edid[2]);
|
|
if (monitor)
|
|
{
|
|
if (out_monitor)
|
|
*out_monitor = monitor;
|
|
if (out_logical_monitor)
|
|
*out_logical_monitor = logical_monitor;
|
|
break;
|
|
}
|
|
}
|
|
|
|
out:
|
|
g_strfreev (edid);
|
|
}
|
|
|
|
static gboolean
|
|
meta_input_settings_delegate_on_mapper (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
gboolean builtin = FALSE;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHSCREEN_DEVICE)
|
|
{
|
|
WacomDevice *wacom_device;
|
|
WacomIntegrationFlags flags = 0;
|
|
|
|
wacom_device =
|
|
meta_input_settings_get_tablet_wacom_device (input_settings,
|
|
device);
|
|
|
|
if (wacom_device)
|
|
{
|
|
flags = libwacom_get_integration_flags (wacom_device);
|
|
|
|
if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
|
|
WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
|
|
return FALSE;
|
|
|
|
builtin = (flags & WACOM_DEVICE_INTEGRATED_SYSTEM) != 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
meta_input_mapper_add_device (priv->input_mapper, device, builtin);
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
update_tablet_keep_aspect (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaLogicalMonitor *logical_monitor = NULL;
|
|
gboolean keep_aspect;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
|
return;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
{
|
|
WacomDevice *wacom_device;
|
|
|
|
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
|
device);
|
|
/* Keep aspect only makes sense in external tablets */
|
|
if (wacom_device &&
|
|
libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
|
|
if (clutter_input_device_get_mapping_mode (device) ==
|
|
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
|
{
|
|
keep_aspect = g_settings_get_boolean (settings, "keep-aspect");
|
|
meta_input_settings_find_monitor (input_settings, settings, device,
|
|
NULL, &logical_monitor);
|
|
}
|
|
else
|
|
{
|
|
keep_aspect = FALSE;
|
|
}
|
|
|
|
input_settings_class->set_tablet_keep_aspect (input_settings, device,
|
|
logical_monitor, keep_aspect);
|
|
}
|
|
|
|
static void
|
|
update_device_display (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
MetaInputSettingsPrivate *priv;
|
|
gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 };
|
|
MetaMonitor *monitor = NULL;
|
|
MetaLogicalMonitor *logical_monitor = NULL;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHSCREEN_DEVICE)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
|
|
/* If mapping is relative, the device can move on all displays */
|
|
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE ||
|
|
clutter_input_device_get_mapping_mode (device) ==
|
|
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
|
{
|
|
meta_input_settings_find_monitor (input_settings, settings, device,
|
|
&monitor, &logical_monitor);
|
|
if (monitor)
|
|
{
|
|
meta_input_mapper_remove_device (priv->input_mapper, device);
|
|
meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
|
|
monitor, logical_monitor, matrix);
|
|
}
|
|
else
|
|
{
|
|
if (meta_input_settings_delegate_on_mapper (input_settings, device))
|
|
return;
|
|
}
|
|
}
|
|
|
|
input_settings_class->set_matrix (input_settings, device, matrix);
|
|
|
|
/* Ensure the keep-aspect mapping is updated */
|
|
update_tablet_keep_aspect (input_settings, settings, device);
|
|
}
|
|
|
|
static void
|
|
update_tablet_mapping (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GDesktopTabletMapping mapping;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
|
return;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
{
|
|
WacomDevice *wacom_device;
|
|
|
|
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
|
device);
|
|
/* Tablet mapping only makes sense on external tablets */
|
|
if (wacom_device &&
|
|
(libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
mapping = g_settings_get_enum (settings, "mapping");
|
|
|
|
settings_device_set_uint_setting (input_settings, device,
|
|
input_settings_class->set_tablet_mapping,
|
|
mapping);
|
|
|
|
/* Relative mapping disables keep-aspect/display */
|
|
update_tablet_keep_aspect (input_settings, settings, device);
|
|
update_device_display (input_settings, settings, device);
|
|
}
|
|
|
|
static void
|
|
update_tablet_area (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GVariant *variant;
|
|
const gdouble *area;
|
|
gsize n_elems;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
|
return;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
{
|
|
WacomDevice *wacom_device;
|
|
|
|
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
|
device);
|
|
/* Tablet area only makes sense on system/display integrated tablets */
|
|
if (wacom_device &&
|
|
(libwacom_get_integration_flags (wacom_device) &
|
|
(WACOM_DEVICE_INTEGRATED_SYSTEM | WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
variant = g_settings_get_value (settings, "area");
|
|
|
|
area = g_variant_get_fixed_array (variant, &n_elems, sizeof (gdouble));
|
|
if (n_elems == 4)
|
|
{
|
|
input_settings_class->set_tablet_area (input_settings, device,
|
|
area[0], area[1],
|
|
area[2], area[3]);
|
|
}
|
|
|
|
g_variant_unref (variant);
|
|
}
|
|
|
|
static void
|
|
update_tablet_left_handed (MetaInputSettings *input_settings,
|
|
GSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
gboolean enabled;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PAD_DEVICE)
|
|
return;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
{
|
|
WacomDevice *wacom_device;
|
|
|
|
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
|
device);
|
|
/* Left handed mode only makes sense on external tablets */
|
|
if (wacom_device &&
|
|
(libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE))
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
enabled = g_settings_get_boolean (settings, "left-handed");
|
|
|
|
settings_device_set_bool_setting (input_settings, device,
|
|
input_settings_class->set_left_handed,
|
|
enabled);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_changed_cb (GSettings *settings,
|
|
const char *key,
|
|
gpointer user_data)
|
|
{
|
|
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
|
|
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
if (settings == priv->mouse_settings)
|
|
{
|
|
if (strcmp (key, "left-handed") == 0)
|
|
update_mouse_left_handed (input_settings, NULL);
|
|
else if (strcmp (key, "speed") == 0)
|
|
update_device_speed (input_settings, NULL);
|
|
else if (strcmp (key, "natural-scroll") == 0)
|
|
update_device_natural_scroll (input_settings, NULL);
|
|
else if (strcmp (key, "accel-profile") == 0)
|
|
update_pointer_accel_profile (input_settings, settings, NULL);
|
|
}
|
|
else if (settings == priv->touchpad_settings)
|
|
{
|
|
if (strcmp (key, "left-handed") == 0)
|
|
update_touchpad_left_handed (input_settings, NULL);
|
|
else if (strcmp (key, "speed") == 0)
|
|
update_device_speed (input_settings, NULL);
|
|
else if (strcmp (key, "natural-scroll") == 0)
|
|
update_device_natural_scroll (input_settings, NULL);
|
|
else if (strcmp (key, "tap-to-click") == 0)
|
|
update_touchpad_tap_enabled (input_settings, NULL);
|
|
else if (strcmp (key, "tap-and-drag") == 0)
|
|
update_touchpad_tap_and_drag_enabled (input_settings, NULL);
|
|
else if (strcmp(key, "disable-while-typing") == 0)
|
|
update_touchpad_disable_while_typing (input_settings, NULL);
|
|
else if (strcmp (key, "send-events") == 0)
|
|
update_touchpad_send_events (input_settings, NULL);
|
|
else if (strcmp (key, "edge-scrolling-enabled") == 0)
|
|
update_touchpad_edge_scroll (input_settings, NULL);
|
|
else if (strcmp (key, "two-finger-scrolling-enabled") == 0)
|
|
update_touchpad_two_finger_scroll (input_settings, NULL);
|
|
else if (strcmp (key, "click-method") == 0)
|
|
update_touchpad_click_method (input_settings, NULL);
|
|
}
|
|
else if (settings == priv->trackball_settings)
|
|
{
|
|
if (strcmp (key, "scroll-wheel-emulation-button") == 0)
|
|
update_trackball_scroll_button (input_settings, NULL);
|
|
else if (strcmp (key, "accel-profile") == 0)
|
|
update_pointer_accel_profile (input_settings, settings, NULL);
|
|
}
|
|
else if (settings == priv->keyboard_settings)
|
|
{
|
|
if (strcmp (key, "repeat") == 0 ||
|
|
strcmp (key, "repeat-interval") == 0 ||
|
|
strcmp (key, "delay") == 0)
|
|
update_keyboard_repeat (input_settings);
|
|
}
|
|
}
|
|
|
|
static void
|
|
mapped_device_changed_cb (GSettings *settings,
|
|
const gchar *key,
|
|
DeviceMappingInfo *info)
|
|
{
|
|
if (strcmp (key, "output") == 0)
|
|
update_device_display (info->input_settings, settings, info->device);
|
|
else if (strcmp (key, "mapping") == 0)
|
|
update_tablet_mapping (info->input_settings, settings, info->device);
|
|
else if (strcmp (key, "area") == 0)
|
|
update_tablet_area (info->input_settings, settings, info->device);
|
|
else if (strcmp (key, "keep-aspect") == 0)
|
|
update_tablet_keep_aspect (info->input_settings, settings, info->device);
|
|
else if (strcmp (key, "left-handed") == 0)
|
|
update_tablet_left_handed (info->input_settings, settings, info->device);
|
|
}
|
|
|
|
static void
|
|
apply_mappable_device_settings (MetaInputSettings *input_settings,
|
|
DeviceMappingInfo *info)
|
|
{
|
|
ClutterInputDeviceType device_type;
|
|
|
|
update_device_display (input_settings, info->settings, info->device);
|
|
device_type = clutter_input_device_get_device_type (info->device);
|
|
|
|
if (device_type == CLUTTER_TABLET_DEVICE ||
|
|
device_type == CLUTTER_PEN_DEVICE ||
|
|
device_type == CLUTTER_ERASER_DEVICE ||
|
|
device_type == CLUTTER_PAD_DEVICE)
|
|
{
|
|
update_tablet_mapping (input_settings, info->settings, info->device);
|
|
update_tablet_area (input_settings, info->settings, info->device);
|
|
update_tablet_keep_aspect (input_settings, info->settings, info->device);
|
|
update_tablet_left_handed (input_settings, info->settings, info->device);
|
|
}
|
|
}
|
|
|
|
struct _a11y_settings_flags_pair {
|
|
const char *name;
|
|
ClutterKeyboardA11yFlags flag;
|
|
} settings_flags_pair[] = {
|
|
{ "enable", CLUTTER_A11Y_KEYBOARD_ENABLED },
|
|
{ "timeout-enable", CLUTTER_A11Y_TIMEOUT_ENABLED },
|
|
{ "mousekeys-enable", CLUTTER_A11Y_MOUSE_KEYS_ENABLED },
|
|
{ "slowkeys-enable", CLUTTER_A11Y_SLOW_KEYS_ENABLED },
|
|
{ "slowkeys-beep-press", CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS },
|
|
{ "slowkeys-beep-accept", CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT },
|
|
{ "slowkeys-beep-reject", CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT },
|
|
{ "bouncekeys-enable", CLUTTER_A11Y_BOUNCE_KEYS_ENABLED },
|
|
{ "bouncekeys-beep-reject", CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT },
|
|
{ "togglekeys-enable", CLUTTER_A11Y_TOGGLE_KEYS_ENABLED },
|
|
{ "stickykeys-enable", CLUTTER_A11Y_STICKY_KEYS_ENABLED },
|
|
{ "stickykeys-modifier-beep", CLUTTER_A11Y_STICKY_KEYS_BEEP },
|
|
{ "stickykeys-two-key-off", CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF },
|
|
{ "feature-state-change-beep", CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP },
|
|
};
|
|
|
|
static void
|
|
load_keyboard_a11y_settings (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
|
ClutterKbdA11ySettings kbd_a11y_settings = { 0 };
|
|
ClutterInputDevice *core_keyboard;
|
|
guint i;
|
|
|
|
core_keyboard = clutter_device_manager_get_core_device (priv->device_manager, CLUTTER_KEYBOARD_DEVICE);
|
|
if (device && device != core_keyboard)
|
|
return;
|
|
|
|
kbd_a11y_settings.controls = 0;
|
|
for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++)
|
|
{
|
|
if (g_settings_get_boolean (priv->a11y_settings, settings_flags_pair[i].name))
|
|
kbd_a11y_settings.controls |= settings_flags_pair[i].flag;
|
|
}
|
|
|
|
kbd_a11y_settings.timeout_delay = g_settings_get_int (priv->a11y_settings,
|
|
"disable-timeout");
|
|
kbd_a11y_settings.slowkeys_delay = g_settings_get_int (priv->a11y_settings,
|
|
"slowkeys-delay");
|
|
kbd_a11y_settings.debounce_delay = g_settings_get_int (priv->a11y_settings,
|
|
"bouncekeys-delay");
|
|
kbd_a11y_settings.mousekeys_init_delay = g_settings_get_int (priv->a11y_settings,
|
|
"mousekeys-init-delay");
|
|
kbd_a11y_settings.mousekeys_max_speed = g_settings_get_int (priv->a11y_settings,
|
|
"mousekeys-max-speed");
|
|
kbd_a11y_settings.mousekeys_accel_time = g_settings_get_int (priv->a11y_settings,
|
|
"mousekeys-accel-time");
|
|
|
|
clutter_device_manager_set_kbd_a11y_settings (priv->device_manager, &kbd_a11y_settings);
|
|
}
|
|
|
|
static void
|
|
on_keyboard_a11y_settings_changed (ClutterDeviceManager *device_manager,
|
|
ClutterKeyboardA11yFlags new_flags,
|
|
ClutterKeyboardA11yFlags what_changed,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
|
guint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (settings_flags_pair); i++)
|
|
{
|
|
if (settings_flags_pair[i].flag & what_changed)
|
|
g_settings_set_boolean (priv->a11y_settings,
|
|
settings_flags_pair[i].name,
|
|
(new_flags & settings_flags_pair[i].flag) ? TRUE : FALSE);
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_input_a11y_settings_changed (GSettings *settings,
|
|
const char *key,
|
|
gpointer user_data)
|
|
{
|
|
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
|
|
|
|
load_keyboard_a11y_settings (input_settings, NULL);
|
|
}
|
|
|
|
static GSettings *
|
|
lookup_device_settings (ClutterInputDevice *device)
|
|
{
|
|
const gchar *group, *schema, *vendor, *product;
|
|
ClutterInputDeviceType type;
|
|
GSettings *settings;
|
|
gchar *path;
|
|
|
|
type = clutter_input_device_get_device_type (device);
|
|
|
|
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
|
|
{
|
|
group = "touchscreens";
|
|
schema = "org.gnome.desktop.peripherals.touchscreen";
|
|
}
|
|
else if (type == CLUTTER_TABLET_DEVICE ||
|
|
type == CLUTTER_PEN_DEVICE ||
|
|
type == CLUTTER_ERASER_DEVICE ||
|
|
type == CLUTTER_CURSOR_DEVICE ||
|
|
type == CLUTTER_PAD_DEVICE)
|
|
{
|
|
group = "tablets";
|
|
schema = "org.gnome.desktop.peripherals.tablet";
|
|
}
|
|
else
|
|
return NULL;
|
|
|
|
vendor = clutter_input_device_get_vendor_id (device);
|
|
product = clutter_input_device_get_product_id (device);
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
|
|
group, vendor, product);
|
|
|
|
settings = g_settings_new_with_path (schema, path);
|
|
g_free (path);
|
|
|
|
return settings;
|
|
}
|
|
|
|
static GSettings *
|
|
lookup_tool_settings (ClutterInputDeviceTool *tool,
|
|
ClutterInputDevice *device)
|
|
{
|
|
GSettings *tool_settings;
|
|
guint64 serial;
|
|
gchar *path;
|
|
|
|
tool_settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
|
|
if (tool_settings)
|
|
return tool_settings;
|
|
|
|
serial = clutter_input_device_tool_get_serial (tool);
|
|
|
|
/* The Wacom driver uses serial 1 for serial-less devices but 1 is not a
|
|
* real serial, so let's custom-case this */
|
|
if (serial == 0 || serial == 1)
|
|
{
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
|
|
clutter_input_device_get_vendor_id (device),
|
|
clutter_input_device_get_product_id (device));
|
|
}
|
|
else
|
|
{
|
|
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", serial);
|
|
}
|
|
|
|
tool_settings =
|
|
g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
|
|
path);
|
|
g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, tool_settings,
|
|
(GDestroyNotify) g_object_unref);
|
|
g_free (path);
|
|
|
|
return tool_settings;
|
|
}
|
|
|
|
static GSettings *
|
|
lookup_pad_action_settings (ClutterInputDevice *device,
|
|
MetaPadActionType action,
|
|
guint number,
|
|
MetaPadDirection direction,
|
|
gint mode)
|
|
{
|
|
const gchar *vendor, *product, *action_type, *detail_type = NULL;
|
|
GSettings *settings;
|
|
GString *path;
|
|
gchar action_label;
|
|
|
|
vendor = clutter_input_device_get_vendor_id (device);
|
|
product = clutter_input_device_get_product_id (device);
|
|
|
|
action_label = 'A' + number;
|
|
|
|
switch (action)
|
|
{
|
|
case META_PAD_ACTION_BUTTON:
|
|
action_type = "button";
|
|
break;
|
|
case META_PAD_ACTION_RING:
|
|
g_assert (direction == META_PAD_DIRECTION_CW ||
|
|
direction == META_PAD_DIRECTION_CCW);
|
|
action_type = "ring";
|
|
detail_type = (direction == META_PAD_DIRECTION_CW) ? "cw" : "ccw";
|
|
break;
|
|
case META_PAD_ACTION_STRIP:
|
|
g_assert (direction == META_PAD_DIRECTION_UP ||
|
|
direction == META_PAD_DIRECTION_DOWN);
|
|
action_type = "strip";
|
|
detail_type = (direction == META_PAD_DIRECTION_UP) ? "up" : "down";
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
|
|
path = g_string_new (NULL);
|
|
g_string_append_printf (path, "/org/gnome/desktop/peripherals/tablets/%s:%s/%s%c",
|
|
vendor, product, action_type, action_label);
|
|
|
|
if (detail_type)
|
|
g_string_append_printf (path, "-%s", detail_type);
|
|
|
|
if (mode >= 0)
|
|
g_string_append_printf (path, "-mode-%d", mode);
|
|
|
|
g_string_append_c (path, '/');
|
|
|
|
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
|
|
path->str);
|
|
g_string_free (path, TRUE);
|
|
|
|
return settings;
|
|
}
|
|
|
|
static void
|
|
monitors_changed_cb (MetaMonitorManager *monitor_manager,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
ClutterInputDevice *device;
|
|
DeviceMappingInfo *info;
|
|
GHashTableIter iter;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
g_hash_table_iter_init (&iter, priv->mappable_devices);
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &device,
|
|
(gpointer *) &info))
|
|
update_device_display (input_settings, info->settings, device);
|
|
}
|
|
|
|
static void
|
|
input_mapper_device_mapped_cb (MetaInputMapper *mapper,
|
|
ClutterInputDevice *device,
|
|
MetaLogicalMonitor *logical_monitor,
|
|
MetaMonitor *monitor,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
float matrix[6] = { 1, 0, 0, 0, 1, 0 };
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
if (monitor && logical_monitor)
|
|
{
|
|
meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
|
|
monitor, logical_monitor,
|
|
matrix);
|
|
}
|
|
|
|
META_INPUT_SETTINGS_GET_CLASS (input_settings)->set_matrix (input_settings,
|
|
device, matrix);
|
|
}
|
|
|
|
static void
|
|
device_mapping_info_free (DeviceMappingInfo *info)
|
|
{
|
|
#ifdef HAVE_LIBWACOM
|
|
if (info->wacom_device)
|
|
libwacom_destroy (info->wacom_device);
|
|
#endif
|
|
g_signal_handler_disconnect (info->settings, info->changed_id);
|
|
g_object_unref (info->settings);
|
|
g_free (info->group_modes);
|
|
g_slice_free (DeviceMappingInfo, info);
|
|
}
|
|
|
|
static gboolean
|
|
check_add_mappable_device (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
ClutterInputDeviceType device_type;
|
|
GSettings *settings;
|
|
|
|
device_type = clutter_input_device_get_device_type (device);
|
|
|
|
if ((device_type == CLUTTER_TABLET_DEVICE ||
|
|
device_type == CLUTTER_PEN_DEVICE ||
|
|
device_type == CLUTTER_ERASER_DEVICE ||
|
|
device_type == CLUTTER_PAD_DEVICE) &&
|
|
g_getenv ("MUTTER_DISABLE_WACOM_CONFIGURATION") != NULL)
|
|
return FALSE;
|
|
|
|
settings = lookup_device_settings (device);
|
|
|
|
if (!settings)
|
|
return FALSE;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
info = g_slice_new0 (DeviceMappingInfo);
|
|
info->input_settings = input_settings;
|
|
info->device = device;
|
|
info->settings = settings;
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
if (device_type == CLUTTER_TABLET_DEVICE ||
|
|
device_type == CLUTTER_PAD_DEVICE)
|
|
{
|
|
WacomError *error = libwacom_error_new ();
|
|
|
|
info->wacom_device = libwacom_new_from_path (priv->wacom_db,
|
|
clutter_input_device_get_device_node (device),
|
|
WFALLBACK_NONE, error);
|
|
if (!info->wacom_device)
|
|
{
|
|
g_warning ("Could not get tablet information for '%s': %s",
|
|
clutter_input_device_get_device_name (device),
|
|
libwacom_error_get_message (error));
|
|
}
|
|
|
|
libwacom_error_free (&error);
|
|
}
|
|
#endif
|
|
|
|
if (device_type == CLUTTER_PAD_DEVICE)
|
|
{
|
|
info->group_modes =
|
|
g_new0 (guint, clutter_input_device_get_n_mode_groups (device));
|
|
}
|
|
|
|
info->changed_id = g_signal_connect (settings, "changed",
|
|
G_CALLBACK (mapped_device_changed_cb),
|
|
info);
|
|
|
|
g_hash_table_insert (priv->mappable_devices, device, info);
|
|
|
|
apply_mappable_device_settings (input_settings, info);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
apply_device_settings (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv =
|
|
meta_input_settings_get_instance_private (input_settings);
|
|
|
|
update_device_speed (input_settings, device);
|
|
update_device_natural_scroll (input_settings, device);
|
|
|
|
update_mouse_left_handed (input_settings, device);
|
|
update_pointer_accel_profile (input_settings,
|
|
priv->mouse_settings,
|
|
device);
|
|
|
|
update_touchpad_left_handed (input_settings, device);
|
|
update_touchpad_tap_enabled (input_settings, device);
|
|
update_touchpad_tap_and_drag_enabled (input_settings, device);
|
|
update_touchpad_disable_while_typing (input_settings, device);
|
|
update_touchpad_send_events (input_settings, device);
|
|
update_touchpad_two_finger_scroll (input_settings, device);
|
|
update_touchpad_edge_scroll (input_settings, device);
|
|
update_touchpad_click_method (input_settings, device);
|
|
|
|
update_trackball_scroll_button (input_settings, device);
|
|
update_pointer_accel_profile (input_settings,
|
|
priv->trackball_settings,
|
|
device);
|
|
load_keyboard_a11y_settings (input_settings, device);
|
|
}
|
|
|
|
static void
|
|
update_stylus_pressure (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ClutterInputDeviceTool *tool)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GSettings *tool_settings;
|
|
const gint32 *curve;
|
|
GVariant *variant;
|
|
gsize n_elems;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
|
return;
|
|
|
|
if (!tool)
|
|
return;
|
|
|
|
tool_settings = lookup_tool_settings (tool, device);
|
|
|
|
if (clutter_input_device_tool_get_tool_type (tool) ==
|
|
CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
|
variant = g_settings_get_value (tool_settings, "eraser-pressure-curve");
|
|
else
|
|
variant = g_settings_get_value (tool_settings, "pressure-curve");
|
|
|
|
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
|
if (n_elems != 4)
|
|
return;
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
input_settings_class->set_stylus_pressure (input_settings, device, tool, curve);
|
|
}
|
|
|
|
static void
|
|
update_stylus_buttonmap (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ClutterInputDeviceTool *tool)
|
|
{
|
|
MetaInputSettingsClass *input_settings_class;
|
|
GDesktopStylusButtonAction primary, secondary, tertiary;
|
|
GSettings *tool_settings;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
|
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
|
return;
|
|
|
|
if (!tool)
|
|
return;
|
|
|
|
tool_settings = lookup_tool_settings (tool, device);
|
|
|
|
primary = g_settings_get_enum (tool_settings, "button-action");
|
|
secondary = g_settings_get_enum (tool_settings, "secondary-button-action");
|
|
tertiary = g_settings_get_enum (tool_settings, "tertiary-button-action");
|
|
|
|
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
input_settings_class->set_stylus_button_map (input_settings, device, tool,
|
|
primary, secondary, tertiary);
|
|
}
|
|
|
|
static void
|
|
apply_stylus_settings (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ClutterInputDeviceTool *tool)
|
|
{
|
|
update_stylus_pressure (input_settings, device, tool);
|
|
update_stylus_buttonmap (input_settings, device, tool);
|
|
}
|
|
|
|
static void
|
|
evaluate_two_finger_scrolling (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsClass *klass;
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE)
|
|
return;
|
|
|
|
klass = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
if (klass->has_two_finger_scroll (input_settings, device))
|
|
g_hash_table_add (priv->two_finger_devices, device);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
|
|
ClutterInputDevice *device,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
|
|
return;
|
|
|
|
evaluate_two_finger_scrolling (input_settings, device);
|
|
|
|
apply_device_settings (input_settings, device);
|
|
check_add_mappable_device (input_settings, device);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_device_removed (ClutterDeviceManager *device_manager,
|
|
ClutterInputDevice *device,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
meta_input_mapper_remove_device (priv->input_mapper, device);
|
|
g_hash_table_remove (priv->mappable_devices, device);
|
|
g_hash_table_remove (priv->current_tools, device);
|
|
|
|
if (g_hash_table_remove (priv->two_finger_devices, device) &&
|
|
g_hash_table_size (priv->two_finger_devices) == 0)
|
|
apply_device_settings (input_settings, NULL);
|
|
}
|
|
|
|
static void
|
|
current_tool_changed_cb (GSettings *settings,
|
|
const char *key,
|
|
gpointer user_data)
|
|
{
|
|
CurrentToolInfo *info = user_data;
|
|
|
|
apply_stylus_settings (info->input_settings, info->device, info->tool);
|
|
}
|
|
|
|
static CurrentToolInfo *
|
|
current_tool_info_new (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device,
|
|
ClutterInputDeviceTool *tool)
|
|
{
|
|
CurrentToolInfo *info;
|
|
|
|
info = g_new0 (CurrentToolInfo, 1);
|
|
info->input_settings = input_settings;
|
|
info->device = device;
|
|
info->tool = tool;
|
|
info->settings = lookup_tool_settings (tool, device);
|
|
info->changed_id =
|
|
g_signal_connect (info->settings, "changed",
|
|
G_CALLBACK (current_tool_changed_cb),
|
|
info);
|
|
return info;
|
|
}
|
|
|
|
static void
|
|
current_tool_info_free (CurrentToolInfo *info)
|
|
{
|
|
g_signal_handler_disconnect (info->settings, info->changed_id);
|
|
g_free (info);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_tool_changed (ClutterDeviceManager *device_manager,
|
|
ClutterInputDevice *device,
|
|
ClutterInputDeviceTool *tool,
|
|
MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
if (tool)
|
|
{
|
|
CurrentToolInfo *current_tool;
|
|
|
|
current_tool = current_tool_info_new (input_settings, device, tool);
|
|
g_hash_table_insert (priv->current_tools, device, current_tool);
|
|
apply_stylus_settings (input_settings, device, tool);
|
|
}
|
|
else
|
|
{
|
|
g_hash_table_remove (priv->current_tools, device);
|
|
}
|
|
}
|
|
|
|
static void
|
|
check_mappable_devices (MetaInputSettings *input_settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
const GSList *devices, *l;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
devices = clutter_device_manager_peek_devices (priv->device_manager);
|
|
|
|
for (l = devices; l; l = l->next)
|
|
{
|
|
ClutterInputDevice *device = l->data;
|
|
|
|
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER)
|
|
continue;
|
|
|
|
check_add_mappable_device (input_settings, device);
|
|
}
|
|
}
|
|
|
|
static void
|
|
power_save_mode_changed_cb (MetaMonitorManager *manager,
|
|
gpointer user_data)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
ClutterInputDevice *device;
|
|
MetaLogicalMonitor *logical_monitor;
|
|
MetaMonitor *builtin;
|
|
MetaPowerSave power_save_mode;
|
|
gboolean on;
|
|
|
|
power_save_mode = meta_monitor_manager_get_power_save_mode (manager);
|
|
on = power_save_mode == META_POWER_SAVE_ON;
|
|
priv = meta_input_settings_get_instance_private (user_data);
|
|
|
|
builtin = meta_monitor_manager_get_laptop_panel (manager);
|
|
if (!builtin)
|
|
return;
|
|
|
|
logical_monitor = meta_monitor_get_logical_monitor (builtin);
|
|
if (!logical_monitor)
|
|
return;
|
|
|
|
device =
|
|
meta_input_mapper_get_logical_monitor_device (priv->input_mapper,
|
|
logical_monitor,
|
|
CLUTTER_TOUCHSCREEN_DEVICE);
|
|
if (!device)
|
|
return;
|
|
|
|
clutter_input_device_set_enabled (device, on);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_constructed (GObject *object)
|
|
{
|
|
MetaInputSettings *input_settings = META_INPUT_SETTINGS (object);
|
|
GSList *devices, *d;
|
|
|
|
devices = meta_input_settings_get_devices (input_settings, CLUTTER_TOUCHPAD_DEVICE);
|
|
for (d = devices; d; d = d->next)
|
|
evaluate_two_finger_scrolling (input_settings, d->data);
|
|
|
|
g_slist_free (devices);
|
|
|
|
apply_device_settings (input_settings, NULL);
|
|
update_keyboard_repeat (input_settings);
|
|
check_mappable_devices (input_settings);
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_class_init (MetaInputSettingsClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
object_class->dispose = meta_input_settings_dispose;
|
|
object_class->constructed = meta_input_settings_constructed;
|
|
|
|
quark_tool_settings =
|
|
g_quark_from_static_string ("meta-input-settings-tool-settings");
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_init (MetaInputSettings *settings)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
priv->device_manager = clutter_device_manager_get_default ();
|
|
g_signal_connect (priv->device_manager, "device-added",
|
|
G_CALLBACK (meta_input_settings_device_added), settings);
|
|
g_signal_connect (priv->device_manager, "device-removed",
|
|
G_CALLBACK (meta_input_settings_device_removed), settings);
|
|
g_signal_connect (priv->device_manager, "tool-changed",
|
|
G_CALLBACK (meta_input_settings_tool_changed), settings);
|
|
|
|
priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
|
|
g_signal_connect (priv->mouse_settings, "changed",
|
|
G_CALLBACK (meta_input_settings_changed_cb), settings);
|
|
|
|
priv->touchpad_settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
|
|
g_signal_connect (priv->touchpad_settings, "changed",
|
|
G_CALLBACK (meta_input_settings_changed_cb), settings);
|
|
|
|
priv->trackball_settings = g_settings_new ("org.gnome.desktop.peripherals.trackball");
|
|
g_signal_connect (priv->trackball_settings, "changed",
|
|
G_CALLBACK (meta_input_settings_changed_cb), settings);
|
|
|
|
priv->keyboard_settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
|
|
g_signal_connect (priv->keyboard_settings, "changed",
|
|
G_CALLBACK (meta_input_settings_changed_cb), settings);
|
|
|
|
priv->gsd_settings = g_settings_new ("org.gnome.settings-daemon.peripherals.mouse");
|
|
|
|
g_settings_bind (priv->gsd_settings, "double-click",
|
|
clutter_settings_get_default(), "double-click-time",
|
|
G_SETTINGS_BIND_GET);
|
|
|
|
priv->a11y_settings = g_settings_new ("org.gnome.desktop.a11y.keyboard");
|
|
g_signal_connect (priv->a11y_settings, "changed",
|
|
G_CALLBACK (meta_input_a11y_settings_changed), settings);
|
|
g_signal_connect (priv->device_manager, "kbd-a11y-flags-changed",
|
|
G_CALLBACK (on_keyboard_a11y_settings_changed), settings);
|
|
|
|
priv->mappable_devices =
|
|
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free);
|
|
|
|
priv->current_tools =
|
|
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) current_tool_info_free);
|
|
|
|
priv->monitor_manager = g_object_ref (meta_monitor_manager_get ());
|
|
g_signal_connect (priv->monitor_manager, "monitors-changed-internal",
|
|
G_CALLBACK (monitors_changed_cb), settings);
|
|
g_signal_connect (priv->monitor_manager, "power-save-mode-changed",
|
|
G_CALLBACK (power_save_mode_changed_cb), settings);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
priv->wacom_db = libwacom_database_new ();
|
|
if (!priv->wacom_db)
|
|
{
|
|
g_warning ("Could not create database of Wacom devices, "
|
|
"expect tablets to misbehave");
|
|
}
|
|
#endif
|
|
|
|
priv->two_finger_devices = g_hash_table_new (NULL, NULL);
|
|
|
|
priv->input_mapper = meta_input_mapper_new ();
|
|
g_signal_connect (priv->input_mapper, "device-mapped",
|
|
G_CALLBACK (input_mapper_device_mapped_cb), settings);
|
|
}
|
|
|
|
GSettings *
|
|
meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, device);
|
|
|
|
return info ? g_object_ref (info->settings) : NULL;
|
|
}
|
|
|
|
MetaLogicalMonitor *
|
|
meta_input_settings_get_tablet_logical_monitor (MetaInputSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaLogicalMonitor *logical_monitor = NULL;
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, device);
|
|
if (!info)
|
|
return NULL;
|
|
|
|
meta_input_settings_find_monitor (settings, info->settings, device,
|
|
NULL, &logical_monitor);
|
|
return logical_monitor;
|
|
}
|
|
|
|
GDesktopTabletMapping
|
|
meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings),
|
|
G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
|
|
G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, device);
|
|
g_return_val_if_fail (info != NULL, G_DESKTOP_TABLET_MAPPING_ABSOLUTE);
|
|
|
|
return g_settings_get_enum (info->settings, "mapping");
|
|
}
|
|
|
|
static GDesktopPadButtonAction
|
|
meta_input_settings_get_pad_button_action (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
guint button)
|
|
{
|
|
GDesktopPadButtonAction action;
|
|
GSettings *settings;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
|
|
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
|
button, META_PAD_DIRECTION_NONE, -1);
|
|
action = g_settings_get_enum (settings, "action");
|
|
g_object_unref (settings);
|
|
|
|
return action;
|
|
}
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
WacomDevice *
|
|
meta_input_settings_get_tablet_wacom_device (MetaInputSettings *settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
|
|
|
priv = meta_input_settings_get_instance_private (settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, device);
|
|
g_return_val_if_fail (info != NULL, NULL);
|
|
|
|
return info->wacom_device;
|
|
}
|
|
#endif /* HAVE_LIBWACOM */
|
|
|
|
static gboolean
|
|
cycle_logical_monitors (MetaInputSettings *settings,
|
|
MetaLogicalMonitor *current_logical_monitor,
|
|
MetaLogicalMonitor **next_logical_monitor)
|
|
{
|
|
MetaInputSettingsPrivate *priv =
|
|
meta_input_settings_get_instance_private (settings);
|
|
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
|
GList *logical_monitors;
|
|
|
|
/* We cycle between:
|
|
* - the span of all monitors (current_output = NULL)
|
|
* - each monitor individually.
|
|
*/
|
|
|
|
logical_monitors =
|
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
|
|
|
if (!current_logical_monitor)
|
|
{
|
|
*next_logical_monitor = logical_monitors->data;
|
|
}
|
|
else
|
|
{
|
|
GList *l;
|
|
|
|
l = g_list_find (logical_monitors, current_logical_monitor);
|
|
if (l->next)
|
|
*next_logical_monitor = l->next->data;
|
|
else
|
|
*next_logical_monitor = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_cycle_tablet_output (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *device)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
MetaLogicalMonitor *logical_monitor = NULL;
|
|
const gchar *edid[4] = { 0 }, *pretty_name = NULL;
|
|
|
|
g_return_if_fail (META_IS_INPUT_SETTINGS (input_settings));
|
|
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
|
g_return_if_fail (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE ||
|
|
clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE);
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, device);
|
|
g_return_if_fail (info != NULL);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
if (info->wacom_device)
|
|
{
|
|
/* Output rotation only makes sense on external tablets */
|
|
if (libwacom_get_integration_flags (info->wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)
|
|
return;
|
|
|
|
pretty_name = libwacom_get_name (info->wacom_device);
|
|
}
|
|
#endif
|
|
|
|
meta_input_settings_find_monitor (input_settings, info->settings, device,
|
|
NULL, &logical_monitor);
|
|
|
|
if (!cycle_logical_monitors (input_settings,
|
|
logical_monitor,
|
|
&logical_monitor))
|
|
return;
|
|
|
|
if (logical_monitor)
|
|
{
|
|
MetaMonitor *monitor;
|
|
|
|
/* Pick an arbitrary monitor in the logical monitor to represent it. */
|
|
monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
|
edid[0] = meta_monitor_get_vendor (monitor);
|
|
edid[1] = meta_monitor_get_product (monitor);
|
|
edid[2] = meta_monitor_get_serial (monitor);
|
|
}
|
|
else
|
|
{
|
|
edid[0] = "";
|
|
edid[1] = "";
|
|
edid[2] = "";
|
|
}
|
|
g_settings_set_strv (info->settings, "output", edid);
|
|
|
|
meta_display_show_tablet_mapping_notification (meta_get_display (),
|
|
device, pretty_name);
|
|
}
|
|
|
|
static void
|
|
emulate_modifiers (ClutterVirtualInputDevice *device,
|
|
ClutterModifierType mods,
|
|
ClutterKeyState state)
|
|
{
|
|
guint i;
|
|
struct {
|
|
ClutterModifierType mod;
|
|
guint keyval;
|
|
} mod_map[] = {
|
|
{ CLUTTER_SHIFT_MASK, CLUTTER_KEY_Shift_L },
|
|
{ CLUTTER_CONTROL_MASK, CLUTTER_KEY_Control_L },
|
|
{ CLUTTER_MOD1_MASK, CLUTTER_KEY_Meta_L }
|
|
};
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (mod_map); i++)
|
|
{
|
|
if ((mods & mod_map[i].mod) == 0)
|
|
continue;
|
|
|
|
clutter_virtual_input_device_notify_keyval (device,
|
|
clutter_get_current_event_time (),
|
|
mod_map[i].keyval, state);
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_input_settings_emulate_keybinding (MetaInputSettings *input_settings,
|
|
const gchar *accel,
|
|
gboolean is_press)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
ClutterKeyState state;
|
|
guint key, mods;
|
|
|
|
if (!accel || !*accel)
|
|
return;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
|
|
/* FIXME: This is appalling */
|
|
gtk_accelerator_parse (accel, &key, &mods);
|
|
|
|
if (!priv->virtual_pad_keyboard)
|
|
{
|
|
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
|
|
|
priv->virtual_pad_keyboard =
|
|
clutter_device_manager_create_virtual_device (manager,
|
|
CLUTTER_KEYBOARD_DEVICE);
|
|
}
|
|
|
|
state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
|
|
|
|
if (is_press)
|
|
emulate_modifiers (priv->virtual_pad_keyboard, mods, state);
|
|
|
|
clutter_virtual_input_device_notify_keyval (priv->virtual_pad_keyboard,
|
|
clutter_get_current_event_time (),
|
|
key, state);
|
|
if (!is_press)
|
|
emulate_modifiers (priv->virtual_pad_keyboard, mods, state);
|
|
}
|
|
|
|
gboolean
|
|
meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
guint button)
|
|
{
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), FALSE);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
|
|
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
|
CLUTTER_PAD_DEVICE, FALSE);
|
|
|
|
return (meta_input_settings_get_pad_button_action (input_settings, pad, button) !=
|
|
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
|
}
|
|
|
|
static gboolean
|
|
meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
const ClutterPadButtonEvent *event)
|
|
{
|
|
GDesktopPadButtonAction action;
|
|
gint button, group, mode;
|
|
gboolean is_press;
|
|
GSettings *settings;
|
|
gchar *accel;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), FALSE);
|
|
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
|
event->type == CLUTTER_PAD_BUTTON_RELEASE, FALSE);
|
|
|
|
button = event->button;
|
|
mode = event->mode;
|
|
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
|
is_press = event->type == CLUTTER_PAD_BUTTON_PRESS;
|
|
|
|
if (is_press && group >= 0)
|
|
{
|
|
guint n_modes = clutter_input_device_get_group_n_modes (pad, group);
|
|
const gchar *pretty_name = NULL;
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, pad);
|
|
|
|
#ifdef HAVE_LIBWACOM
|
|
if (info && info->wacom_device)
|
|
pretty_name = libwacom_get_name (info->wacom_device);
|
|
#endif
|
|
meta_display_notify_pad_group_switch (meta_get_display (), pad,
|
|
pretty_name, group, mode, n_modes);
|
|
info->group_modes[group] = mode;
|
|
}
|
|
|
|
action = meta_input_settings_get_pad_button_action (input_settings, pad, button);
|
|
|
|
switch (action)
|
|
{
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
|
if (is_press)
|
|
meta_input_settings_cycle_tablet_output (input_settings, pad);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
|
if (is_press)
|
|
meta_display_request_pad_osd (meta_get_display (), pad, FALSE);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
|
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
|
button, META_PAD_DIRECTION_NONE, -1);
|
|
accel = g_settings_get_string (settings, "keybinding");
|
|
meta_input_settings_emulate_keybinding (input_settings, accel, is_press);
|
|
g_object_unref (settings);
|
|
g_free (accel);
|
|
return TRUE;
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
meta_input_settings_handle_pad_action (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
MetaPadActionType action,
|
|
guint number,
|
|
MetaPadDirection direction,
|
|
guint mode)
|
|
{
|
|
GSettings *settings;
|
|
gboolean handled = FALSE;
|
|
gchar *accel;
|
|
|
|
settings = lookup_pad_action_settings (pad, action, number, direction, mode);
|
|
accel = g_settings_get_string (settings, "keybinding");
|
|
|
|
if (accel && *accel)
|
|
{
|
|
meta_input_settings_emulate_keybinding (input_settings, accel, TRUE);
|
|
meta_input_settings_emulate_keybinding (input_settings, accel, FALSE);
|
|
handled = TRUE;
|
|
}
|
|
|
|
g_object_unref (settings);
|
|
g_free (accel);
|
|
|
|
return handled;
|
|
}
|
|
|
|
static gboolean
|
|
meta_input_settings_get_pad_action_direction (MetaInputSettings *input_settings,
|
|
const ClutterEvent *event,
|
|
MetaPadDirection *direction)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
ClutterInputDevice *pad = clutter_event_get_device (event);
|
|
MetaPadActionType pad_action;
|
|
gboolean has_direction = FALSE;
|
|
MetaPadDirection inc_dir, dec_dir;
|
|
guint number;
|
|
gdouble value;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
*direction = META_PAD_DIRECTION_NONE;
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_PAD_RING:
|
|
pad_action = META_PAD_ACTION_RING;
|
|
number = event->pad_ring.ring_number;
|
|
value = event->pad_ring.angle;
|
|
inc_dir = META_PAD_DIRECTION_CW;
|
|
dec_dir = META_PAD_DIRECTION_CCW;
|
|
break;
|
|
case CLUTTER_PAD_STRIP:
|
|
pad_action = META_PAD_ACTION_STRIP;
|
|
number = event->pad_strip.strip_number;
|
|
value = event->pad_strip.value;
|
|
inc_dir = META_PAD_DIRECTION_DOWN;
|
|
dec_dir = META_PAD_DIRECTION_UP;
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
if (priv->last_pad_action_info.pad == pad &&
|
|
priv->last_pad_action_info.action == pad_action &&
|
|
priv->last_pad_action_info.number == number &&
|
|
value >= 0 && priv->last_pad_action_info.value >= 0)
|
|
{
|
|
*direction = (value - priv->last_pad_action_info.value) > 0 ?
|
|
inc_dir : dec_dir;
|
|
has_direction = TRUE;
|
|
}
|
|
|
|
priv->last_pad_action_info.pad = pad;
|
|
priv->last_pad_action_info.action = pad_action;
|
|
priv->last_pad_action_info.number = number;
|
|
priv->last_pad_action_info.value = value;
|
|
return has_direction;
|
|
}
|
|
|
|
gboolean
|
|
meta_input_settings_handle_pad_event (MetaInputSettings *input_settings,
|
|
const ClutterEvent *event)
|
|
{
|
|
ClutterInputDevice *pad;
|
|
MetaPadDirection direction = META_PAD_DIRECTION_NONE;
|
|
|
|
pad = clutter_event_get_source_device ((ClutterEvent *) event);
|
|
|
|
switch (event->type)
|
|
{
|
|
case CLUTTER_PAD_BUTTON_PRESS:
|
|
case CLUTTER_PAD_BUTTON_RELEASE:
|
|
return meta_input_settings_handle_pad_button (input_settings, pad,
|
|
&event->pad_button);
|
|
case CLUTTER_PAD_RING:
|
|
if (!meta_input_settings_get_pad_action_direction (input_settings,
|
|
event, &direction))
|
|
return FALSE;
|
|
return meta_input_settings_handle_pad_action (input_settings, pad,
|
|
META_PAD_ACTION_RING,
|
|
event->pad_ring.ring_number,
|
|
direction,
|
|
event->pad_ring.mode);
|
|
case CLUTTER_PAD_STRIP:
|
|
if (!meta_input_settings_get_pad_action_direction (input_settings,
|
|
event, &direction))
|
|
return FALSE;
|
|
return meta_input_settings_handle_pad_action (input_settings, pad,
|
|
META_PAD_ACTION_STRIP,
|
|
event->pad_strip.strip_number,
|
|
direction,
|
|
event->pad_strip.mode);
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static gchar *
|
|
compose_directional_action_label (GSettings *direction1,
|
|
GSettings *direction2)
|
|
{
|
|
gchar *accel1, *accel2, *str = NULL;
|
|
|
|
accel1 = g_settings_get_string (direction1, "keybinding");
|
|
accel2 = g_settings_get_string (direction2, "keybinding");
|
|
|
|
if (accel1 && *accel1 && accel2 && *accel2)
|
|
str = g_strdup_printf ("%s / %s", accel1, accel2);
|
|
|
|
g_free (accel1);
|
|
g_free (accel2);
|
|
|
|
return str;
|
|
}
|
|
|
|
static gchar *
|
|
meta_input_settings_get_ring_label (MetaInputSettings *settings,
|
|
ClutterInputDevice *pad,
|
|
guint number,
|
|
guint mode)
|
|
{
|
|
GSettings *settings1, *settings2;
|
|
gchar *label;
|
|
|
|
/* We only allow keybinding actions with those */
|
|
settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
|
|
META_PAD_DIRECTION_CW, mode);
|
|
settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
|
|
META_PAD_DIRECTION_CCW, mode);
|
|
label = compose_directional_action_label (settings1, settings2);
|
|
g_object_unref (settings1);
|
|
g_object_unref (settings2);
|
|
|
|
return label;
|
|
}
|
|
|
|
static gchar *
|
|
meta_input_settings_get_strip_label (MetaInputSettings *settings,
|
|
ClutterInputDevice *pad,
|
|
guint number,
|
|
guint mode)
|
|
{
|
|
GSettings *settings1, *settings2;
|
|
gchar *label;
|
|
|
|
/* We only allow keybinding actions with those */
|
|
settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
|
|
META_PAD_DIRECTION_UP, mode);
|
|
settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
|
|
META_PAD_DIRECTION_DOWN, mode);
|
|
label = compose_directional_action_label (settings1, settings2);
|
|
g_object_unref (settings1);
|
|
g_object_unref (settings2);
|
|
|
|
return label;
|
|
}
|
|
|
|
static gchar *
|
|
meta_input_settings_get_button_label (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
guint button)
|
|
{
|
|
GDesktopPadButtonAction action;
|
|
gint group;
|
|
|
|
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), NULL);
|
|
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL);
|
|
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
|
CLUTTER_PAD_DEVICE, NULL);
|
|
|
|
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
|
|
|
if (group >= 0)
|
|
{
|
|
/* TRANSLATORS: This string refers to a button that switches between
|
|
* different modes.
|
|
*/
|
|
return g_strdup_printf (_("Mode Switch (Group %d)"), group);
|
|
}
|
|
|
|
action = meta_input_settings_get_pad_button_action (input_settings, pad, button);
|
|
|
|
switch (action)
|
|
{
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
|
{
|
|
GSettings *settings;
|
|
gchar *accel;
|
|
|
|
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
|
button, META_PAD_DIRECTION_NONE, -1);
|
|
accel = g_settings_get_string (settings, "keybinding");
|
|
g_object_unref (settings);
|
|
|
|
return accel;
|
|
}
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
|
/* TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
|
* mapping through the available outputs.
|
|
*/
|
|
return g_strdup (_("Switch monitor"));
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
|
return g_strdup (_("Show on-screen help"));
|
|
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static guint
|
|
get_current_pad_mode (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
MetaPadActionType action_type,
|
|
guint number)
|
|
{
|
|
MetaInputSettingsPrivate *priv;
|
|
DeviceMappingInfo *info;
|
|
guint group = 0, n_groups;
|
|
|
|
priv = meta_input_settings_get_instance_private (input_settings);
|
|
info = g_hash_table_lookup (priv->mappable_devices, pad);
|
|
n_groups = clutter_input_device_get_n_mode_groups (pad);
|
|
|
|
if (!info->group_modes || n_groups == 0)
|
|
return 0;
|
|
|
|
if (action_type == META_PAD_ACTION_RING ||
|
|
action_type == META_PAD_ACTION_STRIP)
|
|
{
|
|
/* Assume features are evenly distributed in groups */
|
|
group = number % n_groups;
|
|
}
|
|
|
|
return info->group_modes[group];
|
|
}
|
|
|
|
gchar *
|
|
meta_input_settings_get_pad_action_label (MetaInputSettings *input_settings,
|
|
ClutterInputDevice *pad,
|
|
MetaPadActionType action_type,
|
|
guint number)
|
|
{
|
|
guint mode;
|
|
|
|
switch (action_type)
|
|
{
|
|
case META_PAD_ACTION_BUTTON:
|
|
return meta_input_settings_get_button_label (input_settings, pad, number);
|
|
case META_PAD_ACTION_RING:
|
|
mode = get_current_pad_mode (input_settings, pad, action_type, number);
|
|
return meta_input_settings_get_ring_label (input_settings, pad,
|
|
number, mode);
|
|
case META_PAD_ACTION_STRIP:
|
|
mode = get_current_pad_mode (input_settings, pad, action_type, number);
|
|
return meta_input_settings_get_strip_label (input_settings, pad,
|
|
number, mode);
|
|
}
|
|
|
|
return NULL;
|
|
}
|