clutter: Move pointer a11y settings management from MetaInputSettings
All pointer a11y is a fabrication of Clutter backend-independent code, with the help of a ClutterVirtualInputDevice and with some UI on top. On the other hand, MetaInputSettings is a backend implementation detail, this has 2 gotchas: - In the native backend, the MetaInputSettings (and pointer a11y with it) are initialized early, before the ClutterSeat core pointer is set up. - Doing this from the MetaInputSettings also means another dubious access from the input thread into main thread territory. Move the pointer a11y into ClutterSettings, making this effectively backend-independent business, invariably done from the main thread and ensured to happen after seat initialization. Fixes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1765 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1849>
This commit is contained in:
parent
d4a042b88d
commit
7ba1448e5b
5 changed files with 138 additions and 98 deletions
|
@ -31,6 +31,7 @@
|
|||
#include "clutter-private.h"
|
||||
#include "clutter-seat.h"
|
||||
#include "clutter-seat-private.h"
|
||||
#include "clutter-settings-private.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
|
||||
enum
|
||||
|
@ -114,6 +115,16 @@ clutter_seat_get_property (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_constructed (GObject *object)
|
||||
{
|
||||
ClutterSettings *settings = clutter_settings_get_default ();
|
||||
|
||||
G_OBJECT_CLASS (clutter_seat_parent_class)->constructed (object);
|
||||
clutter_settings_ensure_pointer_a11y_settings (settings,
|
||||
CLUTTER_SEAT (object));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_class_init (ClutterSeatClass *klass)
|
||||
{
|
||||
|
@ -121,6 +132,7 @@ clutter_seat_class_init (ClutterSeatClass *klass)
|
|||
|
||||
object_class->set_property = clutter_seat_set_property;
|
||||
object_class->get_property = clutter_seat_get_property;
|
||||
object_class->constructed = clutter_seat_constructed;
|
||||
|
||||
signals[DEVICE_ADDED] =
|
||||
g_signal_new (I_("device-added"),
|
||||
|
|
|
@ -13,6 +13,9 @@ void clutter_settings_set_property_internal (ClutterSettings *settings,
|
|||
const char *property,
|
||||
GValue *value);
|
||||
|
||||
void clutter_settings_ensure_pointer_a11y_settings (ClutterSettings *settings,
|
||||
ClutterSeat *seat);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_SETTINGS_PRIVATE_H__ */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "clutter-stage-private.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#include <gdesktop-enums.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DEFAULT_FONT_NAME "Sans 12"
|
||||
|
@ -67,6 +68,7 @@ struct _ClutterSettings
|
|||
ClutterBackend *backend;
|
||||
GSettings *font_settings;
|
||||
GSettings *mouse_settings;
|
||||
GSettings *mouse_a11y_settings;
|
||||
|
||||
gint double_click_time;
|
||||
gint double_click_distance;
|
||||
|
@ -436,11 +438,110 @@ on_mouse_settings_change_event (GSettings *settings,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
struct _pointer_a11y_settings_flags_pair {
|
||||
const char *name;
|
||||
ClutterPointerA11yFlags flag;
|
||||
} pointer_a11y_settings_flags_pair[] = {
|
||||
{ "secondary-click-enabled", CLUTTER_A11Y_SECONDARY_CLICK_ENABLED },
|
||||
{ "dwell-click-enabled", CLUTTER_A11Y_DWELL_ENABLED },
|
||||
};
|
||||
|
||||
static ClutterPointerA11yDwellDirection
|
||||
pointer_a11y_dwell_direction_from_setting (ClutterSettings *self,
|
||||
const char *key)
|
||||
{
|
||||
GDesktopMouseDwellDirection dwell_gesture_direction;
|
||||
|
||||
dwell_gesture_direction = g_settings_get_enum (self->mouse_a11y_settings,
|
||||
key);
|
||||
switch (dwell_gesture_direction)
|
||||
{
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_LEFT:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_LEFT;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_RIGHT:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_UP:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_UP;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_DOWN:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_DOWN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
sync_pointer_a11y_settings (ClutterSettings *self,
|
||||
ClutterSeat *seat)
|
||||
{
|
||||
ClutterPointerA11ySettings pointer_a11y_settings;
|
||||
GDesktopMouseDwellMode dwell_mode;
|
||||
int i;
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (seat, &pointer_a11y_settings);
|
||||
pointer_a11y_settings.controls = 0;
|
||||
for (i = 0; i < G_N_ELEMENTS (pointer_a11y_settings_flags_pair); i++)
|
||||
{
|
||||
if (!g_settings_get_boolean (self->mouse_a11y_settings,
|
||||
pointer_a11y_settings_flags_pair[i].name))
|
||||
continue;
|
||||
|
||||
pointer_a11y_settings.controls |=
|
||||
pointer_a11y_settings_flags_pair[i].flag;
|
||||
}
|
||||
|
||||
/* "secondary-click-time" is expressed in seconds */
|
||||
pointer_a11y_settings.secondary_click_delay =
|
||||
(1000 * g_settings_get_double (self->mouse_a11y_settings,
|
||||
"secondary-click-time"));
|
||||
/* "dwell-time" is expressed in seconds */
|
||||
pointer_a11y_settings.dwell_delay =
|
||||
(1000 * g_settings_get_double (self->mouse_a11y_settings, "dwell-time"));
|
||||
pointer_a11y_settings.dwell_threshold =
|
||||
g_settings_get_int (self->mouse_a11y_settings, "dwell-threshold");
|
||||
|
||||
dwell_mode = g_settings_get_enum (self->mouse_a11y_settings, "dwell-mode");
|
||||
if (dwell_mode == G_DESKTOP_MOUSE_DWELL_MODE_WINDOW)
|
||||
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_WINDOW;
|
||||
else
|
||||
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_GESTURE;
|
||||
|
||||
pointer_a11y_settings.dwell_gesture_single =
|
||||
pointer_a11y_dwell_direction_from_setting (self, "dwell-gesture-single");
|
||||
pointer_a11y_settings.dwell_gesture_double =
|
||||
pointer_a11y_dwell_direction_from_setting (self, "dwell-gesture-double");
|
||||
pointer_a11y_settings.dwell_gesture_drag =
|
||||
pointer_a11y_dwell_direction_from_setting (self, "dwell-gesture-drag");
|
||||
pointer_a11y_settings.dwell_gesture_secondary =
|
||||
pointer_a11y_dwell_direction_from_setting (self, "dwell-gesture-secondary");
|
||||
|
||||
clutter_seat_set_pointer_a11y_settings (seat, &pointer_a11y_settings);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_mouse_a11y_settings_change_event (GSettings *settings,
|
||||
gpointer keys,
|
||||
int n_keys,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterSettings *self = CLUTTER_SETTINGS (user_data);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (self->backend);
|
||||
|
||||
sync_pointer_a11y_settings (self, seat);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_initial_settings (ClutterSettings *self)
|
||||
{
|
||||
static const gchar *font_settings_path = "org.gnome.desktop.interface";
|
||||
static const gchar *mouse_settings_path = "org.gnome.desktop.peripherals.mouse";
|
||||
static const char *mouse_a11y_settings_path = "org.gnome.desktop.a11y.mouse";
|
||||
GSettingsSchemaSource *source = g_settings_schema_source_get_default ();
|
||||
GSettingsSchema *schema;
|
||||
|
||||
|
@ -477,6 +578,19 @@ load_initial_settings (ClutterSettings *self)
|
|||
self);
|
||||
}
|
||||
}
|
||||
|
||||
schema = g_settings_schema_source_lookup (source, mouse_a11y_settings_path, TRUE);
|
||||
if (!schema)
|
||||
{
|
||||
g_warning ("Failed to find schema: %s", mouse_settings_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->mouse_a11y_settings = g_settings_new_full (schema, NULL, NULL);
|
||||
g_signal_connect (self->mouse_a11y_settings, "change-event",
|
||||
G_CALLBACK (on_mouse_a11y_settings_change_event),
|
||||
self);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -490,6 +604,7 @@ clutter_settings_finalize (GObject *gobject)
|
|||
|
||||
g_clear_object (&self->font_settings);
|
||||
g_clear_object (&self->mouse_settings);
|
||||
g_clear_object (&self->mouse_a11y_settings);
|
||||
|
||||
G_OBJECT_CLASS (clutter_settings_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
@ -958,3 +1073,10 @@ _clutter_settings_set_backend (ClutterSettings *settings,
|
|||
|
||||
load_initial_settings (settings);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_settings_ensure_pointer_a11y_settings (ClutterSettings *settings,
|
||||
ClutterSeat *seat)
|
||||
{
|
||||
sync_pointer_a11y_settings (settings, seat);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,7 @@ endif
|
|||
clutter_deps = [
|
||||
clutter_pkg_deps,
|
||||
clutter_pkg_private_deps,
|
||||
gsettings_desktop_schemas_dep,
|
||||
libmutter_cogl_dep,
|
||||
m_dep
|
||||
]
|
||||
|
|
|
@ -74,7 +74,6 @@ struct _MetaInputSettingsPrivate
|
|||
GSettings *trackball_settings;
|
||||
GSettings *keyboard_settings;
|
||||
GSettings *keyboard_a11y_settings;
|
||||
GSettings *mouse_a11y_settings;
|
||||
|
||||
GList *devices;
|
||||
GHashTable *mappable_devices;
|
||||
|
@ -152,7 +151,6 @@ meta_input_settings_dispose (GObject *object)
|
|||
g_clear_object (&priv->trackball_settings);
|
||||
g_clear_object (&priv->keyboard_settings);
|
||||
g_clear_object (&priv->keyboard_a11y_settings);
|
||||
g_clear_object (&priv->mouse_a11y_settings);
|
||||
g_clear_pointer (&priv->mappable_devices, g_hash_table_unref);
|
||||
g_clear_pointer (&priv->current_tools, g_hash_table_unref);
|
||||
|
||||
|
@ -1273,97 +1271,6 @@ meta_input_keyboard_a11y_settings_changed (GSettings *settings,
|
|||
load_keyboard_a11y_settings (input_settings);
|
||||
}
|
||||
|
||||
struct _pointer_a11y_settings_flags_pair {
|
||||
const char *name;
|
||||
ClutterPointerA11yFlags flag;
|
||||
} pointer_a11y_settings_flags_pair[] = {
|
||||
{ "secondary-click-enabled", CLUTTER_A11Y_SECONDARY_CLICK_ENABLED },
|
||||
{ "dwell-click-enabled", CLUTTER_A11Y_DWELL_ENABLED },
|
||||
};
|
||||
|
||||
static ClutterPointerA11yDwellDirection
|
||||
pointer_a11y_dwell_direction_from_setting (MetaInputSettings *input_settings,
|
||||
const char *key)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
||||
GDesktopMouseDwellDirection dwell_gesture_direction;
|
||||
|
||||
dwell_gesture_direction = g_settings_get_enum (priv->mouse_a11y_settings, key);
|
||||
switch (dwell_gesture_direction)
|
||||
{
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_LEFT:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_LEFT;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_RIGHT:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_RIGHT;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_UP:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_UP;
|
||||
break;
|
||||
case G_DESKTOP_MOUSE_DWELL_DIRECTION_DOWN:
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_DOWN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return CLUTTER_A11Y_DWELL_DIRECTION_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
load_pointer_a11y_settings (MetaInputSettings *input_settings)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (input_settings);
|
||||
ClutterPointerA11ySettings pointer_a11y_settings;
|
||||
GDesktopMouseDwellMode dwell_mode;
|
||||
guint i;
|
||||
|
||||
clutter_seat_get_pointer_a11y_settings (CLUTTER_SEAT (priv->seat),
|
||||
&pointer_a11y_settings);
|
||||
pointer_a11y_settings.controls = 0;
|
||||
for (i = 0; i < G_N_ELEMENTS (pointer_a11y_settings_flags_pair); i++)
|
||||
{
|
||||
if (g_settings_get_boolean (priv->mouse_a11y_settings, pointer_a11y_settings_flags_pair[i].name))
|
||||
pointer_a11y_settings.controls |= pointer_a11y_settings_flags_pair[i].flag;
|
||||
}
|
||||
|
||||
/* "secondary-click-time" is expressed in seconds */
|
||||
pointer_a11y_settings.secondary_click_delay =
|
||||
(1000 * g_settings_get_double (priv->mouse_a11y_settings, "secondary-click-time"));
|
||||
/* "dwell-time" is expressed in seconds */
|
||||
pointer_a11y_settings.dwell_delay =
|
||||
(1000 * g_settings_get_double (priv->mouse_a11y_settings, "dwell-time"));
|
||||
pointer_a11y_settings.dwell_threshold = g_settings_get_int (priv->mouse_a11y_settings,
|
||||
"dwell-threshold");
|
||||
|
||||
dwell_mode = g_settings_get_enum (priv->mouse_a11y_settings, "dwell-mode");
|
||||
if (dwell_mode == G_DESKTOP_MOUSE_DWELL_MODE_WINDOW)
|
||||
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_WINDOW;
|
||||
else
|
||||
pointer_a11y_settings.dwell_mode = CLUTTER_A11Y_DWELL_MODE_GESTURE;
|
||||
|
||||
pointer_a11y_settings.dwell_gesture_single =
|
||||
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-single");
|
||||
pointer_a11y_settings.dwell_gesture_double =
|
||||
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-double");
|
||||
pointer_a11y_settings.dwell_gesture_drag =
|
||||
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-drag");
|
||||
pointer_a11y_settings.dwell_gesture_secondary =
|
||||
pointer_a11y_dwell_direction_from_setting (input_settings, "dwell-gesture-secondary");
|
||||
|
||||
clutter_seat_set_pointer_a11y_settings (CLUTTER_SEAT (priv->seat),
|
||||
&pointer_a11y_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_mouse_a11y_settings_changed (GSettings *settings,
|
||||
const char *key,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaInputSettings *input_settings = META_INPUT_SETTINGS (user_data);
|
||||
|
||||
load_pointer_a11y_settings (input_settings);
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_device_settings (ClutterInputDevice *device)
|
||||
{
|
||||
|
@ -1750,7 +1657,6 @@ meta_input_settings_constructed (GObject *object)
|
|||
check_mappable_devices (input_settings);
|
||||
|
||||
load_keyboard_a11y_settings (input_settings);
|
||||
load_pointer_a11y_settings (input_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1812,10 +1718,6 @@ meta_input_settings_init (MetaInputSettings *settings)
|
|||
g_signal_connect (priv->keyboard_a11y_settings, "changed",
|
||||
G_CALLBACK (meta_input_keyboard_a11y_settings_changed), settings);
|
||||
|
||||
priv->mouse_a11y_settings = g_settings_new ("org.gnome.desktop.a11y.mouse");
|
||||
g_signal_connect (priv->mouse_a11y_settings, "changed",
|
||||
G_CALLBACK (meta_input_mouse_a11y_settings_changed), settings);
|
||||
|
||||
priv->mappable_devices =
|
||||
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free);
|
||||
|
||||
|
|
Loading…
Reference in a new issue