input-settings: Handle device-to-output mapping
For each device that can be mapped (touchscreens, tablets), the output will be fetched from settings and matched with the currently connected ones. If a match is found, the device matrix will be found out from the output configuration and set on the device. This is also updated both individually for newly connected devices, and collectively on output configuration changes. https://bugzilla.gnome.org/show_bug.cgi?id=739397
This commit is contained in:
parent
71c4138933
commit
1dea1813b1
1 changed files with 214 additions and 0 deletions
|
@ -41,14 +41,27 @@
|
|||
#include <meta/util.h>
|
||||
|
||||
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
|
||||
typedef struct _DeviceMappingInfo DeviceMappingInfo;
|
||||
|
||||
struct _DeviceMappingInfo
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsPrivate
|
||||
{
|
||||
ClutterDeviceManager *device_manager;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
guint monitors_changed_id;
|
||||
|
||||
GSettings *mouse_settings;
|
||||
GSettings *touchpad_settings;
|
||||
GSettings *trackball_settings;
|
||||
GSettings *keyboard_settings;
|
||||
|
||||
GHashTable *mappable_devices;
|
||||
};
|
||||
|
||||
typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings,
|
||||
|
@ -98,6 +111,17 @@ meta_input_settings_dispose (GObject *object)
|
|||
g_clear_object (&priv->touchpad_settings);
|
||||
g_clear_object (&priv->trackball_settings);
|
||||
g_clear_object (&priv->keyboard_settings);
|
||||
g_clear_pointer (&priv->mappable_devices, 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);
|
||||
|
||||
G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -451,6 +475,65 @@ update_keyboard_repeat (MetaInputSettings *input_settings)
|
|||
repeat, delay, interval);
|
||||
}
|
||||
|
||||
static MetaOutput *
|
||||
meta_input_settings_find_output (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
guint n_values, n_outputs, i;
|
||||
MetaOutput *outputs;
|
||||
gchar **edid;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
edid = g_settings_get_strv (settings, "display");
|
||||
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));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!*edid[0] && !*edid[1] && !*edid[2])
|
||||
return NULL;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (priv->monitor_manager,
|
||||
&n_outputs);
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
{
|
||||
if (g_strcmp0 (outputs[i].vendor, edid[0]) == 0 &&
|
||||
g_strcmp0 (outputs[i].product, edid[1]) == 0 &&
|
||||
g_strcmp0 (outputs[i].serial, edid[2]) == 0)
|
||||
return &outputs[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 };
|
||||
MetaOutput *output;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
output = meta_input_settings_find_output (input_settings, settings, device);
|
||||
|
||||
if (output)
|
||||
meta_monitor_manager_get_monitor_matrix (priv->monitor_manager,
|
||||
output, matrix);
|
||||
|
||||
input_settings_class->set_matrix (input_settings, device, matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_changed_cb (GSettings *settings,
|
||||
const char *key,
|
||||
|
@ -501,6 +584,100 @@ meta_input_settings_changed_cb (GSettings *settings,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mapped_device_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
if (strcmp (key, "display") == 0)
|
||||
update_device_display (info->input_settings, settings, info->device);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 void
|
||||
monitors_changed_cb (MetaMonitorManager *monitor_manager,
|
||||
MetaInputSettings *input_settings)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
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 *) &settings))
|
||||
update_device_display (input_settings, settings, device);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_add_mappable_device (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
GSettings *settings;
|
||||
|
||||
settings = lookup_device_settings (device);
|
||||
|
||||
if (!settings)
|
||||
return FALSE;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
|
||||
info = g_new0 (DeviceMappingInfo, 1);
|
||||
info->input_settings = input_settings;
|
||||
info->device = device;
|
||||
info->settings = settings;
|
||||
|
||||
g_signal_connect_data (settings, "changed",
|
||||
G_CALLBACK (mapped_device_changed_cb),
|
||||
info, (GClosureNotify) g_free, 0);
|
||||
|
||||
g_hash_table_insert (priv->mappable_devices, device, settings);
|
||||
|
||||
update_device_display (input_settings, settings, device);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
|
@ -535,6 +712,10 @@ meta_input_settings_device_added (ClutterDeviceManager *device_manager,
|
|||
update_device_natural_scroll (input_settings, priv->touchpad_settings,
|
||||
device, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
check_add_mappable_device (input_settings, device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -542,6 +723,30 @@ meta_input_settings_device_removed (ClutterDeviceManager *device_manager,
|
|||
ClutterInputDevice *device,
|
||||
MetaInputSettings *input_settings)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
g_hash_table_remove (priv->mappable_devices, 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
|
||||
|
@ -566,6 +771,8 @@ meta_input_settings_constructed (GObject *object)
|
|||
CLUTTER_POINTER_DEVICE);
|
||||
|
||||
update_keyboard_repeat (input_settings);
|
||||
|
||||
check_mappable_devices (input_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -604,6 +811,13 @@ meta_input_settings_init (MetaInputSettings *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->mappable_devices =
|
||||
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
|
||||
|
||||
priv->monitor_manager = g_object_ref (meta_monitor_manager_get ());
|
||||
g_signal_connect (priv->monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (monitors_changed_cb), settings);
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
|
|
Loading…
Reference in a new issue