+/////////////////////////
+// Input handling
+////
+//TODO: Add joystick support
+//TODO: Add error checking
+
+
+//keysym to quake keysym mapping
+#define tenoh 0,0,0,0,0, 0,0,0,0,0
+#define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
+#define hundredoh fiftyoh, fiftyoh
+static unsigned int tbl_sdltoquake[] =
+{
+ 0,0,0,0, //SDLK_UNKNOWN = 0,
+ 0,0,0,0, //SDLK_FIRST = 0,
+ K_BACKSPACE, //SDLK_BACKSPACE = 8,
+ K_TAB, //SDLK_TAB = 9,
+ 0,0,
+ 0, //SDLK_CLEAR = 12,
+ K_ENTER, //SDLK_RETURN = 13,
+ 0,0,0,0,0,
+ K_PAUSE, //SDLK_PAUSE = 19,
+ 0,0,0,0,0,0,0,
+ K_ESCAPE, //SDLK_ESCAPE = 27,
+ 0,0,0,0,
+ K_SPACE, //SDLK_SPACE = 32,
+ '!', //SDLK_EXCLAIM = 33,
+ '"', //SDLK_QUOTEDBL = 34,
+ '#', //SDLK_HASH = 35,
+ '$', //SDLK_DOLLAR = 36,
+ 0,
+ '&', //SDLK_AMPERSAND = 38,
+ '\'', //SDLK_QUOTE = 39,
+ '(', //SDLK_LEFTPAREN = 40,
+ ')', //SDLK_RIGHTPAREN = 41,
+ '*', //SDLK_ASTERISK = 42,
+ '+', //SDLK_PLUS = 43,
+ ',', //SDLK_COMMA = 44,
+ '-', //SDLK_MINUS = 45,
+ '.', //SDLK_PERIOD = 46,
+ '/', //SDLK_SLASH = 47,
+ '0', //SDLK_0 = 48,
+ '1', //SDLK_1 = 49,
+ '2', //SDLK_2 = 50,
+ '3', //SDLK_3 = 51,
+ '4', //SDLK_4 = 52,
+ '5', //SDLK_5 = 53,
+ '6', //SDLK_6 = 54,
+ '7', //SDLK_7 = 55,
+ '8', //SDLK_8 = 56,
+ '9', //SDLK_9 = 57,
+ ':', //SDLK_COLON = 58,
+ ';', //SDLK_SEMICOLON = 59,
+ '<', //SDLK_LESS = 60,
+ '=', //SDLK_EQUALS = 61,
+ '>', //SDLK_GREATER = 62,
+ '?', //SDLK_QUESTION = 63,
+ '@', //SDLK_AT = 64,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ '[', //SDLK_LEFTBRACKET = 91,
+ '\\', //SDLK_BACKSLASH = 92,
+ ']', //SDLK_RIGHTBRACKET = 93,
+ '^', //SDLK_CARET = 94,
+ '_', //SDLK_UNDERSCORE = 95,
+ '`', //SDLK_BACKQUOTE = 96,
+ 'a', //SDLK_a = 97,
+ 'b', //SDLK_b = 98,
+ 'c', //SDLK_c = 99,
+ 'd', //SDLK_d = 100,
+ 'e', //SDLK_e = 101,
+ 'f', //SDLK_f = 102,
+ 'g', //SDLK_g = 103,
+ 'h', //SDLK_h = 104,
+ 'i', //SDLK_i = 105,
+ 'j', //SDLK_j = 106,
+ 'k', //SDLK_k = 107,
+ 'l', //SDLK_l = 108,
+ 'm', //SDLK_m = 109,
+ 'n', //SDLK_n = 110,
+ 'o', //SDLK_o = 111,
+ 'p', //SDLK_p = 112,
+ 'q', //SDLK_q = 113,
+ 'r', //SDLK_r = 114,
+ 's', //SDLK_s = 115,
+ 't', //SDLK_t = 116,
+ 'u', //SDLK_u = 117,
+ 'v', //SDLK_v = 118,
+ 'w', //SDLK_w = 119,
+ 'x', //SDLK_x = 120,
+ 'y', //SDLK_y = 121,
+ 'z', //SDLK_z = 122,
+ 0,0,0,0,
+ K_DEL, //SDLK_DELETE = 127,
+ hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
+ K_KP_0, //SDLK_KP0 = 256,
+ K_KP_1, //SDLK_KP1 = 257,
+ K_KP_2, //SDLK_KP2 = 258,
+ K_KP_3, //SDLK_KP3 = 259,
+ K_KP_4, //SDLK_KP4 = 260,
+ K_KP_5, //SDLK_KP5 = 261,
+ K_KP_6, //SDLK_KP6 = 262,
+ K_KP_7, //SDLK_KP7 = 263,
+ K_KP_8, //SDLK_KP8 = 264,
+ K_KP_9, //SDLK_KP9 = 265,
+ K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
+ K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
+ K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
+ K_KP_MINUS, //SDLK_KP_MINUS = 269,
+ K_KP_PLUS, //SDLK_KP_PLUS = 270,
+ K_KP_ENTER, //SDLK_KP_ENTER = 271,
+ K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
+ K_UPARROW, //SDLK_UP = 273,
+ K_DOWNARROW,//SDLK_DOWN = 274,
+ K_RIGHTARROW,//SDLK_RIGHT = 275,
+ K_LEFTARROW,//SDLK_LEFT = 276,
+ K_INS, //SDLK_INSERT = 277,
+ K_HOME, //SDLK_HOME = 278,
+ K_END, //SDLK_END = 279,
+ K_PGUP, //SDLK_PAGEUP = 280,
+ K_PGDN, //SDLK_PAGEDOWN = 281,
+ K_F1, //SDLK_F1 = 282,
+ K_F2, //SDLK_F2 = 283,
+ K_F3, //SDLK_F3 = 284,
+ K_F4, //SDLK_F4 = 285,
+ K_F5, //SDLK_F5 = 286,
+ K_F6, //SDLK_F6 = 287,
+ K_F7, //SDLK_F7 = 288,
+ K_F8, //SDLK_F8 = 289,
+ K_F9, //SDLK_F9 = 290,
+ K_F10, //SDLK_F10 = 291,
+ K_F11, //SDLK_F11 = 292,
+ K_F12, //SDLK_F12 = 293,
+ 0, //SDLK_F13 = 294,
+ 0, //SDLK_F14 = 295,
+ 0, //SDLK_F15 = 296,
+ 0,0,0,
+ K_NUMLOCK, //SDLK_NUMLOCK = 300,
+ K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
+ K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
+ K_SHIFT, //SDLK_RSHIFT = 303,
+ K_SHIFT, //SDLK_LSHIFT = 304,
+ K_CTRL, //SDLK_RCTRL = 305,
+ K_CTRL, //SDLK_LCTRL = 306,
+ K_ALT, //SDLK_RALT = 307,
+ K_ALT, //SDLK_LALT = 308,
+ 0, //SDLK_RMETA = 309,
+ 0, //SDLK_LMETA = 310,
+ 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
+ 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
+ K_ALT, //SDLK_MODE = 313, /* "Alt Gr" key */
+ 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
+ 0, //SDLK_HELP = 315,
+ 0, //SDLK_PRINT = 316,
+ 0, //SDLK_SYSREQ = 317,
+ K_PAUSE, //SDLK_BREAK = 318,
+ 0, //SDLK_MENU = 319,
+ 0, //SDLK_POWER = 320, /* Power Macintosh power key */
+ 'e', //SDLK_EURO = 321, /* Some european keyboards */
+ 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
+};
+#undef tenoh
+#undef fiftyoh
+#undef hundredoh
+
+static int MapKey( unsigned int sdlkey )
+{
+ if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
+ return 0;
+ return tbl_sdltoquake[ sdlkey ];
+}
+
+void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor)
+{
+ if (vid_usingmouse != relative)
+ {
+ vid_usingmouse = relative;
+ cl_ignoremousemoves = 2;
+ SDL_WM_GrabInput( relative ? SDL_GRAB_ON : SDL_GRAB_OFF );
+ }
+ if (vid_usinghidecursor != hidecursor)
+ {
+ vid_usinghidecursor = hidecursor;
+ SDL_ShowCursor( hidecursor ? SDL_DISABLE : SDL_ENABLE);
+ }
+}
+
+static double IN_JoystickGetAxis(SDL_Joystick *joy, int axis, double sensitivity, double deadzone)
+{
+ double value;
+ if (axis < 0 || axis >= SDL_JoystickNumAxes(joy))
+ return 0; // no such axis on this joystick
+ value = SDL_JoystickGetAxis(joy, axis) * (1.0 / 32767.0);
+ value = bound(-1, value, 1);
+ if (fabs(value) < deadzone)
+ return 0; // within deadzone around center
+ return value * sensitivity;
+}
+
+void IN_Move( void )
+{
+ int j;
+ static int old_x = 0, old_y = 0;
+ static int stuck = 0;
+ int x, y;
+ if (vid_usingmouse)
+ {
+ if(vid_stick_mouse.integer)
+ {
+ // have the mouse stuck in the middle, example use: prevent expose effect of beryl during the game when not using
+ // window grabbing. --blub
+
+ // we need 2 frames to initialize the center position
+ if(!stuck)
+ {
+ SDL_WarpMouse(win_half_width, win_half_height);
+ SDL_GetMouseState(&x, &y);
+ SDL_GetRelativeMouseState(&x, &y);
+ ++stuck;
+ } else {
+ SDL_GetRelativeMouseState(&x, &y);
+ in_mouse_x = x + old_x;
+ in_mouse_y = y + old_y;
+ SDL_GetMouseState(&x, &y);
+ old_x = x - win_half_width;
+ old_y = y - win_half_height;
+ SDL_WarpMouse(win_half_width, win_half_height);
+ }
+ } else {
+ SDL_GetRelativeMouseState( &x, &y );
+ in_mouse_x = x;
+ in_mouse_y = y;
+ }
+ }
+
+ SDL_GetMouseState(&x, &y);
+ in_windowmouse_x = x;
+ in_windowmouse_y = y;
+
+ if (vid_numjoysticks && joy_enable.integer && joy_index.integer >= 0 && joy_index.integer < vid_numjoysticks)
+ {
+ SDL_Joystick *joy = vid_joysticks[joy_index.integer];
+ int numballs = SDL_JoystickNumBalls(joy);
+ for (j = 0;j < numballs;j++)
+ {
+ SDL_JoystickGetBall(joy, j, &x, &y);
+ in_mouse_x += x;
+ in_mouse_y += y;
+ }
+ cl.cmd.forwardmove += IN_JoystickGetAxis(joy, joy_axisforward.integer, joy_sensitivityforward.value, joy_deadzoneforward.value) * cl_forwardspeed.value;
+ cl.cmd.sidemove += IN_JoystickGetAxis(joy, joy_axisside.integer, joy_sensitivityside.value, joy_deadzoneside.value) * cl_sidespeed.value;
+ cl.cmd.upmove += IN_JoystickGetAxis(joy, joy_axisup.integer, joy_sensitivityup.value, joy_deadzoneup.value) * cl_upspeed.value;
+ cl.viewangles[0] += IN_JoystickGetAxis(joy, joy_axispitch.integer, joy_sensitivitypitch.value, joy_deadzonepitch.value) * cl.realframetime * cl_pitchspeed.value;
+ cl.viewangles[1] += IN_JoystickGetAxis(joy, joy_axisyaw.integer, joy_sensitivityyaw.value, joy_deadzoneyaw.value) * cl.realframetime * cl_yawspeed.value;
+ //cl.viewangles[2] += IN_JoystickGetAxis(joy, joy_axisroll.integer, joy_sensitivityroll.value, joy_deadzoneroll.value) * cl.realframetime * cl_rollspeed.value;
+ }
+}
+
+/////////////////////
+// Message Handling
+////
+
+static int Sys_EventFilter( SDL_Event *event )
+{
+ //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
+ if (event->type == SDL_QUIT)
+ {
+#ifdef WIN32
+ if (MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO)
+ return 0;
+#endif
+ }
+ return 1;
+}
+
+static keynum_t buttonremap[18] =
+{
+ K_MOUSE1,
+ K_MOUSE3,
+ K_MOUSE2,
+ K_MWHEELUP,
+ K_MWHEELDOWN,
+ K_MOUSE4,
+ K_MOUSE5,
+ K_MOUSE6,
+ K_MOUSE7,
+ K_MOUSE8,
+ K_MOUSE9,
+ K_MOUSE10,
+ K_MOUSE11,
+ K_MOUSE12,
+ K_MOUSE13,
+ K_MOUSE14,
+ K_MOUSE15,
+ K_MOUSE16,
+};
+
+void Sys_SendKeyEvents( void )
+{
+ static qboolean sound_active = true;
+ SDL_Event event;
+
+ while( SDL_PollEvent( &event ) )
+ switch( event.type ) {
+ case SDL_QUIT:
+ Sys_Quit(0);
+ break;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ Key_Event( MapKey( event.key.keysym.sym ), (char)event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
+ break;
+ case SDL_ACTIVEEVENT:
+ if( event.active.state == SDL_APPACTIVE )
+ {
+ if( event.active.gain )
+ vid_hidden = false;
+ else
+ vid_hidden = true;
+ }
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ if (event.button.button <= 18)
+ Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED );
+ break;
+ case SDL_JOYBUTTONDOWN:
+ if (!joy_enable.integer)
+ break; // ignore down events if joystick has been disabled
+ case SDL_JOYBUTTONUP:
+ if (event.jbutton.button < 48)
+ Key_Event( event.jbutton.button + (event.jbutton.button < 16 ? K_JOY1 : K_AUX1 - 16), 0, (event.jbutton.state == SDL_PRESSED) );
+ break;
+ case SDL_VIDEORESIZE:
+ if(vid_resizable.integer < 2)
+ {
+ vid.width = event.resize.w;
+ vid.height = event.resize.h;
+ SDL_SetVideoMode(vid.width, vid.height, video_bpp, video_flags);
+ }
+ break;
+ }
+
+ // enable/disable sound on focus gain/loss
+ if (!vid_hidden && (vid_activewindow || !snd_mutewhenidle.integer))
+ {
+ if (!sound_active)
+ {
+ S_UnblockSound ();
+ sound_active = true;
+ }
+ }
+ else
+ {
+ if (sound_active)
+ {
+ S_BlockSound ();
+ sound_active = false;
+ }
+ }
+}
+
+/////////////////
+// Video system
+////
+