Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uppercase keys no longer working #264

Open
lkesteloot opened this issue Jan 25, 2025 · 8 comments
Open

Uppercase keys no longer working #264

lkesteloot opened this issue Jan 25, 2025 · 8 comments

Comments

@lkesteloot
Copy link

I was using v2.22 of pi3d (on RPi 2), and the keyboard's read() function was properly returning uppercase letters (shift-A was returning 65). I've upgraded to the latest version (v2.52) and all letters now return the lowercase value (97 for shift-A). The shift key itself returns 0 (as does other modifier keys). I tried read_code() and it's the same.

I checked the sample programs and they all only ever use lowercase commands.

This is on Linux on Raspberry Pi 5, console mode (via xinit). I tried with and without curses.

@paddywwoof
Copy link
Collaborator

Hi @lkesteloot the keyboard and mouse functionality on the later Raspberry Pus definitely needs sorting out. What OS are you using, and are you using the SDL2 system. Sounds like you're using X rather than Wayland.

Definitely sounds like a bug if the modifier always return 0

Paddy

@lkesteloot
Copy link
Author

Hi!

My current setup:

  • Raspberry Pi 5 Model B Rev 1.0
  • Debian GNU/Linux 12 (bookworm), kernel 6.6.62
  • I assume I'm not using SDL2 since it's forced to False in Display.py (line 115) on the Raspberry Pi.
  • My desktop is set up to use Labwc with Wayland, but here I'm running it from the console with xinit.

With use_curses set to either True or False, all modifier keys return 0, and the Q key always returns 113, whether shifted or not. I don't see a way to detect uppercase letters.

(BTW the project is PiSlide, which uses uppercase letters for dangerous operations like quitting and enabling debugging mode.)

Thank you for responding! I'm happy to do whatever tests you'd like.

@paddywwoof
Copy link
Collaborator

Hi @lkesteloot I've just had a quick look at this (pi3d.Keyboard) The curses keyboard will only available if pi3d thinks it's running on an older raspberry pi using the libbcm.so graphics driver rather than the newer mesa ones.

elif pi3d.PLATFORM != pi3d.PLATFORM_PI:
I'm not sure why the keyboard functionality would be related but I think it just ties in with older versions of the OS and what utilities have been deprecated. Certainly if I comment out the condition and force curses to be used on this RPi5 it doesn't work!!

I think this same issue came up in the past when running pi3d on different platforms and the way round it was to use the X11Keyboard (which will be the default on later Pis in the absence of SDL2) and keep track of which modifier characters had been pressed. This was the system we used in pi3d_demos.Gui.py. Could you try this test program to see it it works on your new Pi?

import pi3d
         
DISPLAY = pi3d.Display.create(w=100, h=100, frames_per_second=30)
keyboard = pi3d.Keyboard(use_curses=True)
print(f"actual type of keyboard running here={type(keyboard)}")
shifted = False
caps = False

while DISPLAY.loop_running():
  kc = keyboard.read_code()
  if len(kc) > 0:
    is_char = (type(kc) == str and len(kc) == 1)
    if kc == chr(27) or kc == "Escape":
      break
    if "Shift" in kc:
      shifted = True
    elif "Caps" in kc:
      caps = not caps
    elif is_char:
      if shifted or caps:
        resultant_char = kc.upper()
      else:
        resultant_char = kc
      print(f"{kc} {ord(kc) if is_char else ''} resulting in {resultant_char}")
      shifted = False
    else:
      print(kc) # an non char key other than Shift.. or Caps..

DISPLAY.destroy()

@paddywwoof
Copy link
Collaborator

For the sdl2Keyboard I need to do something like this in __init__

    self.KEYBOARD = {}
    for k in dir(sdl2): # sift through for key codes
      if "SDLK_" in k:
        key_num = getattr(sdl2, k)
        if type(key_num) == int:
          key_code = k.split("_")[-1]
          self.KEYBOARD[key_num] = key_code
...
def _update_event(self):
...
    self.key_code = self.KEYBOARD[k]

SDL has the extra info in the Display.keys_pressed[k][1] showing the key_mod status, which is held in the Keyboard instance and might get round some issues. However there are multiple keyboard events for each key press and the SDLK constants are different from the X11 ones!

@lkesteloot
Copy link
Author

I tried your test code from this comment. The type of the class is x11Keyboard.

It didn't show any keys at all! read_code() always returns an empty string, and read() always return -1. Took me a while to debug, but eventually figured out that the size of the display is too small, and instead of w=100, h=100 you have to pass in w=800, h=500. Maybe it changed the timing so that both an X11 press and a release got enqueued, and _update_event() processed both, losing the press. (The program otherwise worked fine with 100x100, including drawing a sprite when I modified it to do that.)

Secondly, if the user holds Shift, then presses the A key twice, the first one is uppercase but the second is lowercase. The keyboard class doesn't pass on releases, so we can't know when the shift key is released.

Want me to give it a go to modify the x11Keyboard class to internally track modifier keys and return the correct ASCII key from read()? I'll also enqueue keys so that they never get lost between polls. (I don't know what read_code() is even supposed to return, so I won't mess with that one.)

@lkesteloot
Copy link
Author

Also note that pi3d.PLATFORM is 3, which is PLATFORM_LINUX, not PLATFORM_PI as I'd expected! I had written above that SDL2 is forced to False on Pi, which is true according to the code, but false in my case since pi3d thinks my platform is Linux.

@paddywwoof
Copy link
Collaborator

Hi, that's a bit weird: the display dimensions disrupt the key reading!

As you can probably tell, the code has evolved in a rather nonlinear way as the hardware changed. PLATFORM_PI means early models, with various closed source Broadcom software required and a reasonable probability that no X11 server would be running. The aim of the RPi foundation has been to align themselves with standard Linux so software can be ported with the minimum of low level hacking. Hence later Pi models are identified as PLATFORM_LINUX

Also, yes, it would be great if you had the time and inclination to look at the Keyboard code.

@rec
Copy link
Collaborator

rec commented Jan 27, 2025

the display dimensions disrupt the key reading!

Just unlurking to say that this is a big surprise!

...and also, "I'm still around". I'd help except I don't even have an RPi here, we recently moved to Rouen and our stuff is in storage in Amsterdam.

Thanks for all your work on this, Paddy, and come and visit some time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants