summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColomban Wendling <[email protected]>2020-06-11 11:56:29 +0200
committerRobert Antoni Buj Gelonch <[email protected]>2020-09-05 18:02:41 +0200
commit69a67a7f04fc5c0e36a290ad7a3e7afb4e801083 (patch)
tree0b1772b4f71e37a1ce3cf1235dd43d6fe43c20c7
parent724206c586046ee313ede4c2da85e03149fb8c27 (diff)
downloadmate-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.c63
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 */