[gnome-flashback] implement input settings
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] implement input settings
- Date: Fri, 10 Jun 2016 21:19:00 +0000 (UTC)
commit 20b5ba82198f3a93d7e023091e1109f4b896dea2
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sat Jun 11 00:10:40 2016 +0300
implement input settings
Based on mutter code:
https://git.gnome.org/browse/mutter/tree/src/backends/meta-input-settings.c
https://git.gnome.org/browse/mutter/tree/src/backends/x11/meta-input-settings-x11.c
configure.ac | 2 +
gnome-flashback/gf-application.c | 4 +
.../libdisplay-config/flashback-display-config.c | 6 +
gnome-flashback/libinput-settings/Makefile.am | 1 +
.../libinput-settings/gf-input-settings.c | 1093 +++++++++++++++++++-
.../libinput-settings/gf-input-settings.h | 7 +-
6 files changed, 1111 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f579814..e953714 100644
--- a/configure.ac
+++ b/configure.ac
@@ -169,7 +169,9 @@ PKG_CHECK_MODULES([IDLE_MONITOR], [
PKG_CHECK_MODULES([INPUT_SETTINGS], [
gtk+-3.0 >= $GTK_REQUIRED
+ gnome-desktop-3.0 >= $LIBGNOME_DESKTOP_REQUIRED
gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED
+ xi >= 1.6.0
])
PKG_CHECK_MODULES([INPUT_SOURCES], [
diff --git a/gnome-flashback/gf-application.c b/gnome-flashback/gf-application.c
index dee0d09..62e02a0 100644
--- a/gnome-flashback/gf-application.c
+++ b/gnome-flashback/gf-application.c
@@ -178,6 +178,10 @@ settings_changed (GSettings *settings,
#undef SETTING_CHANGED
+ if (application->input_settings)
+ gf_input_settings_set_display_config (application->input_settings,
+ application->config);
+
if (application->shell)
flashback_shell_set_display_config (application->shell, application->config);
}
diff --git a/gnome-flashback/libdisplay-config/flashback-display-config.c
b/gnome-flashback/libdisplay-config/flashback-display-config.c
index ab0a20c..3cfb637 100644
--- a/gnome-flashback/libdisplay-config/flashback-display-config.c
+++ b/gnome-flashback/libdisplay-config/flashback-display-config.c
@@ -1005,6 +1005,12 @@ flashback_display_config_new (void)
NULL);
}
+/**
+ * flashback_display_config_get_monitor_manager:
+ * @config: a #FlashbackMonitorManager
+ *
+ * Returns: (transfer none):
+ */
FlashbackMonitorManager *
flashback_display_config_get_monitor_manager (FlashbackDisplayConfig *config)
{
diff --git a/gnome-flashback/libinput-settings/Makefile.am b/gnome-flashback/libinput-settings/Makefile.am
index c2f408b..91936a3 100644
--- a/gnome-flashback/libinput-settings/Makefile.am
+++ b/gnome-flashback/libinput-settings/Makefile.am
@@ -6,6 +6,7 @@ noinst_LTLIBRARIES = \
libinput_settings_la_CPPFLAGS = \
-I$(top_builddir)/gnome-flashback/libinput-settings \
+ -I$(top_srcdir)/gnome-flashback \
$(NULL)
libinput_settings_la_CFLAGS = \
diff --git a/gnome-flashback/libinput-settings/gf-input-settings.c
b/gnome-flashback/libinput-settings/gf-input-settings.c
index 963937f..63595d1 100644
--- a/gnome-flashback/libinput-settings/gf-input-settings.c
+++ b/gnome-flashback/libinput-settings/gf-input-settings.c
@@ -1,4 +1,5 @@
/*
+ * Copyright 2014 Red Hat, Inc.
* Copyright (C) 2016 Alberts Muktupāvels
*
* This program is free software: you can redistribute it and/or modify
@@ -17,23 +18,1096 @@
#include "config.h"
+#include <gio/gio.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <gsettings-desktop-schemas/gdesktop-enums.h>
+#include <libdisplay-config/flashback-display-config.h>
+#include <libdisplay-config/flashback-monitor-manager.h>
+#include <string.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/Xatom.h>
+#include <X11/XKBlib.h>
+
#include "gf-input-settings.h"
+typedef void (* ConfigBoolFunc) (GfInputSettings *settings,
+ GdkDevice *device,
+ gboolean value);
+
+typedef void (* ConfigDoubleFunc) (GfInputSettings *settings,
+ GdkDevice *device,
+ gdouble value);
+
+typedef void (* ConfigUintFunc) (GfInputSettings *settings,
+ GdkDevice *device,
+ guint value);
+
+typedef struct
+{
+ GdkDevice *device;
+ GSettings *gsettings;
+ GfInputSettings *settings;
+} DeviceMappingInfo;
+
struct _GfInputSettings
{
- GObject parent;
+ GObject parent;
+
+ Display *xdisplay;
+
+ GdkSeat *seat;
+
+ FlashbackMonitorManager *monitor_manager;
+ gulong monitors_changed_id;
+
+ GSettings *mouse;
+ GSettings *touchpad;
+ GSettings *trackball;
+ GSettings *keyboard;
+
+ GHashTable *mappable_devices;
};
G_DEFINE_TYPE (GfInputSettings, gf_input_settings, G_TYPE_OBJECT)
+static void *
+get_property (GfInputSettings *settings,
+ GdkDevice *device,
+ const gchar *property,
+ Atom type,
+ gint format,
+ gulong nitems)
+{
+ Atom property_atom;
+ gint device_id;
+ gint rc;
+ Atom type_ret;
+ gint format_ret;
+ gulong nitems_ret;
+ gulong bytes_after_ret;
+ guchar *data_ret;
+
+ property_atom = XInternAtom (settings->xdisplay, property, True);
+ if (!property_atom)
+ return NULL;
+
+ device_id = gdk_x11_device_get_id (device);
+ data_ret = NULL;
+
+ rc = XIGetProperty (settings->xdisplay, device_id, property_atom,
+ 0, 10, False, type, &type_ret, &format_ret,
+ &nitems_ret, &bytes_after_ret, &data_ret);
+
+ if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
+ {
+ if (nitems_ret > nitems)
+ g_warning ("Property '%s' for device '%s' returned %lu items, expected %lu",
+ property, gdk_device_get_name (device), nitems_ret, nitems);
+
+ return data_ret;
+ }
+
+ if (data_ret)
+ XFree (data_ret);
+
+ return NULL;
+}
+
+static void
+change_property (GfInputSettings *settings,
+ GdkDevice *device,
+ const gchar *property,
+ Atom type,
+ gint format,
+ void *data,
+ gulong nitems)
+{
+ Atom property_atom;
+ gint device_id;
+ guchar *data_ret;
+
+ property_atom = XInternAtom (settings->xdisplay, property, True);
+ if (!property_atom)
+ return;
+
+ device_id = gdk_x11_device_get_id (device);
+ data_ret = NULL;
+
+ data_ret = get_property (settings, device, property, type, format, nitems);
+ if (!data_ret)
+ return;
+
+ XIChangeProperty (settings->xdisplay, device_id, property_atom, type,
+ format, XIPropModeReplace, data, nitems);
+ XFree (data_ret);
+}
+
+static GList *
+get_devices (GfInputSettings *settings,
+ GdkInputSource source)
+{
+ const GList *devices;
+ const GList *l;
+ GList *list;
+
+ devices = gdk_seat_get_slaves (settings->seat, GDK_SEAT_CAPABILITY_ALL);
+ list = NULL;
+
+ for (l = devices; l; l = l->next)
+ {
+ GdkDevice *device;
+
+ device = GDK_DEVICE (l->data);
+
+ if (gdk_device_get_source (device) != source &&
+ gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
+ continue;
+
+ list = g_list_prepend (list, device);
+ }
+
+ return list;
+}
+
+static void
+device_set_bool_setting (GfInputSettings *settings,
+ GdkDevice *device,
+ ConfigBoolFunc func,
+ gboolean value)
+{
+ func (settings, device, value);
+}
+
+static void
+set_bool_setting (GfInputSettings *settings,
+ GdkInputSource source,
+ ConfigBoolFunc func,
+ gboolean value)
+{
+ GList *devices;
+ GList *d;
+
+ devices = get_devices (settings, source);
+
+ for (d = devices; d; d = d->next)
+ device_set_bool_setting (settings, d->data, func, value);
+
+ g_list_free (devices);
+}
+
+static void
+device_set_double_setting (GfInputSettings *settings,
+ GdkDevice *device,
+ ConfigDoubleFunc func,
+ gdouble value)
+{
+ func (settings, device, value);
+}
+
+static void
+set_double_setting (GfInputSettings *settings,
+ GdkInputSource source,
+ ConfigDoubleFunc func,
+ gdouble value)
+{
+ GList *devices;
+ GList *d;
+
+ devices = get_devices (settings, source);
+
+ for (d = devices; d; d = d->next)
+ device_set_double_setting (settings, d->data, func, value);
+
+ g_list_free (devices);
+}
+
+static void
+device_set_uint_setting (GfInputSettings *settings,
+ GdkDevice *device,
+ ConfigUintFunc func,
+ guint value)
+{
+ func (settings, device, value);
+}
+
+static void
+set_uint_setting (GfInputSettings *settings,
+ GdkInputSource source,
+ ConfigUintFunc func,
+ guint value)
+{
+ GList *devices;
+ GList *d;
+
+ devices = get_devices (settings, source);
+
+ for (d = devices; d; d = d->next)
+ device_set_uint_setting (settings, d->data, func, value);
+
+ g_list_free (devices);
+}
+
+static GSettings *
+get_settings_for_source (GfInputSettings *settings,
+ GdkInputSource source)
+{
+ if (source == GDK_SOURCE_MOUSE)
+ return settings->mouse;
+ else if (source == GDK_SOURCE_TOUCHPAD)
+ return settings->touchpad;
+
+ return NULL;
+}
+
+static void
+set_speed (GfInputSettings *settings,
+ GdkDevice *device,
+ gdouble speed)
+{
+ gfloat value = speed;
+
+ change_property (settings, device, "libinput Accel Speed",
+ XInternAtom (settings->xdisplay, "FLOAT", False),
+ 32, &value, 1);
+}
+
+static void
+set_left_handed (GfInputSettings *settings,
+ GdkDevice *device,
+ gboolean enabled)
+{
+ guchar value = (enabled) ? 1 : 0;
+
+ change_property (settings, device, "libinput Left Handed Enabled",
+ XA_INTEGER, 8, &value, 1);
+}
+
+static void
+set_invert_scroll (GfInputSettings *settings,
+ GdkDevice *device,
+ gboolean inverted)
+{
+ guchar value = (inverted) ? 1 : 0;
+
+ change_property (settings, device, "libinput Natural Scrolling Enabled",
+ XA_INTEGER, 8, &value, 1);
+}
+
+static void
+set_tap_enabled (GfInputSettings *settings,
+ GdkDevice *device,
+ gboolean enabled)
+{
+ guchar value = (enabled) ? 1 : 0;
+
+ change_property (settings, device, "libinput Tapping Enabled",
+ XA_INTEGER, 8, &value, 1);
+}
+
+static void
+set_send_events (GfInputSettings *settings,
+ GdkDevice *device,
+ GDesktopDeviceSendEvents mode)
+{
+ guchar *available;
+ guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */
+
+ available = get_property (settings, device,
+ "libinput Send Events Modes Available",
+ XA_INTEGER, 8, 2);
+
+ if (!available)
+ return;
+
+ switch (mode)
+ {
+ case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED:
+ values[0] = 1;
+ break;
+ case G_DESKTOP_DEVICE_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE:
+ values[1] = 1;
+ break;
+ case G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED:
+ default:
+ break;
+ }
+
+ if ((values[0] && !available[0]) || (values[1] && !available[1]))
+ g_warning ("Device '%s' does not support sendevents mode %d",
+ gdk_device_get_name (device), mode);
+ else
+ change_property (settings, device, "libinput Send Events Mode Enabled",
+ XA_INTEGER, 8, &values, 2);
+
+ XFree (available);
+}
+
+static void
+set_edge_scroll (GfInputSettings *settings,
+ GdkDevice *device,
+ gboolean edge_scroll_enabled)
+{
+ guchar *available;
+ guchar values[3] = { 0 }; /* 2fg, edge, button. The last value is unused */
+
+ available = get_property (settings, device,
+ "libinput Scroll Methods Available",
+ XA_INTEGER, 8, 3);
+
+ if (!available)
+ return;
+
+ if (available[0])
+ {
+ values[0] = 1;
+ }
+ else if (available[1] && edge_scroll_enabled)
+ {
+ values[1] = 1;
+ }
+ else
+ {
+ /* Disabled */
+ }
+
+ change_property (settings, device, "libinput Scroll Method Enabled",
+ XA_INTEGER, 8, &values, 3);
+
+ XFree (available);
+}
+
+static void
+set_click_method (GfInputSettings *settings,
+ GdkDevice *device,
+ GDesktopTouchpadClickMethod mode)
+{
+ guchar *available;
+ guchar *defaults;
+ guchar values[2] = { 0 }; /* buttonareas, clickfinger */
+
+ available = get_property (settings, device,
+ "libinput Click Methods Available",
+ XA_INTEGER, 8, 2);
+
+ if (!available)
+ return;
+
+ switch (mode)
+ {
+ case G_DESKTOP_TOUCHPAD_CLICK_METHOD_DEFAULT:
+ defaults = get_property (settings, device,
+ "libinput Click Method Enabled Default",
+ XA_INTEGER, 8, 2);
+
+ if (!defaults)
+ break;
+
+ memcpy (values, defaults, 2);
+ XFree (defaults);
+ break;
+ case G_DESKTOP_TOUCHPAD_CLICK_METHOD_NONE:
+ break;
+ case G_DESKTOP_TOUCHPAD_CLICK_METHOD_AREAS:
+ values[0] = 1;
+ break;
+ case G_DESKTOP_TOUCHPAD_CLICK_METHOD_FINGERS:
+ values[1] = 1;
+ break;
+ default:
+ g_assert_not_reached ();
+ return;
+ }
+
+ if ((values[0] && !available[0]) || (values[1] && !available[1]))
+ g_warning ("Device '%s' does not support click method %d",
+ gdk_device_get_name (device), mode);
+ else
+ change_property (settings, device, "libinput Click Method Enabled",
+ XA_INTEGER, 8, &values, 2);
+
+ XFree (available);
+}
+
+static gboolean
+device_is_trackball (GdkDevice *device)
+{
+ gboolean is_trackball;
+ gchar *name;
+
+ if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
+ return FALSE;
+
+ name = g_ascii_strdown (gdk_device_get_name (device), -1);
+ is_trackball = strstr (name, "trackball") != NULL;
+ g_free (name);
+
+ return is_trackball;
+}
+
+static void
+update_touchpad_left_handed (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GDesktopTouchpadHandedness handedness;
+ gboolean enabled;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ return;
+
+ handedness = g_settings_get_enum (settings->touchpad, "left-handed");
+ enabled = FALSE;
+
+ 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 (settings->mouse, "left-handed");
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (device)
+ {
+ device_set_bool_setting (settings, device,
+ set_left_handed, enabled);
+ }
+ else
+ {
+ set_bool_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_left_handed, enabled);
+ }
+}
+
+static void
+update_mouse_left_handed (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ gboolean enabled;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
+ return;
+
+ enabled = g_settings_get_boolean (settings->mouse, "left-handed");
+
+ if (device)
+ {
+ device_set_bool_setting (settings, device, set_left_handed, enabled);
+ }
+ else
+ {
+ GDesktopTouchpadHandedness handedness;
+
+ set_bool_setting (settings, GDK_SOURCE_MOUSE, set_left_handed, enabled);
+
+ handedness = g_settings_get_enum (settings->touchpad, "left-handed");
+
+ /* Also update touchpads if they're following mouse settings */
+ if (handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_MOUSE)
+ update_touchpad_left_handed (settings, NULL);
+ }
+}
+
+static void
+update_device_speed (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GSettings *gsettings;
+ const gchar *key;
+ gdouble value;
+
+ key = "speed";
+
+ if (device)
+ {
+ gsettings = get_settings_for_source (settings,
+ gdk_device_get_source (device));
+
+ if (!gsettings)
+ return;
+
+ value = g_settings_get_double (gsettings, key);
+ device_set_double_setting (settings, device, set_speed, value);
+ }
+ else
+ {
+ gsettings = get_settings_for_source (settings, GDK_SOURCE_MOUSE);
+ value = g_settings_get_double (gsettings, key);
+ set_double_setting (settings, GDK_SOURCE_MOUSE, set_speed, value);
+
+ gsettings = get_settings_for_source (settings, GDK_SOURCE_TOUCHPAD);
+ value = g_settings_get_double (gsettings, key);
+ set_double_setting (settings, GDK_SOURCE_TOUCHPAD, set_speed, value);
+ }
+}
+
+static void
+update_device_natural_scroll (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GSettings *gsettings;
+ const gchar *key;
+ gboolean value;
+
+ key = "natural-scroll";
+
+ if (device)
+ {
+ gsettings = get_settings_for_source (settings,
+ gdk_device_get_source (device));
+
+ if (!gsettings)
+ return;
+
+ value = g_settings_get_boolean (gsettings, key);
+ device_set_bool_setting (settings, device, set_invert_scroll, value);
+ }
+ else
+ {
+ gsettings = get_settings_for_source (settings, GDK_SOURCE_MOUSE);
+ value = g_settings_get_boolean (gsettings, key);
+
+ set_bool_setting (settings, GDK_SOURCE_MOUSE,
+ set_invert_scroll, value);
+
+ gsettings = get_settings_for_source (settings, GDK_SOURCE_TOUCHPAD);
+ value = g_settings_get_boolean (gsettings, key);
+
+ set_bool_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_invert_scroll, value);
+ }
+}
+
+static void
+update_touchpad_tap_enabled (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ gboolean enabled;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ return;
+
+ enabled = g_settings_get_boolean (settings->touchpad, "tap-to-click");
+
+ if (device)
+ {
+ device_set_bool_setting (settings, device,
+ set_tap_enabled, enabled);
+ }
+ else
+ {
+ set_bool_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_tap_enabled, enabled);
+ }
+}
+
+static void
+update_touchpad_send_events (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GDesktopDeviceSendEvents mode;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ return;
+
+ mode = g_settings_get_enum (settings->touchpad, "send-events");
+
+ if (device)
+ {
+ device_set_uint_setting (settings, device,
+ set_send_events, mode);
+ }
+ else
+ {
+ set_uint_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_send_events, mode);
+ }
+}
+
+static void
+update_touchpad_edge_scroll (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ gboolean edge_scroll_enabled;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ return;
+
+ edge_scroll_enabled = g_settings_get_boolean (settings->touchpad,
+ "edge-scrolling-enabled");
+
+ if (device)
+ {
+ device_set_bool_setting (settings, device,
+ set_edge_scroll, edge_scroll_enabled);
+ }
+ else
+ {
+ set_bool_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_edge_scroll, edge_scroll_enabled);
+ }
+}
+
+static void
+update_touchpad_click_method (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GDesktopTouchpadClickMethod method;
+
+ if (device && gdk_device_get_source (device) != GDK_SOURCE_TOUCHPAD)
+ return;
+
+ method = g_settings_get_enum (settings->touchpad, "click-method");
+
+ if (device)
+ {
+ device_set_uint_setting (settings, device,
+ set_click_method, method);
+ }
+ else
+ {
+ set_uint_setting (settings, GDK_SOURCE_TOUCHPAD,
+ set_click_method, method);
+ }
+}
+
+static void
+update_trackball_scroll_button (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ guint button;
+
+ if (device && !device_is_trackball (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 (settings->trackball,
+ "scroll-wheel-emulation-button");
+
+ if (device)
+ {
+ change_property (settings, device, "libinput Button Scrolling Button",
+ XA_INTEGER, 32, &button, 1);
+ }
+ else
+ {
+ const GList *devices;
+ const GList *l;
+
+ devices = gdk_seat_get_slaves (settings->seat, GDK_SEAT_CAPABILITY_ALL);
+
+ for (l = devices; l; l = l->next)
+ {
+ device = GDK_DEVICE (l->data);
+
+ if (!device_is_trackball (device))
+ continue;
+
+ change_property (settings, device, "libinput Button Scrolling Button",
+ XA_INTEGER, 32, &button, 1);
+ }
+ }
+}
+
+static void
+update_keyboard_repeat (GfInputSettings *settings)
+{
+ gboolean repeat;
+ guint delay;
+ guint interval;
+
+ repeat = g_settings_get_boolean (settings->keyboard, "repeat");
+ delay = g_settings_get_uint (settings->keyboard, "delay");
+ interval = g_settings_get_uint (settings->keyboard, "repeat-interval");
+
+ if (repeat)
+ {
+ XAutoRepeatOn (settings->xdisplay);
+ XkbSetAutoRepeatRate (settings->xdisplay, XkbUseCoreKbd, delay, interval);
+ }
+ else
+ {
+ XAutoRepeatOff (settings->xdisplay);
+ }
+}
+
+static void
+settings_changed_cb (GSettings *gsettings,
+ const gchar *key,
+ GfInputSettings *settings)
+{
+ if (gsettings == settings->mouse)
+ {
+ if (strcmp (key, "left-handed") == 0)
+ update_mouse_left_handed (settings, NULL);
+ else if (strcmp (key, "speed") == 0)
+ update_device_speed (settings, NULL);
+ else if (strcmp (key, "natural-scroll") == 0)
+ update_device_natural_scroll (settings, NULL);
+ }
+ else if (gsettings == settings->touchpad)
+ {
+ if (strcmp (key, "left-handed") == 0)
+ update_touchpad_left_handed (settings, NULL);
+ else if (strcmp (key, "speed") == 0)
+ update_device_speed (settings, NULL);
+ else if (strcmp (key, "natural-scroll") == 0)
+ update_device_natural_scroll (settings, NULL);
+ else if (strcmp (key, "tap-to-click") == 0)
+ update_touchpad_tap_enabled (settings, NULL);
+ else if (strcmp (key, "send-events") == 0)
+ update_touchpad_send_events (settings, NULL);
+ else if (strcmp (key, "edge-scrolling-enabled") == 0)
+ update_touchpad_edge_scroll (settings, NULL);
+ else if (strcmp (key, "click-method") == 0)
+ update_touchpad_click_method (settings, NULL);
+ }
+ else if (gsettings == settings->trackball)
+ {
+ if (strcmp (key, "scroll-wheel-emulation-button") == 0)
+ update_trackball_scroll_button (settings, NULL);
+ }
+ else if (gsettings == settings->keyboard)
+ {
+ if (strcmp (key, "repeat") == 0 ||
+ strcmp (key, "repeat-interval") == 0 ||
+ strcmp (key, "delay") == 0)
+ update_keyboard_repeat (settings);
+ }
+}
+
+static MetaOutput *
+find_output (GfInputSettings *settings,
+ GSettings *gsettings,
+ GdkDevice *device)
+{
+ gchar **edid;
+ guint n_values;
+ MetaOutput *outputs;
+ guint n_outputs;
+ guint i;
+
+ edid = g_settings_get_strv (gsettings, "display");
+ n_values = g_strv_length (edid);
+
+ if (n_values != 3)
+ {
+ g_warning ("EDID configuration for device '%s' is incorrect, "
+ "must have 3 values", gdk_device_get_name (device));
+
+ return NULL;
+ }
+
+ if (!*edid[0] && !*edid[1] && !*edid[2])
+ return NULL;
+
+ outputs = flashback_monitor_manager_get_outputs (settings->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 (GfInputSettings *settings,
+ GSettings *gsettings,
+ GdkDevice *device)
+{
+ MetaOutput *output;
+ gfloat matrix[6] = { 1, 0, 0, 0, 1, 0 };
+ gfloat full_matrix[9];
+
+ output = find_output (settings, gsettings, device);
+
+ if (output)
+ {
+ flashback_monitor_manager_get_monitor_matrix (settings->monitor_manager,
+ output, matrix);
+ }
+
+ full_matrix[0] = matrix[0];
+ full_matrix[1] = matrix[1];
+ full_matrix[2] = matrix[2];
+ full_matrix[3] = matrix[3];
+ full_matrix[4] = matrix[4];
+ full_matrix[5] = matrix[5];
+ full_matrix[6] = 0;
+ full_matrix[7] = 0;
+ full_matrix[8] = 1;
+
+ change_property (settings, device, "Coordinate Transformation Matrix",
+ XInternAtom (settings->xdisplay, "FLOAT", False),
+ 32, &full_matrix, 9);
+}
+
+static void
+monitors_changed_cb (FlashbackMonitorManager *monitor_manager,
+ GfInputSettings *settings)
+{
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+
+ g_hash_table_iter_init (&iter, settings->mappable_devices);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GSettings *gsettings;
+ GdkDevice *device;
+
+ gsettings = G_SETTINGS (value);
+ device = GDK_DEVICE (key);
+
+ update_device_display (settings, gsettings, device);
+ }
+}
+
+static GSettings *
+lookup_device_settings (GdkDevice *device)
+{
+ GdkInputSource source;
+ const gchar *group;
+ const gchar *schema;
+ const gchar *vendor;
+ const gchar *product;
+ gchar *path;
+ GSettings *gsettings;
+
+ source = gdk_device_get_source (device);
+
+ if (source == GDK_SOURCE_TOUCHSCREEN)
+ {
+ group = "touchscreens";
+ schema = "org.gnome.desktop.peripherals.touchscreen";
+ }
+ else if (/* type == CLUTTER_TABLET_DEVICE || */
+ source == GDK_SOURCE_PEN ||
+ source == GDK_SOURCE_ERASER ||
+ source == GDK_SOURCE_CURSOR)
+ {
+ group = "tablets";
+ schema = "org.gnome.desktop.peripherals.tablet";
+ }
+ else
+ {
+ return NULL;
+ }
+
+ vendor = gdk_device_get_vendor_id (device);
+ product = gdk_device_get_product_id (device);
+
+ path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
+ group, vendor, product);
+
+ gsettings = g_settings_new_with_path (schema, path);
+ g_free (path);
+
+ return gsettings;
+}
+
+static void
+mapped_device_changed_cb (GSettings *gsettings,
+ const gchar *key,
+ DeviceMappingInfo *info)
+{
+ if (strcmp (key, "display") == 0)
+ update_device_display (info->settings, gsettings, info->device);
+}
+
+static void
+check_add_mappable_device (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ GSettings *gsettings;
+ DeviceMappingInfo *info;
+
+ gsettings = lookup_device_settings (device);
+
+ if (!gsettings)
+ return;
+
+ info = g_new0 (DeviceMappingInfo, 1);
+
+ info->device = device;
+ info->gsettings = gsettings;
+ info->settings = settings;
+
+ g_signal_connect_data (gsettings, "changed",
+ G_CALLBACK (mapped_device_changed_cb),
+ info, (GClosureNotify) g_free, 0);
+
+ g_hash_table_insert (settings->mappable_devices, device, settings);
+ update_device_display (settings, gsettings, device);
+}
+
+static void
+apply_device_settings (GfInputSettings *settings,
+ GdkDevice *device)
+{
+ update_mouse_left_handed (settings, device);
+ update_device_speed (settings, device);
+ update_device_natural_scroll (settings, device);
+
+ update_touchpad_left_handed (settings, device);
+#if 0
+ update_device_speed (settings, device);
+ update_device_natural_scroll (settings, device);
+#endif
+ update_touchpad_tap_enabled (settings, device);
+ update_touchpad_send_events (settings, device);
+ update_touchpad_edge_scroll (settings, device);
+ update_touchpad_click_method (settings, device);
+
+ update_trackball_scroll_button (settings, device);
+}
+
+static void
+device_added_cb (GdkSeat *seat,
+ GdkDevice *device,
+ GfInputSettings *settings)
+{
+ if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
+ return;
+
+ apply_device_settings (settings, device);
+ check_add_mappable_device (settings, device);
+}
+
+static void
+device_removed_cb (GdkSeat *seat,
+ GdkDevice *device,
+ GfInputSettings *settings)
+{
+ g_hash_table_remove (settings->mappable_devices, device);
+}
+
+static void
+check_mappable_devices (GfInputSettings *settings)
+{
+ const GList *devices;
+ const GList *l;
+
+ devices = gdk_seat_get_slaves (settings->seat, GDK_SEAT_CAPABILITY_ALL);
+
+ for (l = devices; l; l = l->next)
+ {
+ GdkDevice *device;
+
+ device = GDK_DEVICE (l->data);
+
+ if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER)
+ continue;
+
+ check_add_mappable_device (settings, device);
+ }
+}
+
+static void
+clear_monitor_manager (GfInputSettings *settings)
+{
+ gulong changed_id;
+
+ changed_id = settings->monitors_changed_id;
+
+ if (changed_id > 0 && settings->monitor_manager)
+ {
+ g_signal_handler_disconnect (settings->monitor_manager, changed_id);
+ settings->monitors_changed_id = 0;
+ }
+
+ g_clear_object (&settings->monitor_manager);
+}
+
+static void
+gf_input_settings_constructed (GObject *object)
+{
+ GfInputSettings *settings;
+
+ settings = GF_INPUT_SETTINGS (object);
+
+ apply_device_settings (settings, NULL);
+ update_keyboard_repeat (settings);
+ check_mappable_devices (settings);
+}
+
+static void
+gf_input_settings_dispose (GObject *object)
+{
+ GfInputSettings *settings;
+
+ settings = GF_INPUT_SETTINGS (object);
+
+ clear_monitor_manager (settings);
+
+ g_clear_object (&settings->mouse);
+ g_clear_object (&settings->touchpad);
+ g_clear_object (&settings->trackball);
+ g_clear_object (&settings->keyboard);
+
+ g_clear_pointer (&settings->mappable_devices, g_hash_table_destroy);
+
+ G_OBJECT_CLASS (gf_input_settings_parent_class)->dispose (object);
+}
+
static void
gf_input_settings_class_init (GfInputSettingsClass *settings_class)
{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (settings_class);
+
+ object_class->constructed = gf_input_settings_constructed;
+ object_class->dispose = gf_input_settings_dispose;
}
static void
gf_input_settings_init (GfInputSettings *settings)
{
+ GdkDisplay *display;
+
+ display = gdk_display_get_default ();
+
+ settings->xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ settings->seat = gdk_display_get_default_seat (display);
+ g_signal_connect (settings->seat, "device-added",
+ G_CALLBACK (device_added_cb), settings);
+ g_signal_connect (settings->seat, "device-removed",
+ G_CALLBACK (device_removed_cb), settings);
+
+ settings->mouse = g_settings_new ("org.gnome.desktop.peripherals.mouse");
+ g_signal_connect (settings->mouse, "changed",
+ G_CALLBACK (settings_changed_cb), settings);
+
+ settings->touchpad = g_settings_new ("org.gnome.desktop.peripherals.touchpad");
+ g_signal_connect (settings->touchpad, "changed",
+ G_CALLBACK (settings_changed_cb), settings);
+
+ settings->trackball = g_settings_new ("org.gnome.desktop.peripherals.trackball");
+ g_signal_connect (settings->trackball, "changed",
+ G_CALLBACK (settings_changed_cb), settings);
+
+ settings->keyboard = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
+ g_signal_connect (settings->keyboard, "changed",
+ G_CALLBACK (settings_changed_cb), settings);
+
+ settings->mappable_devices = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
}
GfInputSettings *
@@ -41,3 +1115,20 @@ gf_input_settings_new (void)
{
return g_object_new (GF_TYPE_INPUT_SETTINGS, NULL);
}
+
+void
+gf_input_settings_set_display_config (GfInputSettings *settings,
+ FlashbackDisplayConfig *config)
+{
+ FlashbackMonitorManager *monitor_manager;
+
+ monitor_manager = flashback_display_config_get_monitor_manager (config);
+
+ clear_monitor_manager (settings);
+ if (monitor_manager == NULL)
+ return;
+
+ settings->monitor_manager = g_object_ref (monitor_manager);
+ g_signal_connect (settings->monitor_manager, "monitors-changed",
+ G_CALLBACK (monitors_changed_cb), settings);
+}
diff --git a/gnome-flashback/libinput-settings/gf-input-settings.h
b/gnome-flashback/libinput-settings/gf-input-settings.h
index 56e926a..16d410e 100644
--- a/gnome-flashback/libinput-settings/gf-input-settings.h
+++ b/gnome-flashback/libinput-settings/gf-input-settings.h
@@ -22,11 +22,16 @@
G_BEGIN_DECLS
+typedef struct _FlashbackDisplayConfig FlashbackDisplayConfig;
+
#define GF_TYPE_INPUT_SETTINGS gf_input_settings_get_type ()
G_DECLARE_FINAL_TYPE (GfInputSettings, gf_input_settings,
GF, INPUT_SETTINGS, GObject)
-GfInputSettings *gf_input_settings_new (void);
+GfInputSettings *gf_input_settings_new (void);
+
+void gf_input_settings_set_display_config (GfInputSettings *settings,
+ FlashbackDisplayConfig *config);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]