diff options
author | Colomban Wendling <[email protected]> | 2020-06-11 11:56:29 +0200 |
---|---|---|
committer | Robert Antoni Buj Gelonch <[email protected]> | 2020-09-05 18:02:41 +0200 |
commit | 69a67a7f04fc5c0e36a290ad7a3e7afb4e801083 (patch) | |
tree | 0b1772b4f71e37a1ce3cf1235dd43d6fe43c20c7 | |
parent | 724206c586046ee313ede4c2da85e03149fb8c27 (diff) | |
download | mate-settings-daemon-69a67a7f04fc5c0e36a290ad7a3e7afb4e801083.tar.bz2 mate-settings-daemon-69a67a7f04fc5c0e36a290ad7a3e7afb4e801083.tar.xz |
a11y-keyboard: Manually beep for togglekeys
This allows a customizable and possibly different beep sequence when a
togglekey is enabled or disabled. This is very useful for the user to
know for sure whether the feature got enabled or disabled.
Back in the days of buzzers, XKB was supposed to use different sounds
for each of those, but this is no longer the case now in the vast
majority of setups the beeps are intercepted and use a single recorded
sound.
XKB beeps are also unfortunately not configurable, although they
possibly should be on paper: in theory, one could alter the bell used
by listening to `XkbBellNotify` events, which provides a way to
discriminate bells through a name. Unfortunately XKB's togglekeys
seems to suffer from a bug (?) for a long time, in that it will always
ring the `AX_IndicatorOn` bell if there is *at least one* indicator on
at the moment the bell is rung, and `AX_IndicatorOff` if and only if
*all* indicators are off. This makes it virtually useless as it is not
possible to discriminate between an indicator getting turned on or off
in most cases, especially with NumLock which often stays always on.
Given this behavior dates at the very least as far back as X.org 1.16
which is from 2014, it probably is not very realistic to rely on a fix.
So instead implement togglekeys on our end by listening to the
`XkbIndicatorStateNotify` events.
-rw-r--r-- | plugins/a11y-keyboard/msd-a11y-keyboard-manager.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/plugins/a11y-keyboard/msd-a11y-keyboard-manager.c b/plugins/a11y-keyboard/msd-a11y-keyboard-manager.c index e448afc..06e8586 100644 --- a/plugins/a11y-keyboard/msd-a11y-keyboard-manager.c +++ b/plugins/a11y-keyboard/msd-a11y-keyboard-manager.c @@ -957,6 +957,53 @@ set_settings_from_server (MsdA11yKeyboardManager *manager) g_object_unref (settings); } +typedef struct { + GdkDisplay *display; + gint count; +} BeepSequenceData; + +static gboolean +on_beep_dequence_timeout (gpointer user_data) +{ + BeepSequenceData *data = user_data; + + gdk_display_beep (data->display); + data->count--; + + return data->count > 0; +} + +static void +beep_sequence (MsdA11yKeyboardManager *manager, + GdkDisplay *display, + gint count, + gint delay) +{ + g_return_if_fail (MSD_IS_A11Y_KEYBOARD_MANAGER (manager)); + + if (count < 1) + return; + + if (! display) + display = gdk_display_get_default (); + + gdk_display_beep (display); + if (count > 1) { + BeepSequenceData *data = g_malloc (sizeof *data); + + data->display = display; + data->count = count - 1; + + /* don't allow a delay below 50ms, it doesn't make much sense + * anyway and is more likely to be a broken setting */ + g_warn_if_fail (delay >= 50); + delay = MAX (delay, 50); + + g_timeout_add_full (G_PRIORITY_DEFAULT, (guint) delay, + on_beep_dequence_timeout, data, g_free); + } +} + static GdkFilterReturn cb_xkb_event_filter (GdkXEvent *xevent, GdkEvent *ignored1, @@ -979,6 +1026,21 @@ cb_xkb_event_filter (GdkXEvent *xevent, * set_settings_from_server(). */ } + } else if (xev->xany.type == (manager->priv->xkbEventBase + XkbEventCode) && + xkbEv->any.xkb_type == XkbIndicatorStateNotify && + g_settings_get_boolean (manager->priv->settings, "togglekeys-enable")) { + GdkDisplay *display = gdk_x11_lookup_xdisplay (xkbEv->any.display); + gint beep_count; + gint beep_delay; + + if (xkbEv->indicators.state & xkbEv->indicators.changed) { + beep_count = g_settings_get_int (manager->priv->settings, "togglekeys-enable-beep-count"); + beep_delay = g_settings_get_int (manager->priv->settings, "togglekeys-enable-beep-delay"); + } else { + beep_count = g_settings_get_int (manager->priv->settings, "togglekeys-disable-beep-count"); + beep_delay = g_settings_get_int (manager->priv->settings, "togglekeys-disable-beep-delay"); + } + beep_sequence (manager, display, beep_count, beep_delay); } return GDK_FILTER_CONTINUE; @@ -1036,6 +1098,7 @@ start_a11y_keyboard_idle_cb (MsdA11yKeyboardManager *manager) manager->priv->original_xkb_desc = get_xkb_desc_rec (manager); event_mask = XkbControlsNotifyMask; + event_mask |= XkbIndicatorStateNotifyMask; #ifdef MATE_ENABLE_DEBUG event_mask |= XkbAccessXNotifyMask; /* make default when AXN_AXKWarning works */ #endif /* MATE_ENABLE_DEBUG */ |