2 Copyright (C) 2003 T. Joseph Carter
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 TODOs until first commit:
21 1. Hide and/or show the mouse whether the mainwindow is focused or not.
22 2. Minimize when losing focus in fullscreen mode.
23 d 3. GrabInput while mainwindow is active.
32 // Tell startup code that we have a client
33 int cl_available = true;
34 static int vid_usingmouse;
35 static int vid_isfullscreen;
37 static SDL_Surface *screen;
39 static Uint8 in_mouse_buttons;
41 static void IN_Init( void );
42 static void IN_Shutdown( void );
44 /////////////////////////
47 //TODO: Add joystick support
48 //TODO: Add error checking
51 //keysym to quake keysym mapping
52 #define tenoh 0,0,0,0,0, 0,0,0,0,0
53 #define fiftyoh tenoh, tenoh, tenoh, tenoh, tenoh
54 #define hundredoh fiftyoh, fiftyoh
55 static unsigned int tbl_sdltoquake[] =
57 0,0,0,0, //SDLK_UNKNOWN = 0,
58 0,0,0,0, //SDLK_FIRST = 0,
59 K_BACKSPACE, //SDLK_BACKSPACE = 8,
60 K_TAB, //SDLK_TAB = 9,
63 K_ENTER, //SDLK_RETURN = 13,
65 K_PAUSE, //SDLK_PAUSE = 19,
67 K_ESCAPE, //SDLK_ESCAPE = 27,
69 K_SPACE, //SDLK_SPACE = 32,
70 '!', //SDLK_EXCLAIM = 33,
71 '"', //SDLK_QUOTEDBL = 34,
72 '#', //SDLK_HASH = 35,
73 '$', //SDLK_DOLLAR = 36,
75 '&', //SDLK_AMPERSAND = 38,
76 '\'', //SDLK_QUOTE = 39,
77 '(', //SDLK_LEFTPAREN = 40,
78 ')', //SDLK_RIGHTPAREN = 41,
79 '*', //SDLK_ASTERISK = 42,
80 '+', //SDLK_PLUS = 43,
81 ',', //SDLK_COMMA = 44,
82 '-', //SDLK_MINUS = 45,
83 '.', //SDLK_PERIOD = 46,
84 '/', //SDLK_SLASH = 47,
95 ':', //SDLK_COLON = 58,
96 ';', //SDLK_SEMICOLON = 59,
97 '<', //SDLK_LESS = 60,
98 '=', //SDLK_EQUALS = 61,
99 '>', //SDLK_GREATER = 62,
100 '?', //SDLK_QUESTION = 63,
102 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,
103 '[', //SDLK_LEFTBRACKET = 91,
104 '\\', //SDLK_BACKSLASH = 92,
105 ']', //SDLK_RIGHTBRACKET = 93,
106 '^', //SDLK_CARET = 94,
107 '_', //SDLK_UNDERSCORE = 95,
108 '`', //SDLK_BACKQUOTE = 96,
136 K_DEL, //SDLK_DELETE = 127,
137 hundredoh /*227*/, tenoh, tenoh, 0,0,0,0,0,0,0,0,
138 K_KP_0, //SDLK_KP0 = 256,
139 K_KP_1, //SDLK_KP1 = 257,
140 K_KP_2, //SDLK_KP2 = 258,
141 K_KP_3, //SDLK_KP3 = 259,
142 K_KP_4, //SDLK_KP4 = 260,
143 K_KP_5, //SDLK_KP5 = 261,
144 K_KP_6, //SDLK_KP6 = 262,
145 K_KP_7, //SDLK_KP7 = 263,
146 K_KP_8, //SDLK_KP8 = 264,
147 K_KP_9, //SDLK_KP9 = 265,
148 K_KP_PERIOD,//SDLK_KP_PERIOD = 266,
149 K_KP_DIVIDE,//SDLK_KP_DIVIDE = 267,
150 K_KP_MULTIPLY,//SDLK_KP_MULTIPLY= 268,
151 K_KP_MINUS, //SDLK_KP_MINUS = 269,
152 K_KP_PLUS, //SDLK_KP_PLUS = 270,
153 K_KP_ENTER, //SDLK_KP_ENTER = 271,
154 K_KP_EQUALS,//SDLK_KP_EQUALS = 272,
155 K_UPARROW, //SDLK_UP = 273,
156 K_DOWNARROW,//SDLK_DOWN = 274,
157 K_RIGHTARROW,//SDLK_RIGHT = 275,
158 K_LEFTARROW,//SDLK_LEFT = 276,
159 K_INS, //SDLK_INSERT = 277,
160 K_HOME, //SDLK_HOME = 278,
161 K_END, //SDLK_END = 279,
162 K_PGUP, //SDLK_PAGEUP = 280,
163 K_PGDN, //SDLK_PAGEDOWN = 281,
164 K_F1, //SDLK_F1 = 282,
165 K_F2, //SDLK_F2 = 283,
166 K_F3, //SDLK_F3 = 284,
167 K_F4, //SDLK_F4 = 285,
168 K_F5, //SDLK_F5 = 286,
169 K_F6, //SDLK_F6 = 287,
170 K_F7, //SDLK_F7 = 288,
171 K_F8, //SDLK_F8 = 289,
172 K_F9, //SDLK_F9 = 290,
173 K_F10, //SDLK_F10 = 291,
174 K_F11, //SDLK_F11 = 292,
175 K_F12, //SDLK_F12 = 293,
180 K_NUMLOCK, //SDLK_NUMLOCK = 300,
181 K_CAPSLOCK, //SDLK_CAPSLOCK = 301,
182 K_SCROLLOCK,//SDLK_SCROLLOCK= 302,
183 K_SHIFT, //SDLK_RSHIFT = 303,
184 K_SHIFT, //SDLK_LSHIFT = 304,
185 K_CTRL, //SDLK_RCTRL = 305,
186 K_CTRL, //SDLK_LCTRL = 306,
187 K_ALT, //SDLK_RALT = 307,
188 K_ALT, //SDLK_LALT = 308,
189 0, //SDLK_RMETA = 309,
190 0, //SDLK_LMETA = 310,
191 0, //SDLK_LSUPER = 311, /* Left "Windows" key */
192 0, //SDLK_RSUPER = 312, /* Right "Windows" key */
193 0, //SDLK_MODE = 313, /* "Alt Gr" key */
194 0, //SDLK_COMPOSE = 314, /* Multi-key compose key */
195 0, //SDLK_HELP = 315,
196 0, //SDLK_PRINT = 316,
197 0, //SDLK_SYSREQ = 317,
198 K_PAUSE, //SDLK_BREAK = 318,
199 0, //SDLK_MENU = 319,
200 0, //SDLK_POWER = 320, /* Power Macintosh power key */
201 'e', //SDLK_EURO = 321, /* Some european keyboards */
202 0 //SDLK_UNDO = 322, /* Atari keyboard has Undo */
208 static int MapKey( int sdlkey )
210 if( sdlkey > sizeof(tbl_sdltoquake)/ sizeof(int) )
212 return tbl_sdltoquake[ sdlkey ];
215 static void IN_Activate( void )
217 SDL_WM_GrabInput( SDL_GRAB_ON );
218 SDL_ShowCursor( SDL_DISABLE );
221 static void IN_Deactivate( void )
223 SDL_WM_GrabInput( SDL_GRAB_OFF );
224 SDL_ShowCursor( SDL_ENABLE );
227 void IN_Commands (void)
231 static void IN_MouseMove (usercmd_t *cmd)
237 if( !vid_usingmouse ) {
238 IN_Mouse( cmd, 0, 0 );
242 state = SDL_GetRelativeMouseState( &x, &y );
243 for( i = 0; i < 8 ; i++ )
244 if( state & ~in_mouse_buttons & 1 << i )
245 Key_Event( K_MOUSE1 + i, 0, true );
246 else if( ~state & in_mouse_buttons & 1 << i )
247 Key_Event( K_MOUSE1 + i, 0, false );
249 in_mouse_buttons = state;
251 IN_Mouse( cmd, x, y );
254 void IN_Move( usercmd_t *cmd )
259 static void IN_Init( void )
262 SDL_EnableUNICODE( SDL_ENABLE );
265 in_mouse_buttons = SDL_GetMouseState( NULL, NULL );
266 vid_usingmouse = false;
269 static void IN_Shutdown( void )
273 /////////////////////
277 static int Sys_EventFilter( SDL_Event *event )
279 //TODO: Add a quit query in linux, too - though linux user are more likely to know what they do
281 if( event->type == SDL_QUIT && MessageBox( NULL, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) == IDNO )
290 void Sys_SendKeyEvents( void )
294 while( SDL_PollEvent( &event ) )
295 switch( event.type ) {
301 Key_Event( MapKey( event.key.keysym.sym ), event.key.keysym.unicode, (event.key.state == SDL_PRESSED) );
303 case SDL_ACTIVEEVENT:
304 if( event.active.state == SDL_APPACTIVE )
305 if( event.active.gain )
317 void *GL_GetProcAddress(const char *name)
320 p = SDL_GL_GetProcAddress(name);
324 static int Sys_EventFilter( SDL_Event *event );
327 if (SDL_Init(SDL_INIT_VIDEO) < 0)
328 Sys_Error ("Failed to init video: %s\n", SDL_GetError());
329 vid_isfullscreen = false;
331 SDL_SetEventFilter( (SDL_EventFilter) Sys_EventFilter );
335 int VID_InitMode(int fullscreen, int width, int height, int bpp)
338 int flags = SDL_OPENGL;
339 const char *drivername;
343 We cant switch from one OpenGL video mode to another.
344 Thus we first switch to some stupid 2D mode and then back to OpenGL.
346 SDL_SetVideoMode( 0, 0, 0, 0 );
349 drivername = "opengl32.dll";
350 #elif defined(__APPLE__) && defined(__MACH__)
351 drivername = "OpenGL.framework";
353 drivername = "libGL.so.1";
356 i = COM_CheckParm("-gl_driver");
357 if (i && i < com_argc - 1)
358 drivername = com_argv[i + 1];
359 if (SDL_GL_LoadLibrary(drivername))
361 Con_Printf("Unable to load GL driver \"%s\": ", drivername, SDL_GetError());
365 qglGetString = GL_GetProcAddress("glGetString");
367 // Knghtbrd: should do platform-specific extension string function here
369 if (qglGetString == NULL)
372 Con_Print("Required OpenGL function glGetString not found\n");
376 vid_isfullscreen = false;
378 flags |= SDL_FULLSCREEN;
379 vid_isfullscreen = true;
382 SDL_GL_SetAttribute (SDL_GL_RED_SIZE, 1);
383 SDL_GL_SetAttribute (SDL_GL_GREEN_SIZE, 1);
384 SDL_GL_SetAttribute (SDL_GL_BLUE_SIZE, 1);
385 SDL_GL_SetAttribute (SDL_GL_DEPTH_SIZE, 16);
386 SDL_GL_SetAttribute (SDL_GL_DOUBLEBUFFER, 1);
388 screen = SDL_SetVideoMode(width, height, bpp, flags);
391 Con_Printf("Failed to set video mode to %ix%i: %s\n", width, height, SDL_GetError);
396 gl_renderer = qglGetString(GL_RENDERER);
397 gl_vendor = qglGetString(GL_VENDOR);
398 gl_version = qglGetString(GL_VERSION);
399 gl_extensions = qglGetString(GL_EXTENSIONS);
401 // Knghtbrd: should assign platform-specific extensions here
403 gl_platformextensions = "";
404 gl_videosyncavailable = false;
409 vid_activewindow = false;
410 vid_usingmouse = false;
415 void VID_Shutdown (void)
418 SDL_QuitSubSystem(SDL_INIT_VIDEO);
421 int VID_SetGamma (unsigned short *ramps)
423 return !SDL_SetGammaRamp (ramps, ramps + 256, ramps + 512);
426 int VID_GetGamma (unsigned short *ramps)
428 return !SDL_GetGammaRamp( ramps, ramps + 256, ramps + 512);
431 void VID_GetWindowSize (int *x, int *y, int *width, int *height)
438 void VID_Finish (void)
444 SDL_GL_SwapBuffers();
446 //react on appstate changes
447 appstate = SDL_GetAppState();
449 if( !( appstate & SDL_APPMOUSEFOCUS ) || !( appstate & SDL_APPINPUTFOCUS ) )
450 vid_activewindow = false;
452 vid_activewindow = true;
454 vid_usemouse = false;
455 if( vid_mouse.integer && !key_consoleactive )
457 if( vid_isfullscreen )
459 if( !vid_activewindow )
460 vid_usemouse = false;
462 if( vid_usemouse && !vid_usingmouse ) {
463 vid_usingmouse = true;
465 } else if( !vid_usemouse && vid_usingmouse ) {
466 vid_usingmouse = false;