mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-03-20 17:51:02 +00:00
Port Linux events to SDL
New CVar "in_kbd" to set the layout for the keyboard. SDL 1.2 doesn't offer any way to determine it, and we need this feature to use the same key for toggling the console independent of the keyboard layout. The old "in_nograb" from the Linux backend is still supported.
This commit is contained in:
parent
5d69699edf
commit
79aea4082f
9 changed files with 579 additions and 631 deletions
|
@ -675,6 +675,7 @@ else()
|
|||
set(src_sys_base
|
||||
sys/cpu.cpp
|
||||
sys/threads.cpp
|
||||
sys/events.cpp
|
||||
sys/sys_local.cpp
|
||||
sys/posix/posix_net.cpp
|
||||
sys/posix/posix_signal.cpp
|
||||
|
@ -685,8 +686,6 @@ else()
|
|||
set(src_sys_core
|
||||
${src_stub_util}
|
||||
sys/glimp.cpp
|
||||
sys/posix/posix_input.cpp
|
||||
sys/linux/input.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -2797,6 +2797,14 @@ idCommonLocal::Init
|
|||
=================
|
||||
*/
|
||||
void idCommonLocal::Init( int argc, char **argv ) {
|
||||
#ifdef ID_DEDICATED
|
||||
// we want to use the SDL event queue for dedicated servers. That
|
||||
// requires video to be initialized, so we just use the dummy
|
||||
// driver for headless boxen
|
||||
char dummy[] = "SDL_VIDEODRIVER=dummy\0";
|
||||
SDL_putenv(dummy);
|
||||
#endif
|
||||
|
||||
if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO))
|
||||
Sys_Error("Error while initializing SDL: %s", SDL_GetError());
|
||||
|
||||
|
|
565
neo/sys/events.cpp
Normal file
565
neo/sys/events.cpp
Normal file
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
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"
|
||||
|
||||
#include "sys/sys_public.h"
|
||||
|
||||
const char *kbdNames[] = {
|
||||
"english", "french", "german", "italian", "turkish", NULL
|
||||
};
|
||||
|
||||
idCVar in_nograb("in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "prevents input grabbing");
|
||||
idCVar in_kbd("in_kbd", "english", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "keyboard layout", kbdNames, idCmdSystem::ArgCompletion_String<kbdNames> );
|
||||
|
||||
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;
|
||||
static bool grabbed = false;
|
||||
|
||||
static byte mapkey(SDLKey key) {
|
||||
switch (key) {
|
||||
case SDLK_BACKSPACE:
|
||||
return K_BACKSPACE;
|
||||
case SDLK_PAUSE:
|
||||
return K_PAUSE;
|
||||
}
|
||||
|
||||
if (key <= SDLK_z)
|
||||
return key & 0xff;
|
||||
|
||||
switch (key) {
|
||||
case SDLK_COMPOSE:
|
||||
return K_COMMAND;
|
||||
case SDLK_CAPSLOCK:
|
||||
return K_CAPSLOCK;
|
||||
case SDLK_SCROLLOCK:
|
||||
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;
|
||||
|
||||
case SDLK_LSUPER:
|
||||
return K_LWIN;
|
||||
case SDLK_RSUPER:
|
||||
return K_RWIN;
|
||||
case SDLK_MENU:
|
||||
return K_MENU;
|
||||
|
||||
case SDLK_LALT:
|
||||
return K_ALT;
|
||||
case SDLK_RCTRL:
|
||||
case SDLK_LCTRL:
|
||||
return K_CTRL;
|
||||
case SDLK_RSHIFT:
|
||||
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;
|
||||
|
||||
case SDLK_KP7:
|
||||
return K_KP_HOME;
|
||||
case SDLK_KP8:
|
||||
return K_KP_UPARROW;
|
||||
case SDLK_KP9:
|
||||
return K_KP_PGUP;
|
||||
case SDLK_KP4:
|
||||
return K_KP_LEFTARROW;
|
||||
case SDLK_KP5:
|
||||
return K_KP_5;
|
||||
case SDLK_KP6:
|
||||
return K_KP_RIGHTARROW;
|
||||
case SDLK_KP1:
|
||||
return K_KP_END;
|
||||
case SDLK_KP2:
|
||||
return K_KP_DOWNARROW;
|
||||
case SDLK_KP3:
|
||||
return K_KP_PGDN;
|
||||
case SDLK_KP_ENTER:
|
||||
return K_KP_ENTER;
|
||||
case SDLK_KP0:
|
||||
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;
|
||||
case SDLK_NUMLOCK:
|
||||
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;
|
||||
|
||||
case SDLK_PRINT:
|
||||
return K_PRINT_SCR;
|
||||
case SDLK_MODE:
|
||||
return K_RIGHT_ALT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void GrabInput(bool grab, bool hide_cursor, bool set_state) {
|
||||
#if defined(ID_DEDICATED)
|
||||
return;
|
||||
#else
|
||||
if (set_state)
|
||||
grabbed = grab;
|
||||
|
||||
if (hide_cursor)
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
else
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
if (in_nograb.GetBool())
|
||||
grab = false;
|
||||
|
||||
if (grab)
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
else
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_InitInput
|
||||
=================
|
||||
*/
|
||||
void Sys_InitInput() {
|
||||
kbd_polls.SetGranularity(64);
|
||||
mouse_polls.SetGranularity(64);
|
||||
|
||||
SDL_EnableUNICODE(1);
|
||||
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
|
||||
|
||||
in_kbd.SetModified();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ShutdownInput
|
||||
=================
|
||||
*/
|
||||
void Sys_ShutdownInput() {
|
||||
kbd_polls.Clear();
|
||||
mouse_polls.Clear();
|
||||
}
|
||||
|
||||
/*
|
||||
===========
|
||||
Sys_InitScanTable
|
||||
===========
|
||||
*/
|
||||
void Sys_InitScanTable() {
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_GetConsoleKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_GetConsoleKey(bool shifted) {
|
||||
static unsigned char keys[2] = { '`', '~' };
|
||||
|
||||
if (in_kbd.IsModified()) {
|
||||
idStr lang = in_kbd.GetString();
|
||||
|
||||
if (lang.Length()) {
|
||||
if (!lang.Icmp("french")) {
|
||||
keys[0] = '<';
|
||||
keys[1] = '>';
|
||||
} else if (!lang.Icmp("german")) {
|
||||
keys[0] = '^';
|
||||
keys[1] = 176; // °
|
||||
} else if (!lang.Icmp("italian")) {
|
||||
keys[0] = '\\';
|
||||
keys[1] = '|';
|
||||
} else if (!lang.Icmp("turkish")) {
|
||||
keys[0] = '"';
|
||||
keys[1] = 233; // é
|
||||
}
|
||||
}
|
||||
|
||||
in_kbd.ClearModified();
|
||||
}
|
||||
|
||||
return shifted ? keys[1] : keys[0];
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_MapCharForKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_MapCharForKey(int key) {
|
||||
return key & 0xff;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_GrabMouseCursor
|
||||
===============
|
||||
*/
|
||||
void Sys_GrabMouseCursor(bool grabIt) {
|
||||
GrabInput(grabIt, grabIt, true);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetEvent
|
||||
================
|
||||
*/
|
||||
sysEvent_t Sys_GetEvent() {
|
||||
SDL_Event ev;
|
||||
sysEvent_t res = { };
|
||||
byte key;
|
||||
|
||||
static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };
|
||||
static byte c = 0;
|
||||
|
||||
if (c) {
|
||||
res.evType = SE_CHAR;
|
||||
res.evValue = c;
|
||||
|
||||
c = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
if (SDL_PollEvent(&ev)) {
|
||||
switch (ev.type) {
|
||||
case SDL_ACTIVEEVENT:
|
||||
GrabInput(grabbed && ev.active.gain == 1, ev.active.gain == 1, false);
|
||||
return res_none;
|
||||
|
||||
case SDL_VIDEOEXPOSE:
|
||||
return res_none;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP:
|
||||
key = mapkey(ev.key.keysym.sym);
|
||||
|
||||
if (!key) {
|
||||
common->Warning("unmapped SDL key %d", ev.key.keysym.sym);
|
||||
return res_none;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (ev.key.state == SDL_PRESSED && (ev.key.keysym.unicode & 0xff00) == 0)
|
||||
c = ev.key.keysym.unicode & 0xff;
|
||||
|
||||
return res;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;
|
||||
|
||||
return res;
|
||||
|
||||
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);
|
||||
return res_none;
|
||||
}
|
||||
default:
|
||||
common->Warning("unknown event %u", ev.type);
|
||||
return res_none;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -36,13 +36,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
idCVar sys_videoRam("sys_videoRam", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "Texture memory on the video card (in megabytes) - 0: autodetect", 0, 512);
|
||||
|
||||
#ifdef __unix__
|
||||
// workaround until events are ported to sdl
|
||||
Display *dpy = NULL;
|
||||
Window win = 0;
|
||||
bool dga_found = false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
===================
|
||||
GLimp_Init
|
||||
|
@ -166,19 +159,6 @@ bool GLimp_Init(glimpParms_t parms) {
|
|||
|
||||
glConfig.wgl_extensions_string = "";
|
||||
|
||||
SDL_SysWMinfo info;
|
||||
SDL_VERSION(&info.version);
|
||||
|
||||
if (SDL_GetWMInfo(&info)) {
|
||||
#if defined(__unix__)
|
||||
// workaround until events are ported to sdl
|
||||
if (info.subsystem == SDL_SYSWM_X11) {
|
||||
dpy = info.info.x11.display;
|
||||
win = info.info.x11.window;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,32 +32,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "sys/linux/local.h"
|
||||
|
||||
/*
|
||||
==========
|
||||
input
|
||||
==========
|
||||
*/
|
||||
|
||||
void Sys_InitInput( void ) { }
|
||||
|
||||
void Sys_ShutdownInput( void ) { }
|
||||
|
||||
void Sys_GrabMouseCursor( bool ) { }
|
||||
|
||||
int Sys_PollMouseInputEvents( void ) { return 0; }
|
||||
|
||||
void Sys_EndMouseInputEvents( void ) { }
|
||||
|
||||
int Sys_ReturnMouseInputEvent( const int n, int &action, int &value ) { return 0; }
|
||||
|
||||
int Sys_PollKeyboardInputEvents( void ) { return 0; }
|
||||
|
||||
void Sys_EndKeyboardInputEvents( void ) { }
|
||||
|
||||
int Sys_ReturnKeyboardInputEvent( const int n, int &action, bool &state ) { return 0; }
|
||||
|
||||
unsigned char Sys_MapCharForKey( int key ) { return (unsigned char)key; }
|
||||
|
||||
/*
|
||||
================
|
||||
Sys_GetVideoRam
|
||||
|
|
|
@ -1,563 +0,0 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
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 "sys/platform.h"
|
||||
#include "framework/KeyInput.h"
|
||||
#include "sys/posix/posix_public.h"
|
||||
|
||||
#include "sys/linux/local.h"
|
||||
|
||||
idCVar in_mouse( "in_mouse", "1", CVAR_SYSTEM | CVAR_ARCHIVE, "" );
|
||||
idCVar in_dgamouse( "in_dgamouse", "1", CVAR_SYSTEM | CVAR_ARCHIVE, "" );
|
||||
idCVar in_nograb( "in_nograb", "0", CVAR_SYSTEM | CVAR_NOCHEAT, "" );
|
||||
|
||||
// have a working xkb extension
|
||||
static bool have_xkb = false;
|
||||
|
||||
// toggled by grab calls - decides if we ignore MotionNotify events
|
||||
static bool mouse_active = false;
|
||||
|
||||
// non-DGA pointer-warping mouse input
|
||||
static int mwx, mwy;
|
||||
static int mx = 0, my = 0;
|
||||
|
||||
// time mouse was last reset, we ignore the first 50ms of the mouse to allow settling of events
|
||||
static unsigned int mouse_reset_time = 0;
|
||||
#define MOUSE_RESET_DELAY 50
|
||||
|
||||
// backup original values for pointer grab/ungrab
|
||||
static int mouse_accel_numerator;
|
||||
static int mouse_accel_denominator;
|
||||
static int mouse_threshold;
|
||||
|
||||
static byte s_scantokey[128] = {
|
||||
/* 0 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 8 */ 0, 27, '1', '2', '3', '4', '5', '6', // 27 - ESC
|
||||
/* 10 */ '7', '8', '9', '0', '-', '=', K_BACKSPACE, 9, // 9 - TAB
|
||||
/* 18 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
|
||||
/* 20 */ 'o', 'p', '[', ']', K_ENTER, K_CTRL, 'a', 's',
|
||||
/* 28 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
|
||||
/* 30 */ '\'', '`', K_SHIFT, '\\', 'z', 'x', 'c', 'v',
|
||||
/* 38 */ 'b', 'n', 'm', ',', '.', '/', K_SHIFT, K_KP_STAR,
|
||||
/* 40 */ K_ALT, ' ', K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5,
|
||||
/* 48 */ K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE, 0, K_HOME,
|
||||
/* 50 */ K_UPARROW, K_PGUP, K_KP_MINUS, K_LEFTARROW, K_KP_5, K_RIGHTARROW, K_KP_PLUS, K_END,
|
||||
/* 58 */ K_DOWNARROW, K_PGDN, K_INS, K_DEL, 0, 0, '\\', K_F11,
|
||||
/* 60 */ K_F12, K_HOME, K_UPARROW, K_PGUP, K_LEFTARROW, 0, K_RIGHTARROW, K_END,
|
||||
/* 68 */ K_DOWNARROW, K_PGDN, K_INS, K_DEL, K_ENTER, K_CTRL, K_PAUSE, 0,
|
||||
/* 70 */ '/', K_ALT, 0, 0, 0, 0, 0, 0,
|
||||
/* 78 */ 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
=================
|
||||
IN_Clear_f
|
||||
=================
|
||||
*/
|
||||
void IN_Clear_f( const idCmdArgs &args ) {
|
||||
idKeyInput::ClearStates();
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_InitInput
|
||||
=================
|
||||
*/
|
||||
void Sys_InitInput(void) {
|
||||
int major_in_out, minor_in_out, opcode_rtrn, event_rtrn, error_rtrn;
|
||||
bool ret;
|
||||
|
||||
common->Printf( "\n------- Input Initialization -------\n" );
|
||||
assert( dpy );
|
||||
cmdSystem->AddCommand( "in_clear", IN_Clear_f, CMD_FL_SYSTEM, "reset the input keys" );
|
||||
major_in_out = XkbMajorVersion;
|
||||
minor_in_out = XkbMinorVersion;
|
||||
ret = XkbLibraryVersion( &major_in_out, &minor_in_out );
|
||||
common->Printf( "XKB extension: compile time 0x%x:0x%x, runtime 0x%x:0x%x: %s\n", XkbMajorVersion, XkbMinorVersion, major_in_out, minor_in_out, ret ? "OK" : "Not compatible" );
|
||||
if ( ret ) {
|
||||
ret = XkbQueryExtension( dpy, &opcode_rtrn, &event_rtrn, &error_rtrn, &major_in_out, &minor_in_out );
|
||||
if ( ret ) {
|
||||
common->Printf( "XKB extension present on server ( 0x%x:0x%x )\n", major_in_out, minor_in_out );
|
||||
have_xkb = true;
|
||||
} else {
|
||||
common->Printf( "XKB extension not present on server\n" );
|
||||
have_xkb = false;
|
||||
}
|
||||
} else {
|
||||
have_xkb = false;
|
||||
}
|
||||
common->Printf( "------------------------------------\n" );
|
||||
}
|
||||
|
||||
//#define XEVT_DBG
|
||||
//#define XEVT_DBG2
|
||||
|
||||
static Cursor Sys_XCreateNullCursor( Display *display, Window root ) {
|
||||
Pixmap cursormask;
|
||||
XGCValues xgc;
|
||||
GC gc;
|
||||
XColor dummycolour;
|
||||
Cursor cursor;
|
||||
|
||||
cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
|
||||
xgc.function = GXclear;
|
||||
gc = XCreateGC(display, cursormask, GCFunction, &xgc);
|
||||
XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
|
||||
dummycolour.pixel = 0;
|
||||
dummycolour.red = 0;
|
||||
dummycolour.flags = 04;
|
||||
cursor = XCreatePixmapCursor(display, cursormask, cursormask,
|
||||
&dummycolour,&dummycolour, 0,0);
|
||||
XFreePixmap(display,cursormask);
|
||||
XFreeGC(display,gc);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
static void Sys_XInstallGrabs( void ) {
|
||||
assert( dpy );
|
||||
|
||||
XWarpPointer( dpy, None, win,
|
||||
0, 0, 0, 0,
|
||||
glConfig.vidWidth / 2, glConfig.vidHeight / 2 );
|
||||
|
||||
XSync( dpy, False );
|
||||
|
||||
XDefineCursor( dpy, win, Sys_XCreateNullCursor( dpy, win ) );
|
||||
|
||||
XGrabPointer( dpy, win,
|
||||
False,
|
||||
MOUSE_MASK,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
win,
|
||||
None,
|
||||
CurrentTime );
|
||||
|
||||
XGetPointerControl( dpy, &mouse_accel_numerator, &mouse_accel_denominator,
|
||||
&mouse_threshold );
|
||||
|
||||
XChangePointerControl( dpy, True, True, 1, 1, 0 );
|
||||
|
||||
XSync( dpy, False );
|
||||
|
||||
mouse_reset_time = Sys_Milliseconds ();
|
||||
|
||||
if ( in_dgamouse.GetBool() && !dga_found ) {
|
||||
common->Printf("XF86DGA not available, forcing DGA mouse off\n");
|
||||
in_dgamouse.SetBool( false );
|
||||
}
|
||||
|
||||
if ( in_dgamouse.GetBool() ) {
|
||||
#if defined( ID_ENABLE_DGA )
|
||||
XF86DGADirectVideo( dpy, DefaultScreen( dpy ), XF86DGADirectMouse );
|
||||
XWarpPointer( dpy, None, win, 0, 0, 0, 0, 0, 0 );
|
||||
#endif
|
||||
} else {
|
||||
mwx = glConfig.vidWidth / 2;
|
||||
mwy = glConfig.vidHeight / 2;
|
||||
mx = my = 0;
|
||||
}
|
||||
|
||||
XGrabKeyboard( dpy, win,
|
||||
False,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
CurrentTime );
|
||||
|
||||
XSync( dpy, False );
|
||||
|
||||
mouse_active = true;
|
||||
}
|
||||
|
||||
void Sys_XUninstallGrabs(void) {
|
||||
assert( dpy );
|
||||
|
||||
#if defined( ID_ENABLE_DGA )
|
||||
if ( in_dgamouse.GetBool() ) {
|
||||
common->DPrintf( "DGA Mouse - Disabling DGA DirectVideo\n" );
|
||||
XF86DGADirectVideo( dpy, DefaultScreen( dpy ), 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
XChangePointerControl( dpy, true, true, mouse_accel_numerator,
|
||||
mouse_accel_denominator, mouse_threshold );
|
||||
|
||||
XUngrabPointer( dpy, CurrentTime );
|
||||
XUngrabKeyboard( dpy, CurrentTime );
|
||||
|
||||
XWarpPointer( dpy, None, win,
|
||||
0, 0, 0, 0,
|
||||
glConfig.vidWidth / 2, glConfig.vidHeight / 2);
|
||||
|
||||
XUndefineCursor( dpy, win );
|
||||
|
||||
mouse_active = false;
|
||||
}
|
||||
|
||||
void Sys_GrabMouseCursor( bool grabIt ) {
|
||||
|
||||
#if defined( ID_DEDICATED )
|
||||
return;
|
||||
#endif
|
||||
|
||||
if ( !dpy ) {
|
||||
#ifdef XEVT_DBG
|
||||
common->DPrintf("Sys_GrabMouseCursor: !dpy\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if ( glConfig.isFullscreen ) {
|
||||
if ( !grabIt ) {
|
||||
return; // never ungrab while fullscreen
|
||||
}
|
||||
if ( in_nograb.GetBool() ) {
|
||||
common->DPrintf("forcing in_nograb 0 while running fullscreen\n");
|
||||
in_nograb.SetBool( false );
|
||||
}
|
||||
}
|
||||
|
||||
if ( in_nograb.GetBool() ) {
|
||||
if ( in_dgamouse.GetBool() ) {
|
||||
common->DPrintf("in_nograb 1, forcing forcing DGA mouse off\n");
|
||||
in_dgamouse.SetBool( false );
|
||||
}
|
||||
if (grabIt) {
|
||||
mouse_active = true;
|
||||
} else {
|
||||
mouse_active = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( grabIt && !mouse_active ) {
|
||||
Sys_XInstallGrabs();
|
||||
} else if ( !grabIt && mouse_active ) {
|
||||
Sys_XUninstallGrabs();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* XPending() actually performs a blocking read
|
||||
* if no events available. From Fakk2, by way of
|
||||
* Heretic2, by way of SDL, original idea GGI project.
|
||||
* The benefit of this approach over the quite
|
||||
* badly behaved XAutoRepeatOn/Off is that you get
|
||||
* focus handling for free, which is a major win
|
||||
* with debug and windowed mode. It rests on the
|
||||
* assumption that the X server will use the
|
||||
* same timestamp on press/release event pairs
|
||||
* for key repeats.
|
||||
*/
|
||||
static bool Sys_XPendingInput( void ) {
|
||||
// Flush the display connection
|
||||
// and look to see if events are queued
|
||||
XFlush( dpy );
|
||||
if ( XEventsQueued( dpy, QueuedAlready) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// More drastic measures are required -- see if X is ready to talk
|
||||
static struct timeval zero_time;
|
||||
int x11_fd;
|
||||
fd_set fdset;
|
||||
|
||||
x11_fd = ConnectionNumber( dpy );
|
||||
FD_ZERO( &fdset );
|
||||
FD_SET( x11_fd, &fdset );
|
||||
if ( select( x11_fd+1, &fdset, NULL, NULL, &zero_time ) == 1 ) {
|
||||
return XPending( dpy );
|
||||
}
|
||||
|
||||
// Oh well, nothing is ready ..
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept a KeyRelease-KeyPress sequence and ignore
|
||||
*/
|
||||
static bool Sys_XRepeatPress( XEvent *event ) {
|
||||
XEvent peekevent;
|
||||
bool repeated = false;
|
||||
int lookupRet;
|
||||
char buf[5];
|
||||
KeySym keysym;
|
||||
|
||||
if ( Sys_XPendingInput() ) {
|
||||
XPeekEvent( dpy, &peekevent );
|
||||
|
||||
if ((peekevent.type == KeyPress) &&
|
||||
(peekevent.xkey.keycode == event->xkey.keycode) &&
|
||||
(peekevent.xkey.time == event->xkey.time)) {
|
||||
repeated = true;
|
||||
XNextEvent( dpy, &peekevent );
|
||||
// emit an SE_CHAR for the repeat
|
||||
lookupRet = XLookupString( (XKeyEvent*)&peekevent, buf, sizeof(buf), &keysym, NULL );
|
||||
if (lookupRet > 0) {
|
||||
Posix_QueEvent( SE_CHAR, buf[ 0 ], 0, 0, NULL);
|
||||
} else {
|
||||
// shouldn't we be doing a release/press in this order rather?
|
||||
// ( doesn't work .. but that's what I would have expected to do though )
|
||||
Posix_QueEvent( SE_KEY, s_scantokey[peekevent.xkey.keycode], true, 0, NULL);
|
||||
Posix_QueEvent( SE_KEY, s_scantokey[peekevent.xkey.keycode], false, 0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return repeated;
|
||||
}
|
||||
|
||||
/*
|
||||
==========================
|
||||
Posix_PollInput
|
||||
==========================
|
||||
*/
|
||||
void Posix_PollInput() {
|
||||
static char buf[16];
|
||||
static XEvent event;
|
||||
static XKeyEvent *key_event = (XKeyEvent*)&event;
|
||||
int lookupRet;
|
||||
int b, dx, dy;
|
||||
KeySym keysym;
|
||||
|
||||
if ( !dpy ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NOTE: Sys_GetEvent only calls when there are no events left
|
||||
// but here we pump all X events that have accumulated
|
||||
// pump one by one? or use threaded input?
|
||||
while ( XPending( dpy ) ) {
|
||||
XNextEvent( dpy, &event );
|
||||
switch (event.type) {
|
||||
case KeyPress:
|
||||
#ifdef XEVT_DBG
|
||||
if (key_event->keycode > 0x7F)
|
||||
common->DPrintf("WARNING: KeyPress keycode > 0x7F");
|
||||
#endif
|
||||
key_event->keycode &= 0x7F;
|
||||
#ifdef XEVT_DBG2
|
||||
printf("SE_KEY press %d\n", key_event->keycode);
|
||||
#endif
|
||||
Posix_QueEvent( SE_KEY, s_scantokey[key_event->keycode], true, 0, NULL);
|
||||
lookupRet = XLookupString(key_event, buf, sizeof(buf), &keysym, NULL);
|
||||
if (lookupRet > 0) {
|
||||
char s = buf[0];
|
||||
#ifdef XEVT_DBG
|
||||
if (buf[1]!=0)
|
||||
common->DPrintf("WARNING: got XLookupString buffer '%s' (%d)\n", buf, strlen(buf));
|
||||
#endif
|
||||
#ifdef XEVT_DBG2
|
||||
printf("SE_CHAR %s\n", buf);
|
||||
#endif
|
||||
Posix_QueEvent( SE_CHAR, s, 0, 0, NULL);
|
||||
}
|
||||
if (!Posix_AddKeyboardPollEvent( s_scantokey[key_event->keycode], true ))
|
||||
return;
|
||||
break;
|
||||
|
||||
case KeyRelease:
|
||||
if (Sys_XRepeatPress(&event)) {
|
||||
#ifdef XEVT_DBG2
|
||||
printf("RepeatPress\n");
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
#ifdef XEVT_DBG
|
||||
if (key_event->keycode > 0x7F)
|
||||
common->DPrintf("WARNING: KeyRelease keycode > 0x7F");
|
||||
#endif
|
||||
key_event->keycode &= 0x7F;
|
||||
#ifdef XEVT_DBG2
|
||||
printf("SE_KEY release %d\n", key_event->keycode);
|
||||
#endif
|
||||
Posix_QueEvent( SE_KEY, s_scantokey[key_event->keycode], false, 0, NULL);
|
||||
if (!Posix_AddKeyboardPollEvent( s_scantokey[key_event->keycode], false ))
|
||||
return;
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
if (event.xbutton.button == 4) {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELUP, true, 0, NULL);
|
||||
if (!Posix_AddMousePollEvent( M_DELTAZ, 1 ))
|
||||
return;
|
||||
} else if (event.xbutton.button == 5) {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELDOWN, true, 0, NULL);
|
||||
if (!Posix_AddMousePollEvent( M_DELTAZ, -1 ))
|
||||
return;
|
||||
} else {
|
||||
b = -1;
|
||||
if (event.xbutton.button == 1) {
|
||||
b = 0; // K_MOUSE1
|
||||
} else if (event.xbutton.button == 2) {
|
||||
b = 2; // K_MOUSE3
|
||||
} else if (event.xbutton.button == 3) {
|
||||
b = 1; // K_MOUSE2
|
||||
} else if (event.xbutton.button == 6) {
|
||||
b = 3; // K_MOUSE4
|
||||
} else if (event.xbutton.button == 7) {
|
||||
b = 4; // K_MOUSE5
|
||||
}
|
||||
if (b == -1 || b > 4) {
|
||||
common->DPrintf("X ButtonPress %d not supported\n", event.xbutton.button);
|
||||
} else {
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE1 + b, true, 0, NULL);
|
||||
if (!Posix_AddMousePollEvent( M_ACTION1 + b, true ))
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
if (event.xbutton.button == 4) {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELUP, false, 0, NULL);
|
||||
} else if (event.xbutton.button == 5) {
|
||||
Posix_QueEvent( SE_KEY, K_MWHEELDOWN, false, 0, NULL);
|
||||
} else {
|
||||
b = -1;
|
||||
if (event.xbutton.button == 1) {
|
||||
b = 0;
|
||||
} else if (event.xbutton.button == 2) {
|
||||
b = 2;
|
||||
} else if (event.xbutton.button == 3) {
|
||||
b = 1;
|
||||
} else if (event.xbutton.button == 6) {
|
||||
b = 3; // K_MOUSE4
|
||||
} else if (event.xbutton.button == 7) {
|
||||
b = 4; // K_MOUSE5
|
||||
}
|
||||
if (b == -1 || b > 4) {
|
||||
common->DPrintf("X ButtonRelease %d not supported\n", event.xbutton.button);
|
||||
} else {
|
||||
Posix_QueEvent( SE_KEY, K_MOUSE1 + b, false, 0, NULL);
|
||||
if (!Posix_AddMousePollEvent( M_ACTION1 + b, false ))
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
if (!mouse_active)
|
||||
break;
|
||||
if (in_dgamouse.GetBool()) {
|
||||
dx = event.xmotion.x_root;
|
||||
dy = event.xmotion.y_root;
|
||||
|
||||
Posix_QueEvent( SE_MOUSE, dx, dy, 0, NULL);
|
||||
|
||||
// if we overflow here, we'll get a warning, but the delta will be completely processed anyway
|
||||
Posix_AddMousePollEvent( M_DELTAX, dx );
|
||||
if (!Posix_AddMousePollEvent( M_DELTAY, dy ))
|
||||
return;
|
||||
} else {
|
||||
// if it's a center motion, we've just returned from our warp
|
||||
// FIXME: we generate mouse delta on wrap return, but that lags us quite a bit from the initial event..
|
||||
if (event.xmotion.x == glConfig.vidWidth / 2 &&
|
||||
event.xmotion.y == glConfig.vidHeight / 2) {
|
||||
mwx = glConfig.vidWidth / 2;
|
||||
mwy = glConfig.vidHeight / 2;
|
||||
|
||||
Posix_QueEvent( SE_MOUSE, mx, my, 0, NULL);
|
||||
|
||||
Posix_AddMousePollEvent( M_DELTAX, mx );
|
||||
if (!Posix_AddMousePollEvent( M_DELTAY, my ))
|
||||
return;
|
||||
mx = my = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
dx = ((int) event.xmotion.x - mwx);
|
||||
dy = ((int) event.xmotion.y - mwy);
|
||||
mx += dx;
|
||||
my += dy;
|
||||
|
||||
mwx = event.xmotion.x;
|
||||
mwy = event.xmotion.y;
|
||||
XWarpPointer(dpy,None,win,0,0,0,0, (glConfig.vidWidth/2),(glConfig.vidHeight/2));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Sys_ShutdownInput
|
||||
=================
|
||||
*/
|
||||
void Sys_ShutdownInput( void ) { }
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_MapCharForKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_MapCharForKey( int _key ) {
|
||||
int key; // scan key ( != doom key )
|
||||
XkbStateRec kbd_state;
|
||||
XEvent event;
|
||||
KeySym keysym;
|
||||
int lookupRet;
|
||||
char buf[5];
|
||||
|
||||
if ( !have_xkb || !dpy ) {
|
||||
return (unsigned char)_key;
|
||||
}
|
||||
|
||||
// query the current keyboard group, must be passed as bit 13-14 in the constructed XEvent
|
||||
// see X Keyboard Extension library specifications
|
||||
XkbGetState( dpy, XkbUseCoreKbd, &kbd_state );
|
||||
|
||||
// lookup scancode from doom key code. unique hits
|
||||
for ( key = 0; key < 128; key++ ) {
|
||||
if ( _key == s_scantokey[ key ] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( key == 128 ) {
|
||||
// it happens. these, we can't convert
|
||||
common->DPrintf( "Sys_MapCharForKey: doom key %d -> keycode failed\n", _key );
|
||||
return (unsigned char)_key;
|
||||
}
|
||||
|
||||
memset( &event, 0, sizeof( XEvent ) );
|
||||
event.xkey.type = KeyPress;
|
||||
event.xkey.display = dpy;
|
||||
event.xkey.time = CurrentTime;
|
||||
event.xkey.keycode = key;
|
||||
event.xkey.state = kbd_state.group << 13;
|
||||
|
||||
lookupRet = XLookupString( (XKeyEvent *)&event, buf, sizeof( buf ), &keysym, NULL );
|
||||
if ( lookupRet <= 0 ) {
|
||||
Sys_Printf( "Sys_MapCharForKey: XLookupString key 0x%x failed\n", key );
|
||||
return (unsigned char)_key;
|
||||
}
|
||||
if ( lookupRet > 1 ) {
|
||||
// only ever expecting 1 char..
|
||||
Sys_Printf( "Sys_MapCharForKey: XLookupString returned '%s'\n", buf );
|
||||
}
|
||||
return buf[ 0 ];
|
||||
}
|
|
@ -49,15 +49,6 @@ If you have questions concerning this license or the applicable additional terms
|
|||
static idStr basepath;
|
||||
static idStr savepath;
|
||||
|
||||
/*
|
||||
===========
|
||||
Sys_InitScanTable
|
||||
===========
|
||||
*/
|
||||
void Sys_InitScanTable( void ) {
|
||||
common->DPrintf( "TODO: Sys_InitScanTable\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
Sys_DefaultSavePath
|
||||
|
@ -128,15 +119,6 @@ const char *Sys_DefaultBasePath(void) {
|
|||
return LINUX_DEFAULT_PATH;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_GetConsoleKey
|
||||
===============
|
||||
*/
|
||||
unsigned char Sys_GetConsoleKey( bool shifted ) {
|
||||
return shifted ? '~' : '`';
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Sys_Shutdown
|
||||
|
|
|
@ -223,6 +223,7 @@ int Sys_ListFiles( const char *directory, const char *extension, idStrList &list
|
|||
return list.Num();
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
============================================================================
|
||||
EVENT LOOP
|
||||
|
@ -298,6 +299,7 @@ Sys_ClearEvents
|
|||
void Sys_ClearEvents( void ) {
|
||||
eventHead = eventTail = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -912,6 +914,7 @@ char *Sys_ConsoleInput( void ) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef MACOS_X
|
||||
/*
|
||||
called during frame loops, pacifier updates etc.
|
||||
this is only for console input polling and misc mouse grab tasks
|
||||
|
@ -929,6 +932,7 @@ void Sys_GenerateEvents( void ) {
|
|||
Posix_QueEvent( SE_CONSOLE, 0, 0, len, b );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
===============
|
||||
|
|
|
@ -204,8 +204,7 @@ sys_string = ' \
|
|||
if ( local_dedicated == 0 ):
|
||||
sys_string += ' \
|
||||
glimp.cpp \
|
||||
posix/posix_input.cpp \
|
||||
linux/input.cpp'
|
||||
events.cpp'
|
||||
else:
|
||||
sys_string += ' \
|
||||
stub/stub_gl.cpp \
|
||||
|
|
Loading…
Reference in a new issue