I'm on Linux, but solution should work on Win and macOS too.
I want to capture 'double quote' on KEYDOWN event with SDL2.
I want to capture it in a locale independent way.
For example " is SHIFT+' on US keyboard but is SHIFT+2 in IT keyvboard.
After SDL_Init() function SDL_GetScancodeFromKey(SDLK_QUOTEDBL) always return 0, this seems confirmed from table: http://wiki.libsdl.org/SDL_Keycode
Worse seems that event.key.keysym.sym is never equal to SDLK_QUOTEDBL, while pressing 'double quote', event.key.keysym.sym is equal to "'" on US locale and "2" on IT locale.
I saw that event.key.keysym.mod is 4096 without SHIFT and 4098 with SHIFT pressed, so knowing the locale and keyboard layout is possible to catch the double quote, capturing '2' or ''' (or other key on keybords), but I had to discover the active locale and map myself all keyboard layouts.
Is there a better/easy way to read 'double quote' SDL2 event in a locale independent manner?
Here below a code example I used to test it:
#include <SDL2/SDL.h>
#define MAINWINWIDTH 1280
#define MAINWINHEIGHT 1024
#define COLORDEPTH 32
#define BYTESPERPIXEL (COLORDEPTH/8) // 4
#define SC_BLACK 0x00000000ul
#define SC_CYAN 0x0000C0C0ul
#define SP_WIDTH 256
#define SP_HEIGHT 192
#define SP_ZOOM 2
#define SS_WIDTH_SPIXELS (SP_WIDTH*SP_ZOOM)
#define SS_HEIGHT_SPIXELS (SP_HEIGHT*SP_ZOOM)
#define BORDERWIDTH 4
#define OBJWINWIDTH (56*8) // 448: 56 column, 8 pixel/char
#define LOGWINWIDTH (MAINWINWIDTH - OBJWINWIDTH - GAMEWINWIDTH - 10*BORDERWIDTH) // 280
#define GAMEWINPOSX (LOGWINWIDTH + 5*BORDERWIDTH) // 300
#define GAMEWINPOSY (2*BORDERWIDTH) // 8
#define GAMEWINWIDTH SS_WIDTH_SPIXELS // 512
#define GAMEWINHEIGHT SS_HEIGHT_SPIXELS // 384
#define compA(color) ((color>>24)&0xFF)
#define compR(color) ((color>>16)&0xFF)
#define compG(color) ((color>>8)&0xFF)
#define compB(color) ((color>>0)&0xFF)
#define components(color) compR(color),compG(color),compB(color),compA(color)
struct TextWindowStruct {
SDL_Texture* texPtr;
Uint32* framePtr;
int frameSize;
SDL_Rect rect;
int pitch;
int CurrentPrintPosX;
int CurrentPrintPosY;
};
int main (int argNum, char* argVect[]) {
/* ...*/
SDL_Window* winPtr;
SDL_Renderer* renPtr;
struct TextWindowStruct GameWin;
int WinMode;
SDL_Event event;
SDL_Scancode CurrentPressedCod;
SDL_Keycode CurrentPressedKey=0;
Uint16 CurrentPressedMod;
int RunMainLoop;
WinMode = 0; // SDL_WINDOW_FULLSCREEN_DESKTOP;
SDL_Init(SDL_INIT_VIDEO);
winPtr = SDL_CreateWindow("Game", 110, 25, MAINWINWIDTH, MAINWINHEIGHT, WinMode | SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL|SDL_WINDOW_ALLOW_HIGHDPI);
renPtr = SDL_CreateRenderer (winPtr, -1, SDL_RENDERER_ACCELERATED);
SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "linear");
SDL_RenderSetLogicalSize (renPtr, MAINWINWIDTH, MAINWINHEIGHT);
SDL_SetWindowSize (winPtr, MAINWINWIDTH, MAINWINHEIGHT);
SDL_SetRenderDrawColor(renPtr, components(SDL_ALPHA_OPAQUE<<24|SC_CYAN)); // White. Black:R,G,B=0, Alpha=full. SDL_ALPHA_OPAQUE
SDL_RenderClear(renPtr);
GameWin.texPtr = SDL_CreateTexture (renPtr, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, GAMEWINWIDTH, GAMEWINHEIGHT);
if (GameWin.texPtr == NULL) {
fprintf (stderr, "SDL_CreateTexture Error: %s\n", SDL_GetError());
SDL_DestroyRenderer (renPtr);
SDL_DestroyWindow (winPtr);
SDL_Quit ();
return 1;
}
GameWin.pitch = GAMEWINWIDTH * BYTESPERPIXEL;
GameWin.frameSize = GameWin.pitch * GAMEWINHEIGHT;
GameWin.framePtr = malloc (GameWin.frameSize);
if (GameWin.framePtr == NULL) {
fprintf (stderr, "malloc Error\n");
SDL_DestroyRenderer (renPtr);
SDL_DestroyWindow (winPtr);
SDL_Quit ();
return 1;
}
memset (GameWin.framePtr, SC_BLACK, GameWin.frameSize); // Black
GameWin.rect.x = GAMEWINPOSX;
GameWin.rect.y = GAMEWINPOSY;
GameWin.rect.w = GAMEWINWIDTH;
GameWin.rect.h = GAMEWINHEIGHT;
GameWin.CurrentPrintPosX = 0;
GameWin.CurrentPrintPosY = 0;
SDL_UpdateTexture (GameWin.texPtr, NULL, GameWin.framePtr, GameWin.pitch); // copy Frame to Texture
SDL_RenderCopy (renPtr, GameWin.texPtr, NULL, &GameWin.rect); // copy Texture to Renderer
SDL_RenderPresent (renPtr); // update screen
/* ...*/
CurrentPressedCod = SDL_GetScancodeFromKey(SDLK_QUOTEDBL);
SDL_Log("Double quote key:0x%02X has scancode:0x%02X\n", SDLK_QUOTEDBL, CurrentPressedCod);
/* ...*/
RunMainLoop = 1;
while (RunMainLoop) {
/* ...*/
SDL_UpdateTexture (GameWin.texPtr, NULL, GameWin.framePtr, GameWin.pitch); // copy Frame to Texture
SDL_RenderCopy (renPtr, GameWin.texPtr, NULL, &GameWin.rect); // GAMEWIN texture to all Renderer
SDL_RenderPresent (renPtr); // update screen
if (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
RunMainLoop = 0;
break;
case SDL_KEYDOWN:
CurrentPressedCod = event.key.keysym.scancode;
CurrentPressedKey = event.key.keysym.sym;
CurrentPressedMod = event.key.keysym.mod;
SDL_Log("SDL_KEYDOWN cod:0x%02X\n", CurrentPressedCod);
SDL_Log("SDL_KEYDOWN key:0x%02X='%s'\n", CurrentPressedKey , SDL_GetKeyName(CurrentPressedKey));
SDL_Log("SDL_KEYDOWN key:%u='%c'", CurrentPressedKey, CurrentPressedKey);
SDL_Log("SDL_KEYDOWN mod:%u", CurrentPressedMod);
if (CurrentPressedKey) {
switch (CurrentPressedKey) {
case SDLK_QUOTEDBL: // '"'
SDL_Log("Double Quote Key:%u\n", CurrentPressedKey);
break;
case 'a':
case 'q':
/* ...*/
break;
//default:
//SDL_Log("ERR: unsupported key:%u\n", CurrentPressedKey);
//goto Error;
}
}
break;
case SDL_KEYUP:
printf("key up ---\n");
CurrentPressedKey = 0;
break;
//default:
//SDL_Log("INFO: unsupported event:%u\n", event.type);
}
}
SDL_Delay (40); // ms
}
/* ...*/
if (GameWin.framePtr) free(GameWin.framePtr);
if (GameWin.texPtr) SDL_DestroyTexture(GameWin.texPtr);
if (renPtr) SDL_DestroyRenderer(renPtr);
if (winPtr) SDL_DestroyWindow(winPtr);
SDL_Quit();
return 0;
//Error:
return (0xFF);
}
What you describe looks a lot more like text input than keyboard keys. You could use SDL_TextInputEvent for that. E.g.:
int main(int argc, char **argv) {
// ... init
SDL_StartTextInput(); // enable SDL_TEXTINPUT handling
while(in_main_loop) {
SDL_Event event;
while(SDL_PollEvent(&event)) { // 'while', not 'if'!
if(event.type == SDL_TEXTINPUT) {
// check each character for doublequotes. 'text.text' is utf8
for(int i = 0; event.text.text && event.text.text[i]; ++i) {
if(event.text.text[i] == '\"') {
printf("got doublequote\n");
}
}
} else if(event.type == SDL_QUIT) {
in_main_loop = false;
}
}
// ... render
}
}