medley icon indicating copy to clipboard operation
medley copied to clipboard

Character case mismatch when launching Medley on Linux with Caps Lock on

Open pamoroso opened this issue 2 years ago • 4 comments

Describe the bug If I launch Medley from Linux with Caps Lock turned on, the case of the characters typed in any editor (e.g. the Excec) doesn't match the state of the Caps Lock and Shift keys.

Typing a letter while Caps Lock is on yields the lowercase letter and typing a letter with Caps Lock off yields the uppercase version. If Caps Lock is turned off immediately after Medley starts, typing a letter still yields the uppercase version as well as typing Shift + letter with Caps Lock off.

To Reproduce Steps to reproduce the behavior:

  1. from the Linux shell, execute medley &
  2. at the Exec, type a letter

Expected behavior Typing letters with Caps Lock on yields uppercase letters. Typing letters with Caps Lock off yields lowercase letters.

Screenshots

N/A

Context (please complete the following information):

  • OS: Crostini Linux
  • OS Version: Debian 11 Bullseye Linux container of chromeOS 119.0.6045.192
  • Host arch: x86_64 (ASUS Chromebox 3)
  • Maiko version: 3.51
  • IL:MAKESYSDATE: 1 Dec 2023 21:04:05

Additional context I use the SDL backend of Medley built from source on Linux. A similar issue happens with Medley SDL under Raspberry Pi OS Bookworm on my Raspberry Pi 400.

This is likely a known issue but, since I haven't found any specific reports here, I thought I'd record it in its own issue.

pamoroso avatar Dec 11 '23 13:12 pamoroso

The root cause is that Medley/Maiko is unaware of key transitions that happen outside the Lisp window and therefore don't generate key state transition events to the emulator.

nbriggs avatar Dec 11 '23 18:12 nbriggs

I was looking in maiko/src/initkbd.c to figure out the keyboard mapping, and that led me to discover the XkbGetNamedIndicator function. It looks like (for X Windows) this could be invoked to get the current state of the Caps_Lock key and use the state_rtrn value to initialize Medley with the current state of that mode. It could also be used for Num_Lock; that mode is already in Medley. (Lisp keyboard code 73.)

MattHeffron avatar Dec 18 '23 21:12 MattHeffron

I don't know that we can initialize the Medley state - the caps-lock isn't (usually) based on whether the caps-lock key is down or up in the key bit table, at least not under most X servers. You usually get keydown, keyup, then it's in lock mode, then keydown, keyup, and it's not in lock mode. In the Lisp code, the keyaction for the caps-lock key is set to (LOCKTOGGLE . IGNORE) and there's the whole Lisp mechanism that is a black box to the Maiko code for turning LOCKTOGGLE into the current caps-lock state. I suspect the same (wrt X11) goes for the num-lock key.

nbriggs avatar Dec 18 '23 22:12 nbriggs

I've been doing some digging into the keyboard code, and experiments.

  1. The XKeyEvent structure (i.e., report.xkey) that is handled by process_Xevents (in maiko/src/xwinman.c) contains both the keycode of the KeyPress or KeyRelease event and a state field. The state field purports to encode the current state of the keyboard Shift, CapsLock, and Control modes (plus a few others).
  2. I added DEBUG code on KeyPress and KeyRelease to print keycode, state, and the mapped to Lisp key number values.
  3. By experiment I verified, that the state field is correct even if the keyboard focus is not in the medley Xwindow on the CapsLock key press. This was on Windows 11, WSL with Ubuntu, AND on Ubuntu installed natively on an old laptop, both. (In fact, on Windows, a Windows application had the focus for that test.)
  4. Shift and Control report for either the left or right corresponding keys are down.
  5. NumLock is also encoded.
  6. Alt is encoded/reported for either the left or right key down.
  7. The Windows and Menu keys are not encoded in state.
  8. Although the state field is an unsigned int, it appears that only the low-order 8 bits are used (at present).

So, this means that at each key transition, we can (should) know the correct state of the CapsLock (and NumLock). If this information is passed to Lisp, then it can handle each key correctly, even if it doesn't see the key press that set/cleared these modes. It also could know if the Shift and/or Control keys are already pressed when medley is started. This change probably would be considered as a breaking change, since older sysouts wouldn't know about the modes status.

Here is my maiko/src/xwinman.c file (.txt because can't attach .c file) xwinman.c.txt

MattHeffron avatar Jan 03 '24 01:01 MattHeffron