You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
260 lines
10 KiB
260 lines
10 KiB
From a1f33bdac95ba4fd0599f164ef893c05d8be123b Mon Sep 17 00:00:00 2001 |
|
From: Ray Strode <rstrode@redhat.com> |
|
Date: Wed, 6 Oct 2021 15:31:30 -0400 |
|
Subject: [PATCH] backends/x11: Fix key repeat of on-screen keyboard for second |
|
level keysyms |
|
|
|
Certains keys (such as ~ and |) are in the keyboard map behind the |
|
second shift level. This means in order for them to be input, the |
|
shift key needs to be held down by the user. |
|
|
|
The GNOME Shell on-screen keyboard presents these keys separately on |
|
a page of keys that has no shift key. Instead, it relies on mutter |
|
to set a shift latch before the key event is emitted. A shift latch |
|
is a virtual press of the shift key that automatically gets released |
|
after the next key press (in our case the ~ or | key). |
|
|
|
The problem is using a shift latch doesn't work very well in the face |
|
of key repeat. The latch is automatically released after the first |
|
press, and subsequent repeats of that press no longer have shift |
|
latched to them. |
|
|
|
This commit fixes the problem by using a shift lock instead of a shift |
|
latch. A shift lock is never implicitly released, so it remains |
|
in place for the duration of key repeat. |
|
--- |
|
src/backends/x11/meta-keymap-x11.c | 12 ++++++------ |
|
src/backends/x11/meta-keymap-x11.h | 6 +++--- |
|
src/backends/x11/meta-virtual-input-device-x11.c | 4 ++-- |
|
3 files changed, 11 insertions(+), 11 deletions(-) |
|
|
|
diff --git a/src/backends/x11/meta-keymap-x11.c b/src/backends/x11/meta-keymap-x11.c |
|
index da5d064e7..1192cc387 100644 |
|
--- a/src/backends/x11/meta-keymap-x11.c |
|
+++ b/src/backends/x11/meta-keymap-x11.c |
|
@@ -829,85 +829,85 @@ meta_keymap_x11_reserve_keycode (MetaKeymapX11 *keymap_x11, |
|
g_warning ("Cannot reserve a keycode for keyval %d: no available keycode", keyval); |
|
return FALSE; |
|
} |
|
|
|
if (!meta_keymap_x11_replace_keycode (keymap_x11, *keycode_out, keyval)) |
|
{ |
|
g_warning ("Failed to remap keycode %d to keyval %d", *keycode_out, keyval); |
|
return FALSE; |
|
} |
|
|
|
g_hash_table_insert (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (*keycode_out), GUINT_TO_POINTER (keyval)); |
|
g_queue_remove (keymap_x11->available_keycodes, GUINT_TO_POINTER (*keycode_out)); |
|
|
|
return TRUE; |
|
} |
|
|
|
void |
|
meta_keymap_x11_release_keycode_if_needed (MetaKeymapX11 *keymap_x11, |
|
uint32_t keycode) |
|
{ |
|
g_return_if_fail (META_IS_KEYMAP_X11 (keymap_x11)); |
|
|
|
if (!g_hash_table_contains (keymap_x11->reserved_keycodes, GUINT_TO_POINTER (keycode)) || |
|
g_queue_index (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)) != -1) |
|
return; |
|
|
|
g_queue_push_tail (keymap_x11->available_keycodes, GUINT_TO_POINTER (keycode)); |
|
} |
|
|
|
void |
|
-meta_keymap_x11_latch_modifiers (MetaKeymapX11 *keymap_x11, |
|
- uint32_t level, |
|
- gboolean enable) |
|
+meta_keymap_x11_lock_modifiers (MetaKeymapX11 *keymap_x11, |
|
+ uint32_t level, |
|
+ gboolean enable) |
|
{ |
|
uint32_t modifiers[] = { |
|
0, |
|
ShiftMask, |
|
keymap_x11->level3_shift_mask, |
|
keymap_x11->level3_shift_mask | ShiftMask, |
|
}; |
|
uint32_t value = 0; |
|
|
|
if (!keymap_x11->use_xkb) |
|
return; |
|
|
|
level = CLAMP (level, 0, G_N_ELEMENTS (modifiers) - 1); |
|
|
|
if (enable) |
|
value = modifiers[level]; |
|
else |
|
value = 0; |
|
|
|
- XkbLatchModifiers (clutter_x11_get_default_display (), |
|
- XkbUseCoreKbd, modifiers[level], |
|
- value); |
|
+ XkbLockModifiers (clutter_x11_get_default_display (), |
|
+ XkbUseCoreKbd, modifiers[level], |
|
+ value); |
|
} |
|
|
|
static uint32_t |
|
meta_keymap_x11_get_current_group (MetaKeymapX11 *keymap_x11) |
|
{ |
|
XkbStateRec state_rec; |
|
|
|
if (keymap_x11->current_group >= 0) |
|
return keymap_x11->current_group; |
|
|
|
XkbGetState (clutter_x11_get_default_display (), |
|
XkbUseCoreKbd, &state_rec); |
|
return XkbStateGroup (&state_rec); |
|
} |
|
|
|
gboolean |
|
meta_keymap_x11_keycode_for_keyval (MetaKeymapX11 *keymap_x11, |
|
uint32_t keyval, |
|
uint32_t *keycode_out, |
|
uint32_t *level_out) |
|
{ |
|
ClutterKeymapKey *keys; |
|
int i, n_keys, group; |
|
gboolean found = FALSE; |
|
|
|
g_return_val_if_fail (keycode_out != NULL, FALSE); |
|
g_return_val_if_fail (level_out != NULL, FALSE); |
|
|
|
group = meta_keymap_x11_get_current_group (keymap_x11); |
|
|
|
diff --git a/src/backends/x11/meta-keymap-x11.h b/src/backends/x11/meta-keymap-x11.h |
|
index 67a5f8eb9..2f93acdbc 100644 |
|
--- a/src/backends/x11/meta-keymap-x11.h |
|
+++ b/src/backends/x11/meta-keymap-x11.h |
|
@@ -17,45 +17,45 @@ |
|
* Author: Emmanuele Bassi <ebassi@linux.intel.com> |
|
*/ |
|
|
|
#ifndef META_KEYMAP_X11_H |
|
#define META_KEYMAP_X11_H |
|
|
|
#include <glib-object.h> |
|
#include <pango/pango.h> |
|
|
|
#include "clutter/clutter.h" |
|
|
|
G_BEGIN_DECLS |
|
|
|
#define META_TYPE_KEYMAP_X11 (meta_keymap_x11_get_type ()) |
|
G_DECLARE_FINAL_TYPE (MetaKeymapX11, meta_keymap_x11, |
|
META, KEYMAP_X11, ClutterKeymap) |
|
|
|
int meta_keymap_x11_get_key_group (MetaKeymapX11 *keymap, |
|
ClutterModifierType state); |
|
int meta_keymap_x11_translate_key_state (MetaKeymapX11 *keymap, |
|
guint hardware_keycode, |
|
ClutterModifierType *modifier_state_p, |
|
ClutterModifierType *mods_p); |
|
gboolean meta_keymap_x11_get_is_modifier (MetaKeymapX11 *keymap, |
|
int keycode); |
|
|
|
gboolean meta_keymap_x11_keycode_for_keyval (MetaKeymapX11 *keymap_x11, |
|
guint keyval, |
|
guint *keycode_out, |
|
guint *level_out); |
|
-void meta_keymap_x11_latch_modifiers (MetaKeymapX11 *keymap_x11, |
|
- uint32_t level, |
|
- gboolean enable); |
|
+void meta_keymap_x11_lock_modifiers (MetaKeymapX11 *keymap_x11, |
|
+ uint32_t level, |
|
+ gboolean enable); |
|
gboolean meta_keymap_x11_reserve_keycode (MetaKeymapX11 *keymap_x11, |
|
guint keyval, |
|
guint *keycode_out); |
|
void meta_keymap_x11_release_keycode_if_needed (MetaKeymapX11 *keymap_x11, |
|
guint keycode); |
|
|
|
gboolean meta_keymap_x11_handle_event (MetaKeymapX11 *keymap_x11, |
|
XEvent *xevent); |
|
|
|
G_END_DECLS |
|
|
|
#endif /* META_KEYMAP_X11_H */ |
|
diff --git a/src/backends/x11/meta-virtual-input-device-x11.c b/src/backends/x11/meta-virtual-input-device-x11.c |
|
index fe6040859..1a5cdfc2e 100644 |
|
--- a/src/backends/x11/meta-virtual-input-device-x11.c |
|
+++ b/src/backends/x11/meta-virtual-input-device-x11.c |
|
@@ -159,71 +159,71 @@ meta_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_dev |
|
ClutterKeyState key_state) |
|
{ |
|
XTestFakeKeyEvent (clutter_x11_get_default_display (), |
|
key + 8, key_state == CLUTTER_KEY_STATE_PRESSED, 0); |
|
} |
|
|
|
static void |
|
meta_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtual_device, |
|
uint64_t time_us, |
|
uint32_t keyval, |
|
ClutterKeyState key_state) |
|
{ |
|
ClutterBackend *backend = clutter_get_default_backend (); |
|
ClutterSeat *seat = clutter_backend_get_default_seat (backend); |
|
MetaKeymapX11 *keymap = META_KEYMAP_X11 (clutter_seat_get_keymap (seat)); |
|
uint32_t keycode, level; |
|
|
|
if (!meta_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level)) |
|
{ |
|
level = 0; |
|
|
|
if (!meta_keymap_x11_reserve_keycode (keymap, keyval, &keycode)) |
|
{ |
|
g_warning ("No keycode found for keyval %x in current group", keyval); |
|
return; |
|
} |
|
} |
|
|
|
if (!meta_keymap_x11_get_is_modifier (keymap, keycode) && |
|
key_state == CLUTTER_KEY_STATE_PRESSED) |
|
- meta_keymap_x11_latch_modifiers (keymap, level, TRUE); |
|
+ meta_keymap_x11_lock_modifiers (keymap, level, TRUE); |
|
|
|
XTestFakeKeyEvent (clutter_x11_get_default_display (), |
|
(KeyCode) keycode, |
|
key_state == CLUTTER_KEY_STATE_PRESSED, 0); |
|
|
|
|
|
if (key_state == CLUTTER_KEY_STATE_RELEASED) |
|
{ |
|
if (!meta_keymap_x11_get_is_modifier (keymap, keycode)) |
|
- meta_keymap_x11_latch_modifiers (keymap, level, FALSE); |
|
+ meta_keymap_x11_lock_modifiers (keymap, level, FALSE); |
|
meta_keymap_x11_release_keycode_if_needed (keymap, keycode); |
|
} |
|
} |
|
|
|
static void |
|
meta_virtual_input_device_x11_notify_touch_down (ClutterVirtualInputDevice *virtual_device, |
|
uint64_t time_us, |
|
int device_slot, |
|
double x, |
|
double y) |
|
{ |
|
g_warning ("Virtual touch motion not implemented under X11"); |
|
} |
|
|
|
static void |
|
meta_virtual_input_device_x11_notify_touch_motion (ClutterVirtualInputDevice *virtual_device, |
|
uint64_t time_us, |
|
int device_slot, |
|
double x, |
|
double y) |
|
{ |
|
g_warning ("Virtual touch motion not implemented under X11"); |
|
} |
|
|
|
static void |
|
meta_virtual_input_device_x11_notify_touch_up (ClutterVirtualInputDevice *virtual_device, |
|
uint64_t time_us, |
|
int device_slot) |
|
{ |
|
g_warning ("Virtual touch motion not implemented under X11"); |
|
-- |
|
2.33.1 |
|
|
|
|