1 /* _______ __ __ __ ______ __ __ _______ __ __ 2 * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\ 3 * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / / 4 * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / / 5 * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / / 6 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ / 7 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/ 8 * 9 * Copyright (c) 2004, 2005 darkbits Js_./ 10 * Per Larsson a.k.a finalman _RqZ{a<^_aa 11 * Olof Naess�n a.k.a jansem/yakslem _asww7!uY`> )\a// 12 * _Qhm`] _f "'c 1!5m 13 * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[ 14 * .)j(] .d_/ '-( P . S 15 * License: (BSD) <Td/Z <fP"5(\"??"\a. .L 16 * Redistribution and use in source and _dV>ws?a-?' ._/L #' 17 * binary forms, with or without )4d[#7r, . ' )d`)[ 18 * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam' 19 * that the following conditions are met: j<<WP+k/);. _W=j f 20 * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$ 21 * retain the above copyright notice, ]E.pYY(Q]>. a J@\ 22 * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a 23 * following disclaimer. 4'_uomm\. )L);-4 (3= 24 * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[ 25 * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m 26 * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/ 27 * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m 28 * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]' 29 * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W" 30 * 3. Neither the name of Guichan nor the :$we` _! + _/ . j? 31 * names of its contributors may be used =3)= _f (_yQmWW$#( " 32 * to endorse or promote products derived - W, sQQQQmZQ#Wwa].. 33 * from this software without specific (js, \[QQW$QWW#?!V"". 34 * prior written permission. ]y:.<\.. . 35 * -]n w/ ' [. 36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ ! 37 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , ' 38 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- % 39 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r 40 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La 41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L 42 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a 43 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'., 44 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?" 45 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. . 46 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^ 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 49 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 51 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 52 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53 */ 54 55 /* 56 * For comments regarding functions please see the header file. 57 */ 58 #include <assert.h> 59 #include "guichan/sdl/sdlinput.h" 60 #include "guichan/exception.h" 61 62 namespace gcn 63 { SDLInput()64 SDLInput::SDLInput() 65 { 66 mMouseInWindow = true; 67 mMouseDown = false; 68 mIsRepeating = false; 69 } 70 isKeyQueueEmpty()71 bool SDLInput::isKeyQueueEmpty() 72 { 73 return mKeyInputQueue.empty(); 74 } 75 dequeueKeyInput()76 KeyInput SDLInput::dequeueKeyInput() 77 { 78 KeyInput keyInput; 79 80 if (mKeyInputQueue.empty()) 81 { 82 assert(!"The queue is empty."); 83 //throw GCN_EXCEPTION("The queue is empty."); 84 } 85 86 keyInput = mKeyInputQueue.front(); 87 mKeyInputQueue.pop(); 88 89 return keyInput; 90 } 91 isMouseQueueEmpty()92 bool SDLInput::isMouseQueueEmpty() 93 { 94 return mMouseInputQueue.empty(); 95 } 96 dequeueMouseInput()97 MouseInput SDLInput::dequeueMouseInput() 98 { 99 MouseInput mouseInput; 100 101 if (mMouseInputQueue.empty()) 102 { 103 assert(!"The queue is empty."); 104 //throw GCN_EXCEPTION("The queue is empty."); 105 } 106 107 mouseInput = mMouseInputQueue.front(); 108 mMouseInputQueue.pop(); 109 110 return mouseInput; 111 } 112 processKeyRepeat()113 void SDLInput::processKeyRepeat() 114 { 115 KeyInput keyInput; 116 117 if (mIsRepeating) { 118 keyInput.setKey(mLastKey); 119 keyInput.setType(KeyInput::PRESS); 120 mKeyInputQueue.push(keyInput); 121 } 122 } 123 pushInput(SDL_Event event)124 void SDLInput::pushInput(SDL_Event event) 125 { 126 KeyInput keyInput; 127 MouseInput mouseInput; 128 129 switch (event.type) 130 { 131 case SDL_KEYDOWN: 132 mLastKey = convertKeyCharacter(event.key.keysym); 133 mIsRepeating = true; 134 keyInput.setKey(mLastKey); 135 keyInput.setType(KeyInput::PRESS); 136 mKeyInputQueue.push(keyInput); 137 break; 138 139 case SDL_KEYUP: 140 mIsRepeating = false; 141 keyInput.setKey(convertKeyCharacter(event.key.keysym)); 142 keyInput.setType(KeyInput::RELEASE); 143 mKeyInputQueue.push(keyInput); 144 break; 145 146 case SDL_MOUSEBUTTONDOWN: 147 mMouseDown = true; 148 mouseInput.x = event.button.x; 149 mouseInput.y = event.button.y; 150 mouseInput.setButton(convertMouseButton(event.button.button)); 151 mouseInput.setType(MouseInput::PRESS); 152 mouseInput.setTimeStamp(SDL_GetTicks()); 153 mMouseInputQueue.push(mouseInput); 154 break; 155 156 case SDL_MOUSEBUTTONUP: 157 mMouseDown = false; 158 mouseInput.x = event.button.x; 159 mouseInput.y = event.button.y; 160 mouseInput.setButton(convertMouseButton(event.button.button)); 161 mouseInput.setType(MouseInput::RELEASE); 162 mouseInput.setTimeStamp(SDL_GetTicks()); 163 mMouseInputQueue.push(mouseInput); 164 break; 165 166 case SDL_MOUSEMOTION: 167 mouseInput.x = event.button.x; 168 mouseInput.y = event.button.y; 169 mouseInput.setButton(MouseInput::EMPTY); 170 mouseInput.setType(MouseInput::MOTION); 171 mouseInput.setTimeStamp(SDL_GetTicks()); 172 mMouseInputQueue.push(mouseInput); 173 break; 174 175 case SDL_ACTIVEEVENT: 176 /* 177 * This occurs when the mouse leaves the window and the Gui-chan 178 * application loses its mousefocus. 179 */ 180 if ((event.active.state & SDL_APPMOUSEFOCUS) 181 && !event.active.gain) 182 { 183 mMouseInWindow = false; 184 185 if (!mMouseDown) 186 { 187 mouseInput.x = -1; 188 mouseInput.y = -1; 189 mouseInput.setButton(MouseInput::EMPTY); 190 mouseInput.setType(MouseInput::MOTION); 191 mMouseInputQueue.push(mouseInput); 192 } 193 } 194 195 if ((event.active.state & SDL_APPMOUSEFOCUS) 196 && event.active.gain) 197 { 198 mMouseInWindow = true; 199 } 200 break; 201 202 } // end switch 203 } 204 convertMouseButton(int button)205 int SDLInput::convertMouseButton(int button) 206 { 207 switch (button) 208 { 209 case SDL_BUTTON_LEFT: 210 return MouseInput::LEFT; 211 break; 212 case SDL_BUTTON_RIGHT: 213 return MouseInput::RIGHT; 214 break; 215 case SDL_BUTTON_MIDDLE: 216 return MouseInput::MIDDLE; 217 break; 218 case SDL_BUTTON_WHEELUP: 219 return MouseInput::WHEEL_UP; 220 break; 221 case SDL_BUTTON_WHEELDOWN: 222 return MouseInput::WHEEL_DOWN; 223 break; 224 } 225 226 #ifdef DEBUG 227 fprintf(stderr,"Unknown SDL mouse button.\n"); 228 #endif 229 230 return 0; 231 } 232 convertKeyCharacter(SDL_keysym keysym)233 Key SDLInput::convertKeyCharacter(SDL_keysym keysym) 234 { 235 int value = 0; 236 Key key; 237 238 if (keysym.unicode < 255) 239 { 240 if (keysym.unicode == 0) 241 { 242 value = keysym.sym; 243 } 244 else 245 { 246 value = (int)keysym.unicode; 247 } 248 } 249 250 switch (keysym.sym) 251 { 252 case SDLK_TAB: 253 value = Key::K_TAB; 254 break; 255 case SDLK_LALT: 256 value = Key::K_LEFT_ALT; 257 break; 258 case SDLK_RALT: 259 value = Key::K_RIGHT_ALT; 260 break; 261 case SDLK_LSHIFT: 262 value = Key::K_LEFT_SHIFT; 263 break; 264 case SDLK_RSHIFT: 265 value = Key::K_RIGHT_SHIFT; 266 break; 267 case SDLK_LCTRL: 268 value = Key::K_LEFT_CONTROL; 269 break; 270 case SDLK_RCTRL: 271 value = Key::K_RIGHT_CONTROL; 272 break; 273 case SDLK_BACKSPACE: 274 value = Key::K_BACKSPACE; 275 break; 276 case SDLK_PAUSE: 277 value = Key::K_PAUSE; 278 break; 279 case SDLK_SPACE: 280 value = Key::K_SPACE; 281 break; 282 case SDLK_ESCAPE: 283 value = Key::K_ESCAPE; 284 break; 285 case SDLK_DELETE: 286 value = Key::K_DELETE; 287 break; 288 case SDLK_INSERT: 289 value = Key::K_INSERT; 290 break; 291 case SDLK_HOME: 292 value = Key::K_HOME; 293 break; 294 case SDLK_END: 295 value = Key::K_END; 296 break; 297 case SDLK_PAGEUP: 298 value = Key::K_PAGE_UP; 299 break; 300 case SDLK_PRINT: 301 value = Key::K_PRINT_SCREEN; 302 break; 303 case SDLK_PAGEDOWN: 304 value = Key::K_PAGE_DOWN; 305 break; 306 case SDLK_F1: 307 value = Key::K_F1; 308 break; 309 case SDLK_F2: 310 value = Key::K_F2; 311 break; 312 case SDLK_F3: 313 value = Key::K_F3; 314 break; 315 case SDLK_F4: 316 value = Key::K_F4; 317 break; 318 case SDLK_F5: 319 value = Key::K_F5; 320 break; 321 case SDLK_F6: 322 value = Key::K_F6; 323 break; 324 case SDLK_F7: 325 value = Key::K_F7; 326 break; 327 case SDLK_F8: 328 value = Key::K_F8; 329 break; 330 case SDLK_F9: 331 value = Key::K_F9; 332 break; 333 case SDLK_F10: 334 value = Key::K_F10; 335 break; 336 case SDLK_F11: 337 value = Key::K_F11; 338 break; 339 case SDLK_F12: 340 value = Key::K_F12; 341 break; 342 case SDLK_F13: 343 value = Key::K_F13; 344 break; 345 case SDLK_F14: 346 value = Key::K_F14; 347 break; 348 case SDLK_F15: 349 value = Key::K_F15; 350 break; 351 case SDLK_NUMLOCK: 352 value = Key::K_NUM_LOCK; 353 break; 354 case SDLK_CAPSLOCK: 355 value = Key::K_CAPS_LOCK; 356 break; 357 case SDLK_SCROLLOCK: 358 value = Key::K_SCROLL_LOCK; 359 break; 360 case SDLK_RMETA: 361 value = Key::K_RIGHT_META; 362 break; 363 case SDLK_LMETA: 364 value = Key::K_LEFT_META; 365 break; 366 case SDLK_LSUPER: 367 value = Key::K_LEFT_SUPER; 368 break; 369 case SDLK_RSUPER: 370 value = Key::K_RIGHT_SUPER; 371 break; 372 case SDLK_MODE: 373 value = Key::K_ALT_GR; 374 break; 375 case SDLK_UP: 376 value = Key::K_UP; 377 break; 378 case SDLK_DOWN: 379 value = Key::K_DOWN; 380 break; 381 case SDLK_LEFT: 382 value = Key::K_LEFT; 383 break; 384 case SDLK_RIGHT: 385 value = Key::K_RIGHT; 386 break; 387 case SDLK_RETURN: 388 value = Key::K_ENTER; 389 break; 390 case SDLK_KP_ENTER: 391 value = Key::K_ENTER; 392 break; 393 394 default: 395 break; 396 } 397 398 if (!(keysym.mod & KMOD_NUM)) 399 { 400 switch (keysym.sym) 401 { 402 case SDLK_KP0: 403 value = Key::K_INSERT; 404 break; 405 case SDLK_KP1: 406 value = Key::K_END; 407 break; 408 case SDLK_KP2: 409 value = Key::K_DOWN; 410 break; 411 case SDLK_KP3: 412 value = Key::K_PAGE_DOWN; 413 break; 414 case SDLK_KP4: 415 value = Key::K_LEFT; 416 break; 417 case SDLK_KP5: 418 value = 0; 419 break; 420 case SDLK_KP6: 421 value = Key::K_RIGHT; 422 break; 423 case SDLK_KP7: 424 value = Key::K_HOME; 425 break; 426 case SDLK_KP8: 427 value = Key::K_UP; 428 break; 429 case SDLK_KP9: 430 value = Key::K_PAGE_UP; 431 break; 432 default: 433 break; 434 } 435 } 436 437 key.setValue(value); 438 key.setShiftPressed((keysym.mod & KMOD_SHIFT) != 0); 439 key.setControlPressed((keysym.mod & KMOD_CTRL) != 0); 440 key.setAltPressed((keysym.mod & KMOD_ALT) != 0); 441 key.setMetaPressed((keysym.mod & KMOD_META) != 0); 442 443 if (keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS) 444 { 445 key.setNumericPad(true); 446 } 447 448 return key; 449 } 450 } 451