commit a9233e9

Michael Forney  ·  2014-08-01 02:58:01 +0000 UTC
parent ec4e188
Reset keyboard state on session deactivation

This prevents an inconsistent state of the keyboard when the VT is
switched away with keys held down.
5 files changed,  +47, -0
+29, -0
 1@@ -31,6 +31,7 @@
 2 #include "keyboard.h"
 3 #include "util.h"
 4 
 5+#include <assert.h>
 6 #include <stdio.h>
 7 #include <string.h>
 8 
 9@@ -149,6 +150,34 @@ void keyboard_finalize(struct keyboard * keyboard)
10     xkb_finalize(&keyboard->xkb);
11 }
12 
13+void keyboard_reset(struct keyboard * keyboard)
14+{
15+    struct key * key;
16+    uint32_t time = swc_time();
17+
18+    /* Send simulated key release events for all current key handlers. */
19+    wl_array_for_each(key, &keyboard->keys)
20+    {
21+        if (key->handler)
22+        {
23+            key->press.serial = wl_display_next_serial(swc.display);
24+            key->handler->key(keyboard, time, &key->press,
25+                              WL_KEYBOARD_KEY_STATE_RELEASED);
26+            /* Don't bother updating the XKB state because we will be resetting
27+             * it later on and it is unlikely that a key handler cares about the
28+             * keyboard state for release events. */
29+        }
30+    }
31+
32+    /* We should have removed all the client keys by calling the client key
33+     * handler. */
34+    assert(keyboard->client_keys.size == 0);
35+    keyboard->keys.size = 0;
36+    keyboard->modifier_state = (struct keyboard_modifier_state) { };
37+    keyboard->modifiers = 0;
38+    xkb_reset_state(&keyboard->xkb);
39+}
40+
41 /**
42  * Sets the focus of the keyboard to the specified surface.
43  */
+1, -0
1@@ -74,6 +74,7 @@ struct keyboard
2 
3 bool keyboard_initialize(struct keyboard * keyboard);
4 void keyboard_finalize(struct keyboard * keyboard);
5+void keyboard_reset(struct keyboard * keyboard);
6 void keyboard_set_focus(struct keyboard * keyboard,
7                         struct compositor_view * view);
8 struct wl_resource * keyboard_bind(struct keyboard * keyboard,
+1, -0
1@@ -146,6 +146,7 @@ static void handle_launch_event(struct wl_listener * listener, void * data)
2 #ifdef ENABLE_LIBINPUT
3             libinput_suspend(seat.libinput);
4 #endif
5+            keyboard_reset(&seat.keyboard);
6             break;
7         case SWC_LAUNCH_EVENT_ACTIVATED:
8         {
+15, -0
 1@@ -89,6 +89,21 @@ void xkb_finalize(struct xkb * xkb)
 2     xkb_context_unref(xkb->context);
 3 }
 4 
 5+bool xkb_reset_state(struct xkb * xkb)
 6+{
 7+    struct xkb_state * state;
 8+
 9+    if (!(state = xkb_state_new(xkb->keymap.map)))
10+    {
11+        ERROR("Failed to allocate new XKB state\n");
12+        return false;
13+    }
14+
15+    xkb_state_unref(xkb->state);
16+    xkb->state = state;
17+    return true;
18+}
19+
20 bool xkb_update_keymap(struct xkb * xkb)
21 {
22     const char * keymap_directory = getenv("XDG_RUNTIME_DIR") ?: "/tmp";
+1, -0
1@@ -51,6 +51,7 @@ struct xkb
2 
3 bool xkb_initialize(struct xkb * xkb);
4 void xkb_finalize(struct xkb * xkb);
5+bool xkb_reset_state(struct xkb * xkb);
6 
7 bool xkb_update_keymap(struct xkb * xkb);
8