SDL_GetKeyState not detecting japanese keypresses - sdl

SDL_GetKeyState isn't detecting the keypress state of various keys on several Japanese keyboards that I've tested. Specifically Y| (next to backspace) and \_ (next to right shift) and the Kana composition keys on each side of the SPACE bar. Y| and \_ generate and return characters, but their keypress state is not noticed.
Trimmed down code. Pressing the keys return characters:
if (SDL_PollEvent(&ev))
switch(ev.type) {
case SDL_KEYDOWN:
ch = ev.key.keysym.unicode;
// Y| and \_ return characters
But detecting their state does not work. Using code similar to this shows no response to pressing the keys:
SDL_PumpEvents();
keystate = SDL_GetKeyState(NULL);
while(SDL_PollEvent(&ev))
{ if (ev.type == SDL_QUIT) exit(0); }
for (arg=0; arg<512; arg++)
{ printf("%2x ",keystate[arg]); }
Is there a "deeper" level I can call to detect keypress states? Or is SDL immovably bound to only those keyboards that the authors have ever encountered?

Related

SDL_KEYUP triggered when key is still down

I am using SDL2 in C++ to create a sprite. However, the SDL_KEYUP is constantly triggered when I am pressing the key.
void update() override {
if(Game::event.type == SDL_KEYDOWN) {
switch(Game::event.key.keysym.sym) {
case SDLK_z:
cout << "key down" << endl;
break;
default:
break;
}
}
if(Game::event.type == SDL_KEYUP) {
switch(Game::event.key.keysym.sym) {
case SDLK_z:
cout << "Key up" << endl;
break;
default:
break;
}
}
}
It's a feature, not a bug. If you hold a key for half a second or so, SDL will start to generate "fake" key-down & key-up events.
This is used primarily for text editing, but is mostly useless otherwise.
Ignore all keyboard events that have event.key.repeat != 0.
Also, if you're writing a game, you might want to use scancodes instead of keycodes (e.g. event.key.keysym.scancode == SDL_SCANCODE_A instead of event.key.keysym.sym == SDLK_a).
Keycodes depend on the current layout, and scancodes don't. Scancodes represent physical key locations. The diffence is noticeable if you use a non-QWERTY layout. (E.g. SDLK_z is always bound to the key that has Z printed on it, while SDL_SCANCODE_W is bound to W on QWERTY and Z on AZERTY.)

Qt catch shift + 3 on one key press

I'm using Qt 5.11.
I need to catch shift + 3 on one key press. But this combination generates special character ^ because I'm using Turkish Q Keyboard. So I can't catch it without press shift + 3 again.
I tried shift modifiers and multiple key press solutions but not working.
I want to override ^. Is there any possible ways to do it?
Try the following it could work. Although according to the documentation, nativeVirtualKey could return 0 even if there is valid information. So not sure if it will work all the time. I tested it with a german, english and arabic keyboard.
Update (tested it with turkish keyboard layout)
void keyPressEvent(QKeyEvent *ev)
{
if ((ev->nativeVirtualKey() == Qt::Key_3 || ev->key() == Qt::Key_3) && ev->modifiers() == Qt::ShiftModifier)
{
//Do something
}
}
For turkish layout, ^ caret (a dead key), in addition to the above, you can catch the dead key press by overriding the nativeEvent function and calling the keyEvent function manually
bool nativeEvent(const QByteArray & eventType, void * message, long * result)
{
MSG *msg = reinterpret_cast<MSG*>(message);
if (msg->message == WM_DEADCHAR)
{
QKeyEvent *key = new QKeyEvent(QEvent::KeyPress, Qt::Key_3, Qt::ShiftModifier);
}
}
One minor issue, the keyEvent will be called even if ^ is pressed in another language, not necessarily only with Shift+3, so this is an unexpected behaviour, but maybe for your case you can tell the user that both shift+3 or ^ are the shortcut for your specific function

SDL unicode keyboard input: filter none character inputs

I'm using this code to to determine keyboard inputs as unicode character:
while(SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
{
SDL_KeyboardEvent* keyboard = (reinterpret_cast<SDL_KeyboardEvent*> (&event));
//unicode input
std::cout << (int)keyboard->keysym.unicode << std::endl;
//conversion
...
break;
}
}
}
My problem is that keysym.unicode has also a value if I would only press the Shift-key (printed value is 1249).
But I only need valid unicode-charactars (e.g.: pressing Shift+A)
Any hints?
I fixed it using: SDL_StartTextInput(); to enable textinput-events with:
SDL_TEXTINPUT-event instead of SDL_KEYDOWN is working fine.

Handling input with GLFW

Here is the definition of my keyboard callback method I'm using to check for user input for a 2D basic game. However I'm having a problem handling certain simultaneous key presses.
For example, If I hold the Right and Up arrows keys, the player moves 45 degrees toward the top right of the screen as it should. Then, while still holding the up and right keys, if I press Space (which fires a projectile), that works as well.
However, if I hold the Left and Down arrow keys, the player moves as it should, but when I press Space, I get no input response, so I can't fire a projectile when moving down and left. All other movement + fire projectile combinations work, just the down and left doesn't... I can't figure out why. Any ideas?
if (key == GLFW_KEY_LEFT)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_LEFT, action);
}
else if (key == GLFW_KEY_RIGHT)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_RIGHT, action);
}
else if (key == GLFW_KEY_UP)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_UP, action);
}
else if (key == GLFW_KEY_DOWN)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_DOWN, action);
}
else if (key == GLFW_KEY_SPACE)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_SPACE, action);
}
else { }
Rollover is the property that allows a keyboard to properly register many key presses at once. Keyboards are wired in rows and columns. Even if the keyboard is not square, the individual keys are in a roughly square matrix of wires connecting their switches. The controller connects one row and then tests to see which of the columns are hit. Some key combinations "shadow" others. The controller can tell when the input is ambiguous and send no keys.
Better keyboard use diodes arranged to avoid the ambiguity and thus support "full rollover", although in practice USB limits you to all the modifiers plus 6 distinct keycodes at once.
Sounds like a crappy keyboard.
You may have to procure a better one.
Or use different key combinations.
The code should be
if (key == GLFW_KEY_LEFT)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_LEFT, action);
}
if (key == GLFW_KEY_RIGHT)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_RIGHT, action);
}
if (key == GLFW_KEY_UP)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_UP, action);
}
if (key == GLFW_KEY_DOWN)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_DOWN, action);
}
if (key == GLFW_KEY_SPACE)
{
GameController::getInstance()->getPlayer()->changeKeyPress(GLFW_KEY_SPACE, action);
}
The problem is your code just detect 1 key press at a time so when you press left and right at the same time only the if (key == GLFW_KEY_LEFT) is fired

Handling key events in SDL and C++

I'm in the process of migrating a program from GLUT to SDL. In my current program pressing the a key results in a different response then pressing the A key. This was pretty straightforward to do in GLUT as it the keyboard function callback passed in the ASCII value of the key that was pressed.
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
// do work for a
break;
case 'A':
// do work for A
break;
}
}
I'm struggling to replicate similar functionality in SDL as pressing the a key produces the same response regardless of if SHIFT or CAPS LOCK are pressed as well.
Is there a simple way of replicating the above function in SDL?
Edit: In the example above I only show how to handle one key, in practice however, I am going to have a list of about 15 keys that I want to respond to differently if the shift key is pressed as well.
Check the keyboard modifiers that are present when you get a keydown event. For example:
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_KEYDOWN:
if(event.key.keysym.sym == SDLK_a)
{
if(event.key.keysym.mod & KMOD_SHIFT)
{
// Handle 'A'
}
else
{
// Handle 'a'
}
}
break;
...
}
}
SDL_keysym has mod field, which contains state of modifier keys at the time the event has been emitted. Bit-AND it with KMOD_SHIFT to check whether Shift has been active. See SDL wiki.
Why not just do this?
void keyPressedFn(unsigned char key, int x, int y){
switch(key){
case 'a':
case 'A':
// do work for A or a
break;
}
}
Do you have some other concerns that you cannot do as what I have suggested? If not I think this is as simple as it can get.