mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:17 +00:00
ui/kbd-state: Use Linux key codes
QemuInputEvent now stores Linux key codes for key events. Use those codes directly instead of translating between internal key code representations. Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-ID: <20260520-input-v3-7-7c9e4c7abe34@rsg.ci.i.u-tokyo.ac.jp>
This commit is contained in:
committed by
Marc-André Lureau
parent
eb0608e88e
commit
9c6833808a
@@ -52,11 +52,13 @@ void qkbd_state_free(QKbdState *kbd);
|
||||
* This function takes care to not send suspious events (keyup event
|
||||
* for a key not pressed for example).
|
||||
*
|
||||
* This function drops events with key codes outside the defined range.
|
||||
*
|
||||
* @kbd: state tracker state.
|
||||
* @qcode: the key pressed or released.
|
||||
* @lnx: the key pressed or released.
|
||||
* @down: true for key down events, false otherwise.
|
||||
*/
|
||||
void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down);
|
||||
void qkbd_state_key_event(QKbdState *kbd, unsigned int lnx, bool down);
|
||||
|
||||
/**
|
||||
* qkbd_state_set_delay: set key press delay.
|
||||
@@ -72,12 +74,12 @@ void qkbd_state_set_delay(QKbdState *kbd, int delay_ms);
|
||||
/**
|
||||
* qkbd_state_key_get: get key state.
|
||||
*
|
||||
* Returns true when the key is down.
|
||||
* Returns true when the key code is in the defined range and the key is down.
|
||||
*
|
||||
* @kbd: state tracker state.
|
||||
* @qcode: the key to query.
|
||||
* @lnx: the key to query.
|
||||
*/
|
||||
bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode);
|
||||
bool qkbd_state_key_get(QKbdState *kbd, unsigned int lnx);
|
||||
|
||||
/**
|
||||
* qkbd_state_modifier_get: get modifier state.
|
||||
|
||||
67
ui/cocoa.m
67
ui/cocoa.m
@@ -767,7 +767,8 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
|
||||
}
|
||||
|
||||
- (void) toggleKey: (int)keycode {
|
||||
qkbd_state_key_event(kbd, keycode, !qkbd_state_key_get(kbd, keycode));
|
||||
unsigned int lnx = qemu_input_map_qcode_to_linux[keycode];
|
||||
qkbd_state_key_event(kbd, lnx, !qkbd_state_key_get(kbd, lnx));
|
||||
}
|
||||
|
||||
// Does the work of sending input to the monitor
|
||||
@@ -889,34 +890,62 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
|
||||
*/
|
||||
if (!!(modifiers & NSEventModifierFlagCapsLock) !=
|
||||
qkbd_state_modifier_get(kbd, QKBD_MOD_CAPSLOCK)) {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_CAPS_LOCK, true);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_CAPS_LOCK, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_CAPS_LOCK],
|
||||
true);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_CAPS_LOCK],
|
||||
false);
|
||||
}
|
||||
|
||||
if (!(modifiers & NSEventModifierFlagShift)) {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_SHIFT, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_SHIFT_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_SHIFT],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_SHIFT_R],
|
||||
false);
|
||||
}
|
||||
if (!(modifiers & NSEventModifierFlagControl)) {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_CTRL_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_CTRL],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_CTRL_R],
|
||||
false);
|
||||
}
|
||||
if (!(modifiers & NSEventModifierFlagOption)) {
|
||||
if (swap_opt_cmd) {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_META_L],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_META_R],
|
||||
false);
|
||||
} else {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_ALT],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_ALT_R],
|
||||
false);
|
||||
}
|
||||
}
|
||||
if (!(modifiers & NSEventModifierFlagCommand)) {
|
||||
if (swap_opt_cmd) {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_ALT, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_ALT_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_ALT],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_ALT_R],
|
||||
false);
|
||||
} else {
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_META_L, false);
|
||||
qkbd_state_key_event(kbd, Q_KEY_CODE_META_R, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_META_L],
|
||||
false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_META_R],
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1023,7 +1052,9 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
|
||||
}
|
||||
|
||||
if (qemu_console_is_graphic(dcl.con)) {
|
||||
qkbd_state_key_event(kbd, keycode, true);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[keycode],
|
||||
true);
|
||||
} else {
|
||||
[self handleMonitorInput: event];
|
||||
}
|
||||
@@ -1038,7 +1069,9 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven
|
||||
}
|
||||
|
||||
if (qemu_console_is_graphic(dcl.con)) {
|
||||
qkbd_state_key_event(kbd, keycode, false);
|
||||
qkbd_state_key_event(kbd,
|
||||
qemu_input_map_qcode_to_linux[keycode],
|
||||
false);
|
||||
}
|
||||
return true;
|
||||
case NSEventTypeScrollWheel:
|
||||
|
||||
@@ -343,7 +343,7 @@ dbus_kbd_press(DBusDisplayConsole *ddc,
|
||||
|
||||
trace_dbus_kbd_press(arg_keycode);
|
||||
|
||||
qkbd_state_key_event(ddc->kbd, qcode, true);
|
||||
qkbd_state_key_event(ddc->kbd, qemu_input_map_qcode_to_linux[qcode], true);
|
||||
|
||||
qemu_dbus_display1_keyboard_complete_press(ddc->iface_kbd, invocation);
|
||||
|
||||
@@ -359,7 +359,7 @@ dbus_kbd_release(DBusDisplayConsole *ddc,
|
||||
|
||||
trace_dbus_kbd_release(arg_keycode);
|
||||
|
||||
qkbd_state_key_event(ddc->kbd, qcode, false);
|
||||
qkbd_state_key_event(ddc->kbd, qemu_input_map_qcode_to_linux[qcode], false);
|
||||
|
||||
qemu_dbus_display1_keyboard_complete_release(ddc->iface_kbd, invocation);
|
||||
|
||||
|
||||
7
ui/gtk.c
7
ui/gtk.c
@@ -1343,7 +1343,8 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
|
||||
|| key->hardware_keycode == VK_PAUSE
|
||||
#endif
|
||||
) {
|
||||
qkbd_state_key_event(vc->gfx.kbd, Q_KEY_CODE_PAUSE,
|
||||
qkbd_state_key_event(vc->gfx.kbd,
|
||||
qemu_input_map_qcode_to_linux[Q_KEY_CODE_PAUSE],
|
||||
key->type == GDK_KEY_PRESS);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1351,10 +1352,10 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
|
||||
keycode = gd_get_keycode(key);
|
||||
qcode = gd_map_keycode(keycode);
|
||||
|
||||
trace_gd_key_event(vc->label, keycode, qcode,
|
||||
trace_gd_key_event(vc->label, keycode, qemu_input_map_qcode_to_linux[qcode],
|
||||
(key->type == GDK_KEY_PRESS) ? "down" : "up");
|
||||
|
||||
qkbd_state_key_event(vc->gfx.kbd, qcode,
|
||||
qkbd_state_key_event(vc->gfx.kbd, qemu_input_map_qcode_to_linux[qcode],
|
||||
key->type == GDK_KEY_PRESS);
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "standard-headers/linux/input-event-codes.h"
|
||||
#include "ui/console.h"
|
||||
#include "ui/input.h"
|
||||
#include "ui/kbd-state.h"
|
||||
@@ -12,15 +13,15 @@
|
||||
struct QKbdState {
|
||||
QemuConsole *con;
|
||||
int key_delay_ms;
|
||||
DECLARE_BITMAP(keys, Q_KEY_CODE__MAX);
|
||||
DECLARE_BITMAP(keys, KEY_CNT);
|
||||
DECLARE_BITMAP(mods, QKBD_MOD__MAX);
|
||||
};
|
||||
|
||||
static void qkbd_state_modifier_update(QKbdState *kbd,
|
||||
QKeyCode qcode1, QKeyCode qcode2,
|
||||
unsigned int lnx1, unsigned int lnx2,
|
||||
QKbdModifier mod)
|
||||
{
|
||||
if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) {
|
||||
if (test_bit(lnx1, kbd->keys) || test_bit(lnx2, kbd->keys)) {
|
||||
set_bit(mod, kbd->mods);
|
||||
} else {
|
||||
clear_bit(mod, kbd->mods);
|
||||
@@ -32,14 +33,20 @@ bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod)
|
||||
return test_bit(mod, kbd->mods);
|
||||
}
|
||||
|
||||
bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode)
|
||||
bool qkbd_state_key_get(QKbdState *kbd, unsigned int lnx)
|
||||
{
|
||||
return test_bit(qcode, kbd->keys);
|
||||
return lnx < KEY_CNT && test_bit(lnx, kbd->keys);
|
||||
}
|
||||
|
||||
void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||
void qkbd_state_key_event(QKbdState *kbd, unsigned int lnx, bool down)
|
||||
{
|
||||
bool state = test_bit(qcode, kbd->keys);
|
||||
bool state;
|
||||
|
||||
if (lnx >= KEY_CNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
state = test_bit(lnx, kbd->keys);
|
||||
|
||||
if (down == false /* got key-up event */ &&
|
||||
state == false /* key is not pressed */) {
|
||||
@@ -59,35 +66,35 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||
|
||||
/* update key and modifier state */
|
||||
if (down) {
|
||||
set_bit(qcode, kbd->keys);
|
||||
set_bit(lnx, kbd->keys);
|
||||
} else {
|
||||
clear_bit(qcode, kbd->keys);
|
||||
clear_bit(lnx, kbd->keys);
|
||||
}
|
||||
switch (qcode) {
|
||||
case Q_KEY_CODE_SHIFT:
|
||||
case Q_KEY_CODE_SHIFT_R:
|
||||
qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_R,
|
||||
switch (lnx) {
|
||||
case KEY_LEFTSHIFT:
|
||||
case KEY_RIGHTSHIFT:
|
||||
qkbd_state_modifier_update(kbd, KEY_LEFTSHIFT, KEY_RIGHTSHIFT,
|
||||
QKBD_MOD_SHIFT);
|
||||
break;
|
||||
case Q_KEY_CODE_CTRL:
|
||||
case Q_KEY_CODE_CTRL_R:
|
||||
qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R,
|
||||
case KEY_LEFTCTRL:
|
||||
case KEY_RIGHTCTRL:
|
||||
qkbd_state_modifier_update(kbd, KEY_LEFTCTRL, KEY_RIGHTCTRL,
|
||||
QKBD_MOD_CTRL);
|
||||
break;
|
||||
case Q_KEY_CODE_ALT:
|
||||
qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT,
|
||||
case KEY_LEFTALT:
|
||||
qkbd_state_modifier_update(kbd, KEY_LEFTALT, KEY_LEFTALT,
|
||||
QKBD_MOD_ALT);
|
||||
break;
|
||||
case Q_KEY_CODE_ALT_R:
|
||||
qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R,
|
||||
case KEY_RIGHTALT:
|
||||
qkbd_state_modifier_update(kbd, KEY_RIGHTALT, KEY_RIGHTALT,
|
||||
QKBD_MOD_ALTGR);
|
||||
break;
|
||||
case Q_KEY_CODE_CAPS_LOCK:
|
||||
case KEY_CAPSLOCK:
|
||||
if (down) {
|
||||
change_bit(QKBD_MOD_CAPSLOCK, kbd->mods);
|
||||
}
|
||||
break;
|
||||
case Q_KEY_CODE_NUM_LOCK:
|
||||
case KEY_NUMLOCK:
|
||||
if (down) {
|
||||
change_bit(QKBD_MOD_NUMLOCK, kbd->mods);
|
||||
}
|
||||
@@ -99,7 +106,7 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||
|
||||
/* send to guest */
|
||||
if (qemu_console_is_graphic(kbd->con)) {
|
||||
qemu_input_event_send_key_qcode(kbd->con, qcode, down);
|
||||
qemu_input_event_send_key_linux(kbd->con, lnx, down);
|
||||
if (kbd->key_delay_ms) {
|
||||
qemu_input_event_send_key_delay(kbd->key_delay_ms);
|
||||
}
|
||||
@@ -108,11 +115,11 @@ void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
|
||||
|
||||
void qkbd_state_lift_all_keys(QKbdState *kbd)
|
||||
{
|
||||
int qcode;
|
||||
unsigned int lnx;
|
||||
|
||||
for (qcode = 0; qcode < Q_KEY_CODE__MAX; qcode++) {
|
||||
if (test_bit(qcode, kbd->keys)) {
|
||||
qkbd_state_key_event(kbd, qcode, false);
|
||||
for (lnx = 0; lnx < KEY_CNT; lnx++) {
|
||||
if (test_bit(lnx, kbd->keys)) {
|
||||
qkbd_state_key_event(kbd, lnx, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,8 @@ int keysym2scancode(kbd_layout_t *k, int keysym,
|
||||
for (i = 0; i < keysym2code->count; i++) {
|
||||
QKeyCode qcode = qemu_input_key_number_to_qcode
|
||||
(keysym2code->keycodes[i]);
|
||||
if (kbd && qkbd_state_key_get(kbd, qcode)) {
|
||||
unsigned int lnx = qemu_input_map_qcode_to_linux[qcode];
|
||||
if (kbd && qkbd_state_key_get(kbd, lnx)) {
|
||||
return keysym2code->keycodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@ void sdl2_process_key(struct sdl2_console *scon,
|
||||
qcode = qemu_input_map_usb_to_qcode[ev->keysym.scancode];
|
||||
trace_sdl2_process_key(ev->keysym.scancode, qcode,
|
||||
ev->type == SDL_KEYDOWN ? "down" : "up");
|
||||
qkbd_state_key_event(scon->kbd, qcode, ev->type == SDL_KEYDOWN);
|
||||
qkbd_state_key_event(scon->kbd, qemu_input_map_qcode_to_linux[qcode],
|
||||
ev->type == SDL_KEYDOWN);
|
||||
|
||||
if (QEMU_IS_TEXT_CONSOLE(con)) {
|
||||
QemuTextConsole *s = QEMU_TEXT_CONSOLE(con);
|
||||
|
||||
10
ui/vnc.c
10
ui/vnc.c
@@ -1799,8 +1799,11 @@ static void pointer_event(VncState *vs, int button_mask, int x, int y)
|
||||
|
||||
static void press_key(VncState *vs, QKeyCode qcode)
|
||||
{
|
||||
qkbd_state_key_event(vs->vd->kbd, qcode, true);
|
||||
qkbd_state_key_event(vs->vd->kbd, qcode, false);
|
||||
qkbd_state_key_event(vs->vd->kbd, qemu_input_map_qcode_to_linux[qcode],
|
||||
true);
|
||||
|
||||
qkbd_state_key_event(vs->vd->kbd, qemu_input_map_qcode_to_linux[qcode],
|
||||
false);
|
||||
}
|
||||
|
||||
static void vnc_led_state_change(VncState *vs)
|
||||
@@ -1907,7 +1910,8 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
|
||||
}
|
||||
}
|
||||
|
||||
qkbd_state_key_event(vs->vd->kbd, qcode, down);
|
||||
qkbd_state_key_event(vs->vd->kbd, qemu_input_map_qcode_to_linux[qcode],
|
||||
down);
|
||||
if (QEMU_IS_TEXT_CONSOLE(vs->vd->dcl.con)) {
|
||||
QemuTextConsole *con = QEMU_TEXT_CONSOLE(vs->vd->dcl.con);
|
||||
bool numlock = qkbd_state_modifier_get(vs->vd->kbd, QKBD_MOD_NUMLOCK);
|
||||
|
||||
Reference in New Issue
Block a user