Rakashazi / emu-ex-plus-alpha

Multi-platform computer & game console emulation system including supporting code (EmuFramework) and core engine (Imagine)
GNU General Public License v3.0
600 stars 145 forks source link

[Issue]: Arch Linux Num-Lock causes primary keyboard keys to shift/unshift based on state #693

Closed noabody closed 1 year ago

noabody commented 1 year ago

Describe the feature

In both C64.emu and Swan.emu (Options, birth year), I noticed that all keyboard keys produce their "shifted" keysym so that, on US keyboard:

1234567890
asdfghjkl

Produces:

!@#$%^&*()
ASDFGHJKL

Checked layout with command:

localectl status
   System Locale: LANG=en_US.UTF-8
       VC Keymap: us
      X11 Layout: us
       X11 Model: pc105

Relevant code appears to be in file: src/emu-ex-plus-alpha/imagine/src/base/x11/input.cc

Feature enhancement request would be to give full range of keyboard.

Add screenshots

keys17

Rakashazi commented 1 year ago

Is it only when using that virtual keyboard or also the physical keyboard? I'm not familiar with that one but I installed CoreKeyboard from flathub and it enters in the characters correctly.

noabody commented 1 year ago

The physical keyboard has the problem for me on Manjaro Linux xfce. The virtual keyboard was used to illustrate. It's uinput but everything is these days. Will try the developer build later.

Here is some of the output of keyboard while pressing '1' and 'left-shift - 1':

sudo evtest /dev/input/by-id/usb-Logitech_USB_Receiver-event-kbd
Input driver version is 1.0.1
Input device ID: bus 0x3 vendor 0x46d product 0xc53d version 0x111
Input device name: "Logitech USB Receiver"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 1 (KEY_ESC)
    Event code 2 (KEY_1)
    Event code 3 (KEY_2)
    Event code 4 (KEY_3)
    Event code 5 (KEY_4)
    Event code 6 (KEY_5)
    Event code 7 (KEY_6)
    Event code 8 (KEY_7)
    Event code 9 (KEY_8)
    Event code 10 (KEY_9)
    Event code 11 (KEY_0)
    Event code 12 (KEY_MINUS)
    Event code 13 (KEY_EQUAL)
    Event code 14 (KEY_BACKSPACE)
    Event code 15 (KEY_TAB)
    Event code 16 (KEY_Q)
    Event code 17 (KEY_W)
    Event code 18 (KEY_E)
    Event code 19 (KEY_R)
    Event code 20 (KEY_T)
    Event code 21 (KEY_Y)
    Event code 22 (KEY_U)
    Event code 23 (KEY_I)
    Event code 24 (KEY_O)
    Event code 25 (KEY_P)
    Event code 26 (KEY_LEFTBRACE)
    Event code 27 (KEY_RIGHTBRACE)
    Event code 28 (KEY_ENTER)
    Event code 29 (KEY_LEFTCTRL)
    Event code 30 (KEY_A)
    Event code 31 (KEY_S)
    Event code 32 (KEY_D)
    Event code 33 (KEY_F)
    Event code 34 (KEY_G)
    Event code 35 (KEY_H)
    Event code 36 (KEY_J)
    Event code 37 (KEY_K)
    Event code 38 (KEY_L)
    Event code 39 (KEY_SEMICOLON)
    Event code 40 (KEY_APOSTROPHE)
    Event code 41 (KEY_GRAVE)
    Event code 42 (KEY_LEFTSHIFT)
    Event code 43 (KEY_BACKSLASH)
    Event code 44 (KEY_Z)
    Event code 45 (KEY_X)
    Event code 46 (KEY_C)
    Event code 47 (KEY_V)
    Event code 48 (KEY_B)
    Event code 49 (KEY_N)
    Event code 50 (KEY_M)
    Event code 51 (KEY_COMMA)
    Event code 52 (KEY_DOT)
    Event code 53 (KEY_SLASH)
    Event code 54 (KEY_RIGHTSHIFT)
    Event code 55 (KEY_KPASTERISK)
    Event code 56 (KEY_LEFTALT)
    Event code 57 (KEY_SPACE)
    Event code 58 (KEY_CAPSLOCK)
    Event code 59 (KEY_F1)
    Event code 60 (KEY_F2)
    Event code 61 (KEY_F3)
    Event code 62 (KEY_F4)
    Event code 63 (KEY_F5)
    Event code 64 (KEY_F6)
    Event code 65 (KEY_F7)
    Event code 66 (KEY_F8)
    Event code 67 (KEY_F9)
    Event code 68 (KEY_F10)
    Event code 69 (KEY_NUMLOCK)
    Event code 70 (KEY_SCROLLLOCK)
    Event code 71 (KEY_KP7)
    Event code 72 (KEY_KP8)
    Event code 73 (KEY_KP9)
    Event code 74 (KEY_KPMINUS)
    Event code 75 (KEY_KP4)
    Event code 76 (KEY_KP5)
    Event code 77 (KEY_KP6)
    Event code 78 (KEY_KPPLUS)
    Event code 79 (KEY_KP1)
    Event code 80 (KEY_KP2)
    Event code 81 (KEY_KP3)
    Event code 82 (KEY_KP0)
    Event code 83 (KEY_KPDOT)
    Event code 85 (KEY_ZENKAKUHANKAKU)
    Event code 86 (KEY_102ND)
    Event code 87 (KEY_F11)
    Event code 88 (KEY_F12)
    Event code 89 (KEY_RO)
    Event code 90 (KEY_KATAKANA)
    Event code 91 (KEY_HIRAGANA)
    Event code 92 (KEY_HENKAN)
    Event code 93 (KEY_KATAKANAHIRAGANA)
    Event code 94 (KEY_MUHENKAN)
    Event code 95 (KEY_KPJPCOMMA)
    Event code 96 (KEY_KPENTER)
    Event code 97 (KEY_RIGHTCTRL)
    Event code 98 (KEY_KPSLASH)
    Event code 99 (KEY_SYSRQ)
    Event code 100 (KEY_RIGHTALT)
    Event code 102 (KEY_HOME)
    Event code 103 (KEY_UP)
    Event code 104 (KEY_PAGEUP)
    Event code 105 (KEY_LEFT)
    Event code 106 (KEY_RIGHT)
    Event code 107 (KEY_END)
    Event code 108 (KEY_DOWN)
    Event code 109 (KEY_PAGEDOWN)
    Event code 110 (KEY_INSERT)
    Event code 111 (KEY_DELETE)
    Event code 113 (KEY_MUTE)
    Event code 114 (KEY_VOLUMEDOWN)
    Event code 115 (KEY_VOLUMEUP)
    Event code 116 (KEY_POWER)
    Event code 117 (KEY_KPEQUAL)
    Event code 119 (KEY_PAUSE)
    Event code 121 (KEY_KPCOMMA)
    Event code 122 (KEY_HANGUEL)
    Event code 123 (KEY_HANJA)
    Event code 124 (KEY_YEN)
    Event code 125 (KEY_LEFTMETA)
    Event code 126 (KEY_RIGHTMETA)
    Event code 127 (KEY_COMPOSE)
    Event code 128 (KEY_STOP)
    Event code 129 (KEY_AGAIN)
    Event code 130 (KEY_PROPS)
    Event code 131 (KEY_UNDO)
    Event code 132 (KEY_FRONT)
    Event code 133 (KEY_COPY)
    Event code 134 (KEY_OPEN)
    Event code 135 (KEY_PASTE)
    Event code 136 (KEY_FIND)
    Event code 137 (KEY_CUT)
    Event code 138 (KEY_HELP)
    Event code 183 (KEY_F13)
    Event code 184 (KEY_F14)
    Event code 185 (KEY_F15)
    Event code 186 (KEY_F16)
    Event code 187 (KEY_F17)
    Event code 188 (KEY_F18)
    Event code 189 (KEY_F19)
    Event code 190 (KEY_F20)
    Event code 191 (KEY_F21)
    Event code 192 (KEY_F22)
    Event code 193 (KEY_F23)
    Event code 194 (KEY_F24)
    Event code 240 (KEY_UNKNOWN)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
  Event type 17 (EV_LED)
    Event code 0 (LED_NUML) state 0
    Event code 1 (LED_CAPSL) state 0
    Event code 2 (LED_SCROLLL) state 0
    Event code 3 (LED_COMPOSE) state 0
    Event code 4 (LED_KANA) state 0
Key repeat handling:
  Repeat type 20 (EV_REP)
    Repeat code 0 (REP_DELAY)
      Value    250
    Repeat code 1 (REP_PERIOD)
      Value     33
Properties:

Event: time 1662814571.336905, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7001e
Event: time 1662814571.336905, type 1 (EV_KEY), code 2 (KEY_1), value 1
Event: time 1662814571.336905, -------------- SYN_REPORT ------------
Event: time 1662814571.445930, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7001e
Event: time 1662814571.445930, type 1 (EV_KEY), code 2 (KEY_1), value 0
Event: time 1662814571.445930, -------------- SYN_REPORT ------------
Event: time 1662814581.211734, type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e1
Event: time 1662814581.211734, type 1 (EV_KEY), code 42 (KEY_LEFTSHIFT), value 1
Event: time 1662814581.211734, -------------- SYN_REPORT ------------
Event: time 1662814581.290746, type 4 (EV_MSC), code 4 (MSC_SCAN), value 7001e
Event: time 1662814581.290746, type 1 (EV_KEY), code 2 (KEY_1), value 1
Rakashazi commented 1 year ago

Thanks for the clarification. It's probably related to the keycode -> string conversion code in XApplication::inputKeyString. I'll do some research and see if there's a better/updated way to do it in a future update.

noabody commented 1 year ago

Thanks! I was looking at that code just now. It's all gobbledygook to someone who majored in Turbo Pascal in High School. BASH shell scripting is about all I can do.

Rakashazi commented 1 year ago

No problem, I actually started with Turbo Pascal too until our school switched over to C++ when it was standardized in '98 and have stuck with it ever since.

About the keyboard bug, I've updated the string conversion code in the last commit so give it another try and check if the characters are still shifted.

noabody commented 1 year ago

Swan.emu is the oddity. The reason why I didn't think the input issue was a bug is simple - the keyboard is treated as a game input device in all cases except this one dialog. Each keyboard key should be treated as a single event, or button. This includes modifiers such as shift/control/alt. For all intents and purposes, the keyboard is treated the same as a gamepad.

"In-Game actions" generates the lowercase or non-numlock version of each physical keyboard key, essentially the scan-code minus a modifier. In the Birth Year dialog, the same is true except that it uses the shifted version of the scan-code.

The fix, I believe, would be to stop treating the keyboard as a game device in those Swan.emu dialogs Options > System > (Name, Birth Year, Birth Month, Birth Day)

Setting "p" for "Load State" swan_key_button

Typing "6" for "Birth Year" swan_dialog

noabody commented 1 year ago

Totally forgot that, in C64.emu, it's the dialog box for "Start System With Blank (Disk, Tape)":

Disk Name of temp1234 c64_diskname

Rakashazi commented 1 year ago

Right, in-game the app maps the keyboard scan codes directly to actions so the characters they represent don't affect that. With the gray text input boxes it asks the X server what string the combination of scan code and modifier keys represent.

Since the issue is the same with both string conversion functions I'm starting to think it may be a bug in handling the modifier keys. As a test can you run the xev command and post the output when pushing 6 and shift 6? I only need the KeyPress/KeyRelease events and none of the mouse-related output. Here what I get here:

pushing just 6:

KeyPress event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x0, time 200792961, (102,138), root:(131,367),
    state 0x0, keycode 15 (keysym 0x36, 6), same_screen YES,
    XLookupString gives 1 bytes: (36) "6"
    XmbLookupString gives 1 bytes: (36) "6"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x0, time 200793018, (102,138), root:(131,367),
    state 0x0, keycode 15 (keysym 0x36, 6), same_screen YES,
    XLookupString gives 1 bytes: (36) "6"
    XFilterEvent returns: False

pushing shift and 6:

KeyPress event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x4800002, time 200822212, (61,49), root:(1713,1228),
    state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x4800002, time 200823087, (61,49), root:(1713,1228),
    state 0x1, keycode 15 (keysym 0x5e, asciicircum), same_screen YES,
    XLookupString gives 1 bytes: (5e) "^"
    XmbLookupString gives 1 bytes: (5e) "^"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x4800002, time 200823205, (61,49), root:(1713,1228),
    state 0x1, keycode 15 (keysym 0x5e, asciicircum), same_screen YES,
    XLookupString gives 1 bytes: (5e) "^"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x4800001,
    root 0x1cd, subw 0x4800002, time 200823423, (61,49), root:(1713,1228),
    state 0x1, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False
noabody commented 1 year ago

This should be it. I had been trying xinput test-xi2 --root 3 which captures just my keyboard but the output is light on details.

"6"

KeyPress event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 841111, (156,-11), root:(1027,438),
    state 0x10, keycode 15 (keysym 0x36, 6), same_screen YES,
    XLookupString gives 1 bytes: (36) "6"
    XmbLookupString gives 1 bytes: (36) "6"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 841180, (156,-11), root:(1027,438),
    state 0x10, keycode 15 (keysym 0x36, 6), same_screen YES,
    XLookupString gives 1 bytes: (36) "6"
    XFilterEvent returns: False

shift-"6"

KeyPress event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 843882, (156,-11), root:(1027,438),
    state 0x10, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XmbLookupString gives 0 bytes: 
    XFilterEvent returns: False

KeyPress event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 843973, (156,-11), root:(1027,438),
    state 0x11, keycode 15 (keysym 0x5e, asciicircum), same_screen YES,
    XLookupString gives 1 bytes: (5e) "^"
    XmbLookupString gives 1 bytes: (5e) "^"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 844067, (156,-11), root:(1027,438),
    state 0x11, keycode 15 (keysym 0x5e, asciicircum), same_screen YES,
    XLookupString gives 1 bytes: (5e) "^"
    XFilterEvent returns: False

KeyRelease event, serial 37, synthetic NO, window 0x5e00001,
    root 0x6cd, subw 0x0, time 844135, (156,-11), root:(1027,438),
    state 0x11, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes: 
    XFilterEvent returns: False
noabody commented 1 year ago

That's funny, I rebuilt it again and it works on one of my machines. I wonder if there was a build issue yesterday. Sorry about that, I'll test it some more.

noabody commented 1 year ago

Well, it IS a real input problem and follows the operating system. I've tested the program on 4 desktops and laptops. One of each does work. I also have the same OS on a portable SSD drive. Booting the SSD on one of the computers that "work" still has input issues.

Same hardware, slightly different OS, different result.

noabody commented 1 year ago

Okay, now, don't laugh, but the problem is Num-Lock. I know, I know. Num-lock doesn't affect the primary keyboard keys. Honestly, I know I tried Num-Lock before, so that commit you mentioned, regarding UTF-8 fixes, probably fixed part of the issue.

As of right now, on Arch Linux (maybe others?), Num-Lock will not make the Numeric Keypad accessible in dialog boxes (keypad never provides numbers), but it acts as a shift-lock for all regular keyboard keys. Num-Lock on? All you get is the shifted version of each key. Num-Lock off, unshifted keys.

The behavior followed the OS because each machine remembers the Num-Lock state at boot. I'm going to rephrase this feature request as a bug now.

Edit: Even with Num-Lock off Caps-Lock doesn't work as intended. With Caps-Lock on the number keys also input their shifted symbols as if Shift-Lock was in place.

noabody commented 1 year ago

With Num-Lock on, typed temp1234 with regular keyboard keys (not numeric keypad) swan_num_on

With Num-Lock off, typed temp1234 with regular keyboard keys (not numeric keypad) swan_num_off

With Num-Lock off, Caps-Lock on, typed temp1234 with regular keyboard keys (not numeric keypad) swan_num_off_caps_on

Rakashazi commented 1 year ago

Thanks for the additional info. There was indeed a bug with passing around the keyboard modifier data and every type of modifier was being interpreted as a shift. Try the latest commit which should hopefully fix it for good :)

noabody commented 1 year ago

That absolutely fixed it! You're awesome!

Anyway, I'll save you the trouble and close this as resolved. I have one more feature request and that'll be it. Thanks again.