diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt
index bde800ee..d19fed0f 100644
--- a/neo/CMakeLists.txt
+++ b/neo/CMakeLists.txt
@@ -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()
diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp
index 45db61be..52b49285 100644
--- a/neo/framework/Common.cpp
+++ b/neo/framework/Common.cpp
@@ -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());
diff --git a/neo/sys/events.cpp b/neo/sys/events.cpp
new file mode 100644
index 00000000..34abb127
--- /dev/null
+++ b/neo/sys/events.cpp
@@ -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 .
+
+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
+
+#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 );
+
+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_polls;
+static idList 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);
+}
diff --git a/neo/sys/glimp.cpp b/neo/sys/glimp.cpp
index 9a14e399..741e6493 100644
--- a/neo/sys/glimp.cpp
+++ b/neo/sys/glimp.cpp
@@ -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;
}
diff --git a/neo/sys/linux/dedicated.cpp b/neo/sys/linux/dedicated.cpp
index f23e15e2..7cb09f2e 100644
--- a/neo/sys/linux/dedicated.cpp
+++ b/neo/sys/linux/dedicated.cpp
@@ -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
diff --git a/neo/sys/linux/input.cpp b/neo/sys/linux/input.cpp
deleted file mode 100644
index c3405141..00000000
--- a/neo/sys/linux/input.cpp
+++ /dev/null
@@ -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 .
-
-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 ];
-}
diff --git a/neo/sys/linux/main.cpp b/neo/sys/linux/main.cpp
index 7f5cb5d4..26e369ad 100644
--- a/neo/sys/linux/main.cpp
+++ b/neo/sys/linux/main.cpp
@@ -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
diff --git a/neo/sys/posix/posix_main.cpp b/neo/sys/posix/posix_main.cpp
index 77c515d2..bdbf0234 100644
--- a/neo/sys/posix/posix_main.cpp
+++ b/neo/sys/posix/posix_main.cpp
@@ -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
/*
===============
diff --git a/neo/sys/scons/SConscript.core b/neo/sys/scons/SConscript.core
index 1760fb63..4ce95c84 100644
--- a/neo/sys/scons/SConscript.core
+++ b/neo/sys/scons/SConscript.core
@@ -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 \