2011-12-29 19:36:25 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
Doom 3 Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include <SDL.h>
# include "sys/platform.h"
# include "idlib/containers/List.h"
# include "idlib/Heap.h"
# include "framework/Common.h"
# include "framework/KeyInput.h"
2020-07-20 03:06:57 +00:00
# include "framework/Session.h"
2011-12-29 19:53:54 +00:00
# include "renderer/RenderSystem.h"
2012-07-19 19:13:02 +00:00
# include "renderer/tr_local.h"
2011-12-29 19:36:25 +00:00
# include "sys/sys_public.h"
2012-07-19 20:09:53 +00:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
# define SDL_Keycode SDLKey
# define SDLK_APPLICATION SDLK_COMPOSE
# define SDLK_SCROLLLOCK SDLK_SCROLLOCK
# define SDLK_LGUI SDLK_LSUPER
# define SDLK_RGUI SDLK_RSUPER
# define SDLK_KP_0 SDLK_KP0
# define SDLK_KP_1 SDLK_KP1
# define SDLK_KP_2 SDLK_KP2
# define SDLK_KP_3 SDLK_KP3
# define SDLK_KP_4 SDLK_KP4
# define SDLK_KP_5 SDLK_KP5
# define SDLK_KP_6 SDLK_KP6
# define SDLK_KP_7 SDLK_KP7
# define SDLK_KP_8 SDLK_KP8
# define SDLK_KP_9 SDLK_KP9
# define SDLK_NUMLOCKCLEAR SDLK_NUMLOCK
# define SDLK_PRINTSCREEN SDLK_PRINT
# endif
2021-07-03 13:18:55 +00:00
static const char * kbdNames [ ] = {
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0) // auto-detection is only available for SDL2
" auto " ,
# endif
2015-06-20 05:53:53 +00:00
" english " , " french " , " german " , " italian " , " spanish " , " turkish " , " norwegian " , " brazilian " , NULL
2011-12-29 19:36:25 +00:00
} ;
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
static idCVar in_kbd ( " in_kbd " , kbdNames [ 0 ] , CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT , " keyboard layout " , kbdNames , idCmdSystem : : ArgCompletion_String < kbdNames > ) ;
// TODO: I'd really like to make in_ignoreConsoleKey default to 1, but I guess there would be too much confusion :-/
static idCVar in_ignoreConsoleKey ( " in_ignoreConsoleKey " , " 0 " , CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL ,
" Console only opens with Shift+Esc, not ` or ^ etc " ) ;
2021-07-03 13:18:55 +00:00
static idCVar in_grabKeyboard ( " in_grabKeyboard " , " 0 " , CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT | CVAR_BOOL ,
" if enabled, grabs all keyboard input if mouse is grabbed (so keyboard shortcuts from the OS like Alt-Tab or Windows Key won't work) " ) ;
2011-12-29 19:36:25 +00:00
struct kbd_poll_t {
int key ;
bool state ;
kbd_poll_t ( ) {
}
kbd_poll_t ( int k , bool s ) {
key = k ;
state = s ;
}
} ;
struct mouse_poll_t {
int action ;
int value ;
mouse_poll_t ( ) {
}
mouse_poll_t ( int a , int v ) {
action = a ;
value = v ;
}
} ;
static idList < kbd_poll_t > kbd_polls ;
static idList < mouse_poll_t > mouse_polls ;
2021-07-03 02:33:27 +00:00
struct scancodename_t {
int sdlScancode ;
const char * name ;
} ;
// scancodenames[keynum - K_FIRST_SCANCODE] belongs to keynum
static scancodename_t scancodemappings [ ] = {
// NOTE: must be kept in sync with the K_SC_* section of keyNum_t in framework/KeyInput.h !
# if SDL_VERSION_ATLEAST(2, 0, 0)
# define D3_SC_MAPPING(X) { SDL_SCANCODE_ ## X , "SC_" #X }
# else // SDL1.2 doesn't have scancodes
# define D3_SC_MAPPING(X) { 0 , "SC_" #X }
# endif
D3_SC_MAPPING ( A ) , // { SDL_SCANCODE_A, "SC_A" },
D3_SC_MAPPING ( B ) ,
D3_SC_MAPPING ( C ) ,
D3_SC_MAPPING ( D ) ,
D3_SC_MAPPING ( E ) ,
D3_SC_MAPPING ( F ) ,
D3_SC_MAPPING ( G ) ,
D3_SC_MAPPING ( H ) ,
D3_SC_MAPPING ( I ) ,
D3_SC_MAPPING ( J ) ,
D3_SC_MAPPING ( K ) ,
D3_SC_MAPPING ( L ) ,
D3_SC_MAPPING ( M ) ,
D3_SC_MAPPING ( N ) ,
D3_SC_MAPPING ( O ) ,
D3_SC_MAPPING ( P ) ,
D3_SC_MAPPING ( Q ) ,
D3_SC_MAPPING ( R ) ,
D3_SC_MAPPING ( S ) ,
D3_SC_MAPPING ( T ) ,
D3_SC_MAPPING ( U ) ,
D3_SC_MAPPING ( V ) ,
D3_SC_MAPPING ( W ) ,
D3_SC_MAPPING ( X ) ,
D3_SC_MAPPING ( Y ) ,
D3_SC_MAPPING ( Z ) ,
// leaving out SDL_SCANCODE_1 ... _0, we handle them separately already
// also return, escape, backspace, tab, space, already handled as keycodes
D3_SC_MAPPING ( MINUS ) ,
D3_SC_MAPPING ( EQUALS ) ,
D3_SC_MAPPING ( LEFTBRACKET ) ,
D3_SC_MAPPING ( RIGHTBRACKET ) ,
D3_SC_MAPPING ( BACKSLASH ) ,
D3_SC_MAPPING ( NONUSHASH ) ,
D3_SC_MAPPING ( SEMICOLON ) ,
D3_SC_MAPPING ( APOSTROPHE ) ,
D3_SC_MAPPING ( GRAVE ) ,
D3_SC_MAPPING ( COMMA ) ,
D3_SC_MAPPING ( PERIOD ) ,
D3_SC_MAPPING ( SLASH ) ,
// leaving out lots of key incl. from keypad, we already handle them as normal keys
D3_SC_MAPPING ( NONUSBACKSLASH ) ,
D3_SC_MAPPING ( INTERNATIONAL1 ) , /**< used on Asian keyboards, see footnotes in USB doc */
D3_SC_MAPPING ( INTERNATIONAL2 ) ,
D3_SC_MAPPING ( INTERNATIONAL3 ) , /**< Yen */
D3_SC_MAPPING ( INTERNATIONAL4 ) ,
D3_SC_MAPPING ( INTERNATIONAL5 ) ,
D3_SC_MAPPING ( INTERNATIONAL6 ) ,
D3_SC_MAPPING ( INTERNATIONAL7 ) ,
D3_SC_MAPPING ( INTERNATIONAL8 ) ,
D3_SC_MAPPING ( INTERNATIONAL9 ) ,
D3_SC_MAPPING ( THOUSANDSSEPARATOR ) ,
D3_SC_MAPPING ( DECIMALSEPARATOR ) ,
D3_SC_MAPPING ( CURRENCYUNIT ) ,
D3_SC_MAPPING ( CURRENCYSUBUNIT )
# undef D3_SC_MAPPING
} ;
// for keynums between K_FIRST_SCANCODE and K_LAST_SCANCODE
// returns e.g. "SC_A" for K_SC_A
const char * Sys_GetScancodeName ( int key ) {
if ( key > = K_FIRST_SCANCODE & & key < = K_LAST_SCANCODE ) {
int scIdx = key - K_FIRST_SCANCODE ;
return scancodemappings [ scIdx ] . name ;
}
return NULL ;
}
static bool isAscii ( const char * str_ ) {
const unsigned char * str = ( const unsigned char * ) str_ ;
while ( * str ! = ' \0 ' ) {
if ( * str > 127 ) {
return false ;
}
+ + str ;
}
return true ;
}
// returns localized name of the key (between K_FIRST_SCANCODE and K_LAST_SCANCODE),
// regarding the current keyboard layout - if that name is in ASCII or corresponds
// to a "High-ASCII" char supported by Doom3.
// Otherwise return same name as Sys_GetScancodeName()
// !! Returned string is only valid until next call to this function !!
const char * Sys_GetLocalizedScancodeName ( int key ) {
if ( key > = K_FIRST_SCANCODE & & key < = K_LAST_SCANCODE ) {
int scIdx = key - K_FIRST_SCANCODE ;
# if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Scancode sc = ( SDL_Scancode ) scancodemappings [ scIdx ] . sdlScancode ;
SDL_Keycode k = SDL_GetKeyFromScancode ( sc ) ;
if ( k > = 0xA1 & & k < = 0xFF ) {
// luckily, the "High-ASCII" (ISO-8559-1) chars supported by Doom3
// have the same values as the corresponding SDL_Keycodes.
static char oneCharStr [ 2 ] = { 0 , 0 } ;
oneCharStr [ 0 ] = ( unsigned char ) k ;
return oneCharStr ;
} else if ( k ! = SDLK_UNKNOWN ) {
const char * ret = SDL_GetKeyName ( k ) ;
// the keyname from SDL2 is in UTF-8, which Doom3 can't print,
// so only return the name if it's ASCII, otherwise fall back to "SC_bla"
if ( ret & & * ret ! = ' \0 ' & & isAscii ( ret ) ) {
return ret ;
}
}
# endif // SDL1.2 doesn't support this, use unlocalized name (also as fallback if we couldn't get a keyname)
return scancodemappings [ scIdx ] . name ;
}
return NULL ;
}
// returns keyNum_t (K_SC_* constant) for given scancode name (like "SC_A")
// only makes sense to call it if name starts with "SC_" (or "sc_")
// returns -1 if not found
int Sys_GetKeynumForScancodeName ( const char * name ) {
for ( int scIdx = 0 ; scIdx < K_NUM_SCANCODES ; + + scIdx ) {
if ( idStr : : Icmp ( name , scancodemappings [ scIdx ] . name ) = = 0 ) {
return scIdx + K_FIRST_SCANCODE ;
}
}
return - 1 ;
}
# if SDL_VERSION_ATLEAST(2, 0, 0)
static int getKeynumForSDLscancode ( SDL_Scancode scancode ) {
int sc = scancode ;
for ( int scIdx = 0 ; scIdx < K_NUM_SCANCODES ; + + scIdx ) {
if ( scancodemappings [ scIdx ] . sdlScancode = = sc ) {
return scIdx + K_FIRST_SCANCODE ;
}
}
return 0 ;
}
# endif
2012-07-19 20:09:53 +00:00
static byte mapkey ( SDL_Keycode key ) {
2011-12-29 19:36:25 +00:00
switch ( key ) {
case SDLK_BACKSPACE :
return K_BACKSPACE ;
case SDLK_PAUSE :
return K_PAUSE ;
}
if ( key < = SDLK_z )
return key & 0xff ;
switch ( key ) {
2012-07-19 20:09:53 +00:00
case SDLK_APPLICATION :
2011-12-29 19:36:25 +00:00
return K_COMMAND ;
case SDLK_CAPSLOCK :
return K_CAPSLOCK ;
2012-07-19 20:09:53 +00:00
case SDLK_SCROLLLOCK :
2011-12-29 19:36:25 +00:00
return K_SCROLL ;
case SDLK_POWER :
return K_POWER ;
case SDLK_UP :
return K_UPARROW ;
case SDLK_DOWN :
return K_DOWNARROW ;
case SDLK_LEFT :
return K_LEFTARROW ;
case SDLK_RIGHT :
return K_RIGHTARROW ;
2012-07-19 20:09:53 +00:00
case SDLK_LGUI :
2011-12-29 19:36:25 +00:00
return K_LWIN ;
2012-07-19 20:09:53 +00:00
case SDLK_RGUI :
2011-12-29 19:36:25 +00:00
return K_RWIN ;
case SDLK_MENU :
return K_MENU ;
case SDLK_LALT :
return K_ALT ;
2021-07-03 12:42:14 +00:00
case SDLK_RALT :
return K_RIGHT_ALT ;
2011-12-29 19:36:25 +00:00
case SDLK_RCTRL :
2021-07-03 12:42:14 +00:00
return K_RIGHT_CTRL ;
2011-12-29 19:36:25 +00:00
case SDLK_LCTRL :
return K_CTRL ;
case SDLK_RSHIFT :
2021-07-03 12:42:14 +00:00
return K_RIGHT_SHIFT ;
2011-12-29 19:36:25 +00:00
case SDLK_LSHIFT :
return K_SHIFT ;
case SDLK_INSERT :
return K_INS ;
case SDLK_DELETE :
return K_DEL ;
case SDLK_PAGEDOWN :
return K_PGDN ;
case SDLK_PAGEUP :
return K_PGUP ;
case SDLK_HOME :
return K_HOME ;
case SDLK_END :
return K_END ;
case SDLK_F1 :
return K_F1 ;
case SDLK_F2 :
return K_F2 ;
case SDLK_F3 :
return K_F3 ;
case SDLK_F4 :
return K_F4 ;
case SDLK_F5 :
return K_F5 ;
case SDLK_F6 :
return K_F6 ;
case SDLK_F7 :
return K_F7 ;
case SDLK_F8 :
return K_F8 ;
case SDLK_F9 :
return K_F9 ;
case SDLK_F10 :
return K_F10 ;
case SDLK_F11 :
return K_F11 ;
case SDLK_F12 :
return K_F12 ;
// K_INVERTED_EXCLAMATION;
case SDLK_F13 :
return K_F13 ;
case SDLK_F14 :
return K_F14 ;
case SDLK_F15 :
return K_F15 ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_7 :
2011-12-29 19:36:25 +00:00
return K_KP_HOME ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_8 :
2011-12-29 19:36:25 +00:00
return K_KP_UPARROW ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_9 :
2011-12-29 19:36:25 +00:00
return K_KP_PGUP ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_4 :
2011-12-29 19:36:25 +00:00
return K_KP_LEFTARROW ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_5 :
2011-12-29 19:36:25 +00:00
return K_KP_5 ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_6 :
2011-12-29 19:36:25 +00:00
return K_KP_RIGHTARROW ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_1 :
2011-12-29 19:36:25 +00:00
return K_KP_END ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_2 :
2011-12-29 19:36:25 +00:00
return K_KP_DOWNARROW ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_3 :
2011-12-29 19:36:25 +00:00
return K_KP_PGDN ;
case SDLK_KP_ENTER :
return K_KP_ENTER ;
2012-07-19 20:09:53 +00:00
case SDLK_KP_0 :
2011-12-29 19:36:25 +00:00
return K_KP_INS ;
case SDLK_KP_PERIOD :
return K_KP_DEL ;
case SDLK_KP_DIVIDE :
return K_KP_SLASH ;
// K_SUPERSCRIPT_TWO;
case SDLK_KP_MINUS :
return K_KP_MINUS ;
// K_ACUTE_ACCENT;
case SDLK_KP_PLUS :
return K_KP_PLUS ;
2012-07-19 20:09:53 +00:00
case SDLK_NUMLOCKCLEAR :
2011-12-29 19:36:25 +00:00
return K_KP_NUMLOCK ;
case SDLK_KP_MULTIPLY :
return K_KP_STAR ;
case SDLK_KP_EQUALS :
return K_KP_EQUALS ;
// K_MASCULINE_ORDINATOR;
// K_GRAVE_A;
// K_AUX1;
// K_CEDILLA_C;
// K_GRAVE_E;
// K_AUX2;
// K_AUX3;
// K_AUX4;
// K_GRAVE_I;
// K_AUX5;
// K_AUX6;
// K_AUX7;
// K_AUX8;
// K_TILDE_N;
// K_GRAVE_O;
// K_AUX9;
// K_AUX10;
// K_AUX11;
// K_AUX12;
// K_AUX13;
// K_AUX14;
// K_GRAVE_U;
// K_AUX15;
// K_AUX16;
2012-07-19 20:09:53 +00:00
case SDLK_PRINTSCREEN :
2011-12-29 19:36:25 +00:00
return K_PRINT_SCR ;
case SDLK_MODE :
2021-07-03 12:42:14 +00:00
// FIXME: is this really right alt? (also mapping SDLK_RALT to K_RIGHT_ALT)
2011-12-29 19:36:25 +00:00
return K_RIGHT_ALT ;
}
return 0 ;
}
2011-12-29 19:48:41 +00:00
static void PushConsoleEvent ( const char * s ) {
char * b ;
size_t len ;
len = strlen ( s ) + 1 ;
b = ( char * ) Mem_Alloc ( len ) ;
strcpy ( b , s ) ;
SDL_Event event ;
event . type = SDL_USEREVENT ;
event . user . code = SE_CONSOLE ;
event . user . data1 = ( void * ) len ;
event . user . data2 = b ;
SDL_PushEvent ( & event ) ;
}
2011-12-29 19:36:25 +00:00
/*
= = = = = = = = = = = = = = = = =
Sys_InitInput
= = = = = = = = = = = = = = = = =
*/
void Sys_InitInput ( ) {
kbd_polls . SetGranularity ( 64 ) ;
mouse_polls . SetGranularity ( 64 ) ;
2021-07-03 02:33:27 +00:00
assert ( sizeof ( scancodemappings ) / sizeof ( scancodemappings [ 0 ] ) = = K_NUM_SCANCODES & & " scancodemappings incomplete? " ) ;
2012-07-19 20:09:53 +00:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
2011-12-29 19:36:25 +00:00
SDL_EnableUNICODE ( 1 ) ;
SDL_EnableKeyRepeat ( SDL_DEFAULT_REPEAT_DELAY , SDL_DEFAULT_REPEAT_INTERVAL ) ;
2012-07-19 20:09:53 +00:00
# endif
2011-12-29 19:36:25 +00:00
in_kbd . SetModified ( ) ;
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
Sys_GetConsoleKey ( false ) ; // initialize consoleKeymappingIdx from in_kbd
2021-07-03 13:18:55 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
const char * grabKeyboardEnv = SDL_getenv ( SDL_HINT_GRAB_KEYBOARD ) ;
if ( grabKeyboardEnv ) {
common - > Printf ( " The SDL_GRAB_KEYBOARD environment variable is set, setting the in_grabKeyboard CVar to the same value (%s) \n " , grabKeyboardEnv ) ;
in_grabKeyboard . SetString ( grabKeyboardEnv ) ;
} else {
in_grabKeyboard . SetModified ( ) ;
}
# else // SDL1.2 doesn't support this
in_grabKeyboard . ClearModified ( ) ;
# endif
2011-12-29 19:36:25 +00:00
}
/*
= = = = = = = = = = = = = = = = =
Sys_ShutdownInput
= = = = = = = = = = = = = = = = =
*/
void Sys_ShutdownInput ( ) {
kbd_polls . Clear ( ) ;
mouse_polls . Clear ( ) ;
}
/*
= = = = = = = = = = =
Sys_InitScanTable
= = = = = = = = = = =
*/
2011-12-30 00:05:42 +00:00
// Windows has its own version due to the tools
# ifndef _WIN32
2011-12-29 19:36:25 +00:00
void Sys_InitScanTable ( ) {
}
2011-12-30 00:05:42 +00:00
# endif
2011-12-29 19:36:25 +00:00
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
struct ConsoleKeyMapping {
const char * langName ;
unsigned char key ;
unsigned char keyShifted ;
} ;
static ConsoleKeyMapping consoleKeyMappings [ ] = {
# if SDL_VERSION_ATLEAST(2, 0, 0)
{ " auto " , 0 , 0 } , // special case: set current keycode for SDL_SCANCODE_GRAVE (no shifted keycode, though)
# endif
{ " english " , ' ` ' , ' ~ ' } ,
{ " french " , ' < ' , ' > ' } ,
{ " german " , ' ^ ' , 176 } , // °
{ " italian " , ' \\ ' , ' | ' } ,
{ " spanish " , 186 , 170 } , // º ª
{ " turkish " , ' " ' , 233 } , // é
{ " norwegian " , 124 , 167 } , // | §
{ " brazilian " , ' \' ' , ' " ' } ,
} ;
static int consoleKeyMappingIdx = 0 ;
static void initConsoleKeyMapping ( ) {
const int numMappings = sizeof ( consoleKeyMappings ) / sizeof ( consoleKeyMappings [ 0 ] ) ;
idStr lang = in_kbd . GetString ( ) ;
consoleKeyMappingIdx = 0 ;
# if SDL_VERSION_ATLEAST(2, 0, 0)
consoleKeyMappings [ 0 ] . key = 0 ;
if ( lang . Length ( ) = = 0 | | lang . Icmp ( " auto " ) = = 0 ) {
// auto-detection (SDL2-only)
int keycode = SDL_GetKeyFromScancode ( SDL_SCANCODE_GRAVE ) ;
if ( keycode > 0 & & keycode < = 0xFF ) {
// the SDL keycode and dhewm3 keycode should be identical for the mappings,
// as it's ISO-8859-1 ("High ASCII") chars
for ( int i = 1 ; i < numMappings ; + + i ) {
if ( consoleKeyMappings [ i ] . key = = keycode ) {
consoleKeyMappingIdx = i ;
common - > Printf ( " Detected keyboard layout as \" %s \" \n " , consoleKeyMappings [ i ] . langName ) ;
break ;
}
}
if ( consoleKeyMappingIdx = = 0 ) { // not found in known mappings
consoleKeyMappings [ 0 ] . key = keycode ;
}
}
} else
# endif
{
for ( int i = 1 ; i < numMappings ; + + i ) {
if ( lang . Icmp ( consoleKeyMappings [ i ] . langName ) = = 0 ) {
consoleKeyMappingIdx = i ;
# if SDL_VERSION_ATLEAST(2, 0, 0)
int keycode = SDL_GetKeyFromScancode ( SDL_SCANCODE_GRAVE ) ;
if ( keycode & & keycode ! = consoleKeyMappings [ i ] . key ) {
common - > Warning ( " in_kbd is set to \" %s \" , but the actual keycode of the 'console key' is %c (%d), not %c (%d), so this might not work that well.. \n " ,
lang . c_str ( ) , ( unsigned char ) keycode , keycode , consoleKeyMappings [ i ] . key , consoleKeyMappings [ i ] . key ) ;
}
# endif
break ;
}
}
}
}
2011-12-29 19:36:25 +00:00
/*
= = = = = = = = = = = = = = =
Sys_GetConsoleKey
= = = = = = = = = = = = = = =
*/
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
unsigned char Sys_GetConsoleKey ( bool shifted ) {
2011-12-29 19:36:25 +00:00
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
if ( in_ignoreConsoleKey . GetBool ( ) ) {
return 0 ;
}
if ( in_kbd . IsModified ( ) ) {
initConsoleKeyMapping ( ) ;
2011-12-29 19:36:25 +00:00
in_kbd . ClearModified ( ) ;
}
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
return shifted ? consoleKeyMappings [ consoleKeyMappingIdx ] . keyShifted : consoleKeyMappings [ consoleKeyMappingIdx ] . key ;
2011-12-29 19:36:25 +00:00
}
/*
= = = = = = = = = = = = = = =
Sys_MapCharForKey
= = = = = = = = = = = = = = =
*/
unsigned char Sys_MapCharForKey ( int key ) {
return key & 0xff ;
}
/*
= = = = = = = = = = = = = = =
Sys_GrabMouseCursor
= = = = = = = = = = = = = = =
*/
void Sys_GrabMouseCursor ( bool grabIt ) {
2012-07-19 19:07:47 +00:00
int flags ;
if ( grabIt )
flags = GRAB_ENABLE | GRAB_HIDECURSOR | GRAB_SETSTATE ;
else
flags = GRAB_SETSTATE ;
2012-07-19 19:13:02 +00:00
GLimp_GrabInput ( flags ) ;
2011-12-29 19:36:25 +00:00
}
/*
= = = = = = = = = = = = = = = =
Sys_GetEvent
= = = = = = = = = = = = = = = =
*/
sysEvent_t Sys_GetEvent ( ) {
SDL_Event ev ;
sysEvent_t res = { } ;
2021-07-03 02:33:27 +00:00
int key ;
2011-12-29 19:36:25 +00:00
static const sysEvent_t res_none = { SE_NONE , 0 , 0 , 0 , NULL } ;
2012-07-19 20:09:53 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
2015-09-30 13:41:14 +00:00
static char s [ SDL_TEXTINPUTEVENT_TEXT_SIZE ] = { 0 } ;
2012-07-19 20:09:53 +00:00
static size_t s_pos = 0 ;
2015-09-30 13:41:14 +00:00
if ( s [ 0 ] ! = ' \0 ' ) {
2012-07-19 20:09:53 +00:00
res . evType = SE_CHAR ;
res . evValue = s [ s_pos ] ;
2015-09-30 13:41:14 +00:00
+ + s_pos ;
if ( ! s [ s_pos ] | | s_pos = = SDL_TEXTINPUTEVENT_TEXT_SIZE ) {
memset ( s , 0 , sizeof ( s ) ) ;
2012-07-19 20:09:53 +00:00
s_pos = 0 ;
}
return res ;
}
# endif
2011-12-29 19:36:25 +00:00
static byte c = 0 ;
if ( c ) {
res . evType = SE_CHAR ;
res . evValue = c ;
c = 0 ;
return res ;
}
2015-09-30 13:58:50 +00:00
// loop until there is an event we care about (will return then) or no more events
while ( SDL_PollEvent ( & ev ) ) {
2011-12-29 19:36:25 +00:00
switch ( ev . type ) {
2012-07-19 20:09:53 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_WINDOWEVENT :
switch ( ev . window . event ) {
2013-04-19 18:40:34 +00:00
case SDL_WINDOWEVENT_FOCUS_GAINED : {
// unset modifier, in case alt-tab was used to leave window and ALT is still set
// as that can cause fullscreen-toggling when pressing enter...
SDL_Keymod currentmod = SDL_GetModState ( ) ;
int newmod = KMOD_NONE ;
if ( currentmod & KMOD_CAPS ) // preserve capslock
newmod | = KMOD_CAPS ;
SDL_SetModState ( ( SDL_Keymod ) newmod ) ;
} // new context because visual studio complains about newmod and currentmod not initialized because of the case SDL_WINDOWEVENT_FOCUS_LOST
2012-09-07 23:14:06 +00:00
2020-07-20 03:06:57 +00:00
common - > ActivateTool ( false ) ;
GLimp_GrabInput ( GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR ) ; // FIXME: not sure this is still needed after the ActivateTool()-call
// start playing the game sound world again (when coming from editor)
session - > SetPlayingSoundWorld ( ) ;
2012-07-19 20:09:53 +00:00
break ;
case SDL_WINDOWEVENT_FOCUS_LOST :
GLimp_GrabInput ( 0 ) ;
break ;
}
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2012-07-19 20:09:53 +00:00
# else
2011-12-29 19:36:25 +00:00
case SDL_ACTIVEEVENT :
2012-07-19 19:07:47 +00:00
{
int flags = 0 ;
2012-09-07 23:14:06 +00:00
if ( ev . active . gain ) {
2012-07-19 19:07:47 +00:00
flags = GRAB_ENABLE | GRAB_REENABLE | GRAB_HIDECURSOR ;
2012-09-07 23:14:06 +00:00
// unset modifier, in case alt-tab was used to leave window and ALT is still set
// as that can cause fullscreen-toggling when pressing enter...
SDLMod currentmod = SDL_GetModState ( ) ;
int newmod = KMOD_NONE ;
if ( currentmod & KMOD_CAPS ) // preserve capslock
newmod | = KMOD_CAPS ;
SDL_SetModState ( ( SDLMod ) newmod ) ;
}
2012-07-19 19:13:02 +00:00
GLimp_GrabInput ( flags ) ;
2012-07-19 19:07:47 +00:00
}
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2011-12-29 19:36:25 +00:00
case SDL_VIDEOEXPOSE :
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2012-07-19 20:09:53 +00:00
# endif
2011-12-29 19:36:25 +00:00
case SDL_KEYDOWN :
2012-01-18 23:22:47 +00:00
if ( ev . key . keysym . sym = = SDLK_RETURN & & ( ev . key . keysym . mod & KMOD_ALT ) > 0 ) {
2011-12-29 19:53:54 +00:00
cvarSystem - > SetCVarBool ( " r_fullscreen " , ! renderSystem - > IsFullScreen ( ) ) ;
PushConsoleEvent ( " vid_restart " ) ;
return res_none ;
}
// fall through
2011-12-29 19:36:25 +00:00
case SDL_KEYUP :
2013-07-22 15:45:10 +00:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
Workaround to better support AZERTY keyboards
The first row of AZERTY-Keyboards (used in France and Belgium) doesn't
have numbers as keys but ², &, é, ", ', (, -, è, _, ç, à , ), =
(with small differences between France and Belgium).
For some of those keys we don't have keycodes - and neither does SDL2.
See also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
As a workaround, just map those keys to 1, 2, ..., 9, 0 anyway, as those
are keys Quake2 already knows (and those chars are printed on the keys
too, for typing they're reachable via shift).
This workaround only works for SDL2, as SDL1.2 doesn't have Scancodes
which we need to identify the keys.
This should obsolete one part of pull request #135
2015-11-22 22:21:30 +00:00
key = mapkey ( ev . key . keysym . sym ) ;
2011-12-29 19:36:25 +00:00
if ( ! key ) {
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
if ( ! in_ignoreConsoleKey . GetBool ( ) ) {
// check if its an unmapped console key
int c = Sys_GetConsoleKey ( ( ev . key . keysym . mod & KMOD_SHIFT ) ! = 0 ) ;
if ( ev . key . keysym . unicode = = c ) {
key = c ;
}
}
if ( ! key ) {
2012-01-04 23:00:20 +00:00
if ( ev . type = = SDL_KEYDOWN )
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
common - > Warning ( " unmapped SDL key %d (0x%x) - if possible use SDL2 for better keyboard support " ,
ev . key . keysym . sym , ev . key . keysym . unicode ) ;
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2012-01-04 23:00:20 +00:00
}
2011-12-29 19:36:25 +00:00
}
2013-07-22 15:45:10 +00:00
# else
Workaround to better support AZERTY keyboards
The first row of AZERTY-Keyboards (used in France and Belgium) doesn't
have numbers as keys but ², &, é, ", ', (, -, è, _, ç, à , ), =
(with small differences between France and Belgium).
For some of those keys we don't have keycodes - and neither does SDL2.
See also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
As a workaround, just map those keys to 1, 2, ..., 9, 0 anyway, as those
are keys Quake2 already knows (and those chars are printed on the keys
too, for typing they're reachable via shift).
This workaround only works for SDL2, as SDL1.2 doesn't have Scancodes
which we need to identify the keys.
This should obsolete one part of pull request #135
2015-11-22 22:21:30 +00:00
{
// workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
// always map those physical keys (scancodes) to those keycodes anyway
// see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
SDL_Scancode sc = ev . key . keysym . scancode ;
if ( sc = = SDL_SCANCODE_0 )
{
key = ' 0 ' ;
}
else if ( sc > = SDL_SCANCODE_1 & & sc < = SDL_SCANCODE_9 )
{
// note that the SDL_SCANCODEs are SDL_SCANCODE_1, _2, ..., _9, SDL_SCANCODE_0
// while in ASCII it's '0', '1', ..., '9' => handle 0 and 1-9 separately
// (doom3 uses the ASCII values for those keys)
key = ' 1 ' + ( sc - SDL_SCANCODE_1 ) ;
}
else
{
key = mapkey ( ev . key . keysym . sym ) ;
}
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
if ( ! in_ignoreConsoleKey . GetBool ( ) & & ev . key . keysym . scancode = = SDL_SCANCODE_GRAVE ) {
// that key between Esc, Tab and 1 is the console key
key = K_CONSOLE ;
}
if ( ! key ) {
// if the key couldn't be mapped so far, try to map the scancode to K_SC_*
key = getKeynumForSDLscancode ( sc ) ;
if ( ! key ) {
if ( ev . type = = SDL_KEYDOWN ) {
common - > Warning ( " unmapped SDL key %d (scancode %d) " , ev . key . keysym . sym , ( int ) sc ) ;
2013-07-22 15:45:10 +00:00
}
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
continue ; // handle next event
2013-07-22 15:45:10 +00:00
}
}
Workaround to better support AZERTY keyboards
The first row of AZERTY-Keyboards (used in France and Belgium) doesn't
have numbers as keys but ², &, é, ", ', (, -, è, _, ç, à , ), =
(with small differences between France and Belgium).
For some of those keys we don't have keycodes - and neither does SDL2.
See also https://bugzilla.libsdl.org/show_bug.cgi?id=3188
As a workaround, just map those keys to 1, 2, ..., 9, 0 anyway, as those
are keys Quake2 already knows (and those chars are printed on the keys
too, for typing they're reachable via shift).
This workaround only works for SDL2, as SDL1.2 doesn't have Scancodes
which we need to identify the keys.
This should obsolete one part of pull request #135
2015-11-22 22:21:30 +00:00
}
2013-07-22 15:45:10 +00:00
# endif
2011-12-29 19:36:25 +00:00
res . evType = SE_KEY ;
res . evValue = key ;
res . evValue2 = ev . key . state = = SDL_PRESSED ? 1 : 0 ;
kbd_polls . Append ( kbd_poll_t ( key , ev . key . state = = SDL_PRESSED ) ) ;
2012-07-19 20:09:53 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
if ( key = = K_BACKSPACE & & ev . key . state = = SDL_PRESSED )
c = key ;
# else
2011-12-29 19:36:25 +00:00
if ( ev . key . state = = SDL_PRESSED & & ( ev . key . keysym . unicode & 0xff00 ) = = 0 )
c = ev . key . keysym . unicode & 0xff ;
2012-07-19 20:09:53 +00:00
# endif
2011-12-29 19:36:25 +00:00
return res ;
2012-07-19 20:09:53 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_TEXTINPUT :
2015-09-27 16:05:04 +00:00
if ( ev . text . text [ 0 ] ) {
2015-09-30 13:41:14 +00:00
res . evType = SE_CHAR ;
res . evValue = ev . text . text [ 0 ] ;
Improve handling of "console key", add in_ignoreConsoleKey CVar
If in_ignoreConsoleKey is set, the console can only be opened with
Shift+Esc, not `/^/whatever, so you can easily type whatever character
is on your "console key" into the game, or even bind that key.
Otherwise, with SDL2, that key (KEY_SCANCODE_GRAVE) always generates the
newly added K_CONSOLE.
in_kbd has a new (SDL2-only) "auto" mode which tries to detect the
keyboard layout based on SDL_GetKeyFromScancode( SDL_SCANCODE_GRAVE ).
Wherever Sys_GetConsoleKey() is called, I now take the current state of
Shift into account, so we don't discard more chars than necessary, esp.
when they keyboard-layout (in_kbd) is *not* correctly set.
(TBH the only reason besides SDL1.2 to keep in_kbd around is to ignore
the char generated by the "console key" in the console..)
2021-07-12 04:15:22 +00:00
// TODO: translate to "ISO-8859-1" with SDL_iconv() ?
2015-09-30 13:41:14 +00:00
if ( ev . text . text [ 1 ] ! = ' \0 ' )
{
memcpy ( s , ev . text . text , SDL_TEXTINPUTEVENT_TEXT_SIZE ) ;
s_pos = 1 ; // pos 0 is returned
}
return res ;
2012-07-19 20:09:53 +00:00
}
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2015-10-05 13:14:42 +00:00
case SDL_TEXTEDITING :
// on windows we get this event whenever the window gains focus.. just ignore it.
continue ;
2012-07-19 20:09:53 +00:00
# endif
2011-12-29 19:36:25 +00:00
case SDL_MOUSEMOTION :
res . evType = SE_MOUSE ;
res . evValue = ev . motion . xrel ;
res . evValue2 = ev . motion . yrel ;
mouse_polls . Append ( mouse_poll_t ( M_DELTAX , ev . motion . xrel ) ) ;
mouse_polls . Append ( mouse_poll_t ( M_DELTAY , ev . motion . yrel ) ) ;
return res ;
2012-07-19 20:09:53 +00:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
case SDL_MOUSEWHEEL :
res . evType = SE_KEY ;
if ( ev . wheel . y > 0 ) {
res . evValue = K_MWHEELUP ;
mouse_polls . Append ( mouse_poll_t ( M_DELTAZ , 1 ) ) ;
} else {
res . evValue = K_MWHEELDOWN ;
mouse_polls . Append ( mouse_poll_t ( M_DELTAZ , - 1 ) ) ;
}
res . evValue2 = 1 ;
return res ;
# endif
2011-12-29 19:36:25 +00:00
case SDL_MOUSEBUTTONDOWN :
case SDL_MOUSEBUTTONUP :
res . evType = SE_KEY ;
switch ( ev . button . button ) {
case SDL_BUTTON_LEFT :
res . evValue = K_MOUSE1 ;
mouse_polls . Append ( mouse_poll_t ( M_ACTION1 , ev . button . state = = SDL_PRESSED ? 1 : 0 ) ) ;
break ;
case SDL_BUTTON_MIDDLE :
res . evValue = K_MOUSE3 ;
mouse_polls . Append ( mouse_poll_t ( M_ACTION3 , ev . button . state = = SDL_PRESSED ? 1 : 0 ) ) ;
break ;
case SDL_BUTTON_RIGHT :
res . evValue = K_MOUSE2 ;
mouse_polls . Append ( mouse_poll_t ( M_ACTION2 , ev . button . state = = SDL_PRESSED ? 1 : 0 ) ) ;
break ;
2012-07-19 20:09:53 +00:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
2011-12-29 19:36:25 +00:00
case SDL_BUTTON_WHEELUP :
res . evValue = K_MWHEELUP ;
if ( ev . button . state = = SDL_PRESSED )
mouse_polls . Append ( mouse_poll_t ( M_DELTAZ , 1 ) ) ;
break ;
case SDL_BUTTON_WHEELDOWN :
res . evValue = K_MWHEELDOWN ;
if ( ev . button . state = = SDL_PRESSED )
mouse_polls . Append ( mouse_poll_t ( M_DELTAZ , - 1 ) ) ;
break ;
2012-07-19 20:09:53 +00:00
# endif
2015-10-11 10:46:36 +00:00
default :
# if SDL_VERSION_ATLEAST(2, 0, 0)
// handle X1 button and above
2015-12-13 02:49:29 +00:00
if ( ev . button . button < SDL_BUTTON_LEFT + 8 ) // doesn't support more than 8 mouse buttons
2015-10-11 10:46:36 +00:00
{
int buttonIndex = ev . button . button - SDL_BUTTON_LEFT ;
res . evValue = K_MOUSE1 + buttonIndex ;
mouse_polls . Append ( mouse_poll_t ( M_ACTION1 + buttonIndex , ev . button . state = = SDL_PRESSED ? 1 : 0 ) ) ;
}
else
# endif
continue ; // handle next event
2011-12-29 19:36:25 +00:00
}
res . evValue2 = ev . button . state = = SDL_PRESSED ? 1 : 0 ;
return res ;
2011-12-29 19:48:41 +00:00
case SDL_QUIT :
PushConsoleEvent ( " quit " ) ;
return res_none ;
2011-12-29 19:36:25 +00:00
case SDL_USEREVENT :
switch ( ev . user . code ) {
case SE_CONSOLE :
res . evType = SE_CONSOLE ;
res . evPtrLength = ( intptr_t ) ev . user . data1 ;
res . evPtr = ev . user . data2 ;
return res ;
default :
common - > Warning ( " unknown user event %u " , ev . user . code ) ;
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2011-12-29 19:36:25 +00:00
}
default :
2015-10-23 16:19:46 +00:00
// ok, I don't /really/ care about unknown SDL events. only uncomment this for debugging.
// common->Warning("unknown SDL event 0x%x", ev.type);
2015-09-30 13:58:50 +00:00
continue ; // handle next event
2011-12-29 19:36:25 +00:00
}
}
return res_none ;
}
/*
= = = = = = = = = = = = = = = =
Sys_ClearEvents
= = = = = = = = = = = = = = = =
*/
void Sys_ClearEvents ( ) {
SDL_Event ev ;
while ( SDL_PollEvent ( & ev ) )
;
kbd_polls . SetNum ( 0 , false ) ;
mouse_polls . SetNum ( 0 , false ) ;
}
/*
= = = = = = = = = = = = = = = =
Sys_GenerateEvents
= = = = = = = = = = = = = = = =
*/
void Sys_GenerateEvents ( ) {
char * s = Sys_ConsoleInput ( ) ;
2011-12-29 19:48:41 +00:00
if ( s )
PushConsoleEvent ( s ) ;
2011-12-29 19:36:25 +00:00
2021-07-03 13:18:55 +00:00
# ifndef ID_DEDICATED // doesn't make sense on dedicated server
if ( in_grabKeyboard . IsModified ( ) ) {
# if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetHint ( SDL_HINT_GRAB_KEYBOARD , in_grabKeyboard . GetString ( ) ) ;
if ( in_grabKeyboard . GetBool ( ) ) {
common - > Printf ( " in_grabKeyboard: Will grab the keyboard if mouse is grabbed, so global keyboard-shortcuts (like Alt-Tab or the Windows key) will *not* work \n " ) ;
} else {
common - > Printf ( " in_grabKeyboard: Will *not* grab the keyboard if mouse is grabbed, so global keyboard-shortcuts (like Alt-Tab) will still work \n " ) ;
}
# else
common - > Printf ( " Note: SDL1.2 doesn't support in_grabKeyboard (it's always grabbed if mouse is grabbed) \n " ) ;
# endif
in_grabKeyboard . ClearModified ( ) ;
}
# endif
2011-12-29 19:36:25 +00:00
SDL_PumpEvents ( ) ;
}
/*
= = = = = = = = = = = = = = = =
Sys_PollKeyboardInputEvents
= = = = = = = = = = = = = = = =
*/
int Sys_PollKeyboardInputEvents ( ) {
return kbd_polls . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = =
Sys_ReturnKeyboardInputEvent
= = = = = = = = = = = = = = = =
*/
int Sys_ReturnKeyboardInputEvent ( const int n , int & key , bool & state ) {
if ( n > = kbd_polls . Num ( ) )
return 0 ;
key = kbd_polls [ n ] . key ;
state = kbd_polls [ n ] . state ;
return 1 ;
}
/*
= = = = = = = = = = = = = = = =
Sys_EndKeyboardInputEvents
= = = = = = = = = = = = = = = =
*/
void Sys_EndKeyboardInputEvents ( ) {
kbd_polls . SetNum ( 0 , false ) ;
}
/*
= = = = = = = = = = = = = = = =
Sys_PollMouseInputEvents
= = = = = = = = = = = = = = = =
*/
int Sys_PollMouseInputEvents ( ) {
return mouse_polls . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = =
Sys_ReturnMouseInputEvent
= = = = = = = = = = = = = = = =
*/
int Sys_ReturnMouseInputEvent ( const int n , int & action , int & value ) {
if ( n > = mouse_polls . Num ( ) )
return 0 ;
action = mouse_polls [ n ] . action ;
value = mouse_polls [ n ] . value ;
return 1 ;
}
/*
= = = = = = = = = = = = = = = =
Sys_EndMouseInputEvents
= = = = = = = = = = = = = = = =
*/
void Sys_EndMouseInputEvents ( ) {
mouse_polls . SetNum ( 0 , false ) ;
}