qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

kbd-state.c (3691B)


      1 /*
      2  * This work is licensed under the terms of the GNU GPL, version 2 or
      3  * (at your option) any later version.  See the COPYING file in the
      4  * top-level directory.
      5  */
      6 #include "qemu/osdep.h"
      7 #include "qemu/bitmap.h"
      8 #include "ui/console.h"
      9 #include "ui/input.h"
     10 #include "ui/kbd-state.h"
     11 
     12 struct QKbdState {
     13     QemuConsole *con;
     14     int key_delay_ms;
     15     DECLARE_BITMAP(keys, Q_KEY_CODE__MAX);
     16     DECLARE_BITMAP(mods, QKBD_MOD__MAX);
     17 };
     18 
     19 static void qkbd_state_modifier_update(QKbdState *kbd,
     20                                       QKeyCode qcode1, QKeyCode qcode2,
     21                                       QKbdModifier mod)
     22 {
     23     if (test_bit(qcode1, kbd->keys) || test_bit(qcode2, kbd->keys)) {
     24         set_bit(mod, kbd->mods);
     25     } else {
     26         clear_bit(mod, kbd->mods);
     27     }
     28 }
     29 
     30 bool qkbd_state_modifier_get(QKbdState *kbd, QKbdModifier mod)
     31 {
     32     return test_bit(mod, kbd->mods);
     33 }
     34 
     35 bool qkbd_state_key_get(QKbdState *kbd, QKeyCode qcode)
     36 {
     37     return test_bit(qcode, kbd->keys);
     38 }
     39 
     40 void qkbd_state_key_event(QKbdState *kbd, QKeyCode qcode, bool down)
     41 {
     42     bool state = test_bit(qcode, kbd->keys);
     43 
     44     if (down == false  /* got key-up event   */ &&
     45         state == false /* key is not pressed */) {
     46         /*
     47          * Filter out suspicious key-up events.
     48          *
     49          * This allows simply sending along all key-up events, and
     50          * this function will filter out everything where the
     51          * corresponding key-down event wasn't sent to the guest, for
     52          * example due to being a host hotkey.
     53          *
     54          * Note that key-down events on already pressed keys are *not*
     55          * suspicious, those are keyboard autorepeat events.
     56          */
     57         return;
     58     }
     59 
     60     /* update key and modifier state */
     61     if (down) {
     62         set_bit(qcode, kbd->keys);
     63     } else {
     64         clear_bit(qcode, kbd->keys);
     65     }
     66     switch (qcode) {
     67     case Q_KEY_CODE_SHIFT:
     68     case Q_KEY_CODE_SHIFT_R:
     69         qkbd_state_modifier_update(kbd, Q_KEY_CODE_SHIFT, Q_KEY_CODE_SHIFT_R,
     70                                    QKBD_MOD_SHIFT);
     71         break;
     72     case Q_KEY_CODE_CTRL:
     73     case Q_KEY_CODE_CTRL_R:
     74         qkbd_state_modifier_update(kbd, Q_KEY_CODE_CTRL, Q_KEY_CODE_CTRL_R,
     75                                    QKBD_MOD_CTRL);
     76         break;
     77     case Q_KEY_CODE_ALT:
     78         qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT, Q_KEY_CODE_ALT,
     79                                    QKBD_MOD_ALT);
     80         break;
     81     case Q_KEY_CODE_ALT_R:
     82         qkbd_state_modifier_update(kbd, Q_KEY_CODE_ALT_R, Q_KEY_CODE_ALT_R,
     83                                    QKBD_MOD_ALTGR);
     84         break;
     85     case Q_KEY_CODE_CAPS_LOCK:
     86         if (down) {
     87             change_bit(QKBD_MOD_CAPSLOCK, kbd->mods);
     88         }
     89         break;
     90     case Q_KEY_CODE_NUM_LOCK:
     91         if (down) {
     92             change_bit(QKBD_MOD_NUMLOCK, kbd->mods);
     93         }
     94         break;
     95     default:
     96         /* keep gcc happy */
     97         break;
     98     }
     99 
    100     /* send to guest */
    101     if (qemu_console_is_graphic(kbd->con)) {
    102         qemu_input_event_send_key_qcode(kbd->con, qcode, down);
    103         if (kbd->key_delay_ms) {
    104             qemu_input_event_send_key_delay(kbd->key_delay_ms);
    105         }
    106     }
    107 }
    108 
    109 void qkbd_state_lift_all_keys(QKbdState *kbd)
    110 {
    111     int qcode;
    112 
    113     for (qcode = 0; qcode < Q_KEY_CODE__MAX; qcode++) {
    114         if (test_bit(qcode, kbd->keys)) {
    115             qkbd_state_key_event(kbd, qcode, false);
    116         }
    117     }
    118 }
    119 
    120 void qkbd_state_set_delay(QKbdState *kbd, int delay_ms)
    121 {
    122     kbd->key_delay_ms = delay_ms;
    123 }
    124 
    125 void qkbd_state_free(QKbdState *kbd)
    126 {
    127     g_free(kbd);
    128 }
    129 
    130 QKbdState *qkbd_state_init(QemuConsole *con)
    131 {
    132     QKbdState *kbd = g_new0(QKbdState, 1);
    133 
    134     kbd->con = con;
    135 
    136     return kbd;
    137 }