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 extern uint32_t SDL_CUSTOM_KEY_UP; 63 64 namespace gcn 65 { SDLInput()66 SDLInput::SDLInput() 67 { 68 mMouseInWindow = true; 69 mMouseDown = false; 70 mIsRepeating = false; 71 } 72 isKeyQueueEmpty()73 bool SDLInput::isKeyQueueEmpty() 74 { 75 return mKeyInputQueue.empty(); 76 } 77 dequeueKeyInput()78 KeyInput SDLInput::dequeueKeyInput() 79 { 80 KeyInput keyInput; 81 82 if (mKeyInputQueue.empty()) 83 { 84 assert(!"The queue is empty."); 85 //throw GCN_EXCEPTION("The queue is empty."); 86 } 87 88 keyInput = mKeyInputQueue.front(); 89 mKeyInputQueue.pop(); 90 91 return keyInput; 92 } 93 isMouseQueueEmpty()94 bool SDLInput::isMouseQueueEmpty() 95 { 96 return mMouseInputQueue.empty(); 97 } 98 dequeueMouseInput()99 MouseInput SDLInput::dequeueMouseInput() 100 { 101 MouseInput mouseInput; 102 103 if (mMouseInputQueue.empty()) 104 { 105 assert(!"The queue is empty."); 106 //throw GCN_EXCEPTION("The queue is empty."); 107 } 108 109 mouseInput = mMouseInputQueue.front(); 110 mMouseInputQueue.pop(); 111 112 return mouseInput; 113 } 114 processKeyRepeat()115 void SDLInput::processKeyRepeat() 116 { 117 KeyInput keyInput; 118 119 if (mIsRepeating) { 120 keyInput.setKey(mLastKey); 121 keyInput.setType(KeyInput::PRESS); 122 mKeyInputQueue.push(keyInput); 123 } 124 } 125 pushInput(SDL_Event event)126 void SDLInput::pushInput(SDL_Event event) 127 { 128 KeyInput keyInput; 129 MouseInput mouseInput; 130 131 switch (event.type) 132 { 133 case SDL_TEXTINPUT: 134 { 135 char* text = event.text.text; 136 if ((uint8_t)text[0] >= 32 || (uint8_t)text[0] < 128) { 137 mLastKey = text[0]; 138 mIsRepeating = true; 139 keyInput.setKey(mLastKey); 140 keyInput.setType(KeyInput::PRESS); 141 mKeyInputQueue.push(keyInput); 142 } 143 } 144 break; 145 146 case SDL_USEREVENT: 147 if (reinterpret_cast<uintptr_t>(event.user.data1) == SDL_CUSTOM_KEY_UP) { 148 mIsRepeating = false; 149 keyInput.setKey(static_cast<char>(event.user.code)); 150 keyInput.setType(KeyInput::RELEASE); 151 mKeyInputQueue.push(keyInput); 152 } 153 154 case SDL_KEYDOWN: 155 if (event.key.keysym.sym < 32 || event.key.keysym.sym >= 128) { 156 mLastKey = convertKeyCharacter(event.key.keysym); 157 mIsRepeating = true; 158 keyInput.setKey(mLastKey); 159 keyInput.setType(KeyInput::PRESS); 160 mKeyInputQueue.push(keyInput); 161 } 162 break; 163 164 case SDL_KEYUP: 165 if (event.key.keysym.sym < 32 || event.key.keysym.sym >= 128) { 166 mIsRepeating = false; 167 keyInput.setKey(convertKeyCharacter(event.key.keysym)); 168 keyInput.setType(KeyInput::RELEASE); 169 mKeyInputQueue.push(keyInput); 170 } 171 break; 172 173 case SDL_MOUSEBUTTONDOWN: 174 mMouseDown = true; 175 mouseInput.x = event.button.x; 176 mouseInput.y = event.button.y; 177 mouseInput.setButton(convertMouseButton(event.button.button)); 178 mouseInput.setType(MouseInput::PRESS); 179 mouseInput.setTimeStamp(SDL_GetTicks()); 180 mMouseInputQueue.push(mouseInput); 181 break; 182 183 case SDL_MOUSEBUTTONUP: 184 mMouseDown = false; 185 mouseInput.x = event.button.x; 186 mouseInput.y = event.button.y; 187 mouseInput.setButton(convertMouseButton(event.button.button)); 188 mouseInput.setType(MouseInput::RELEASE); 189 mouseInput.setTimeStamp(SDL_GetTicks()); 190 mMouseInputQueue.push(mouseInput); 191 break; 192 193 case SDL_MOUSEWHEEL: 194 if (event.wheel.y != 0) { 195 SDL_GetMouseState(&mouseInput.x, &mouseInput.y); 196 if (event.wheel.y > 0) 197 mouseInput.setType(MouseInput::WHEEL_UP); 198 else 199 mouseInput.setType(MouseInput::WHEEL_DOWN); 200 mouseInput.setButton(MouseInput::EMPTY); 201 mouseInput.setTimeStamp(event.wheel.timestamp); 202 mMouseInputQueue.push(mouseInput); 203 } 204 break; 205 206 case SDL_MOUSEMOTION: 207 mouseInput.x = event.button.x; 208 mouseInput.y = event.button.y; 209 mouseInput.setButton(MouseInput::EMPTY); 210 mouseInput.setType(MouseInput::MOTION); 211 mouseInput.setTimeStamp(SDL_GetTicks()); 212 mMouseInputQueue.push(mouseInput); 213 break; 214 215 case SDL_WINDOWEVENT: 216 /* 217 * This occurs when the mouse leaves the window and the Gui-chan 218 * application loses its mousefocus. 219 */ 220 switch (event.window.event) 221 { 222 case SDL_WINDOWEVENT_LEAVE: 223 { 224 mMouseInWindow = false; 225 226 if (!mMouseDown) 227 { 228 mouseInput.x = -1; 229 mouseInput.y = -1; 230 mouseInput.setButton(MouseInput::EMPTY); 231 mouseInput.setType(MouseInput::MOTION); 232 mMouseInputQueue.push(mouseInput); 233 } 234 } 235 break; 236 237 case SDL_WINDOWEVENT_ENTER: 238 mMouseInWindow = true; 239 break; 240 } 241 break; 242 243 } // end switch 244 } 245 convertMouseButton(int button)246 int SDLInput::convertMouseButton(int button) 247 { 248 switch (button) 249 { 250 case SDL_BUTTON_LEFT: 251 return MouseInput::LEFT; 252 break; 253 case SDL_BUTTON_RIGHT: 254 return MouseInput::RIGHT; 255 break; 256 case SDL_BUTTON_MIDDLE: 257 return MouseInput::MIDDLE; 258 break; 259 } 260 261 #ifdef DEBUG 262 fprintf(stderr,"Unknown SDL mouse button.\n"); 263 #endif 264 265 return 0; 266 } 267 convertKeyCharacter(SDL_Keysym keysym)268 Key SDLInput::convertKeyCharacter(SDL_Keysym keysym) 269 { 270 int value = 0; 271 Key key; 272 273 switch (keysym.sym) 274 { 275 case SDLK_TAB: 276 value = Key::K_TAB; 277 break; 278 case SDLK_LALT: 279 value = Key::K_LEFT_ALT; 280 break; 281 case SDLK_RALT: 282 value = Key::K_RIGHT_ALT; 283 break; 284 case SDLK_LSHIFT: 285 value = Key::K_LEFT_SHIFT; 286 break; 287 case SDLK_RSHIFT: 288 value = Key::K_RIGHT_SHIFT; 289 break; 290 case SDLK_LCTRL: 291 value = Key::K_LEFT_CONTROL; 292 break; 293 case SDLK_RCTRL: 294 value = Key::K_RIGHT_CONTROL; 295 break; 296 case SDLK_BACKSPACE: 297 value = Key::K_BACKSPACE; 298 break; 299 case SDLK_PAUSE: 300 value = Key::K_PAUSE; 301 break; 302 case SDLK_SPACE: 303 value = Key::K_SPACE; 304 break; 305 case SDLK_ESCAPE: 306 value = Key::K_ESCAPE; 307 break; 308 case SDLK_DELETE: 309 value = Key::K_DELETE; 310 break; 311 case SDLK_INSERT: 312 value = Key::K_INSERT; 313 break; 314 case SDLK_HOME: 315 value = Key::K_HOME; 316 break; 317 case SDLK_END: 318 value = Key::K_END; 319 break; 320 case SDLK_PAGEUP: 321 value = Key::K_PAGE_UP; 322 break; 323 case SDLK_PRINTSCREEN: 324 value = Key::K_PRINT_SCREEN; 325 break; 326 case SDLK_PAGEDOWN: 327 value = Key::K_PAGE_DOWN; 328 break; 329 case SDLK_F1: 330 value = Key::K_F1; 331 break; 332 case SDLK_F2: 333 value = Key::K_F2; 334 break; 335 case SDLK_F3: 336 value = Key::K_F3; 337 break; 338 case SDLK_F4: 339 value = Key::K_F4; 340 break; 341 case SDLK_F5: 342 value = Key::K_F5; 343 break; 344 case SDLK_F6: 345 value = Key::K_F6; 346 break; 347 case SDLK_F7: 348 value = Key::K_F7; 349 break; 350 case SDLK_F8: 351 value = Key::K_F8; 352 break; 353 case SDLK_F9: 354 value = Key::K_F9; 355 break; 356 case SDLK_F10: 357 value = Key::K_F10; 358 break; 359 case SDLK_F11: 360 value = Key::K_F11; 361 break; 362 case SDLK_F12: 363 value = Key::K_F12; 364 break; 365 case SDLK_F13: 366 value = Key::K_F13; 367 break; 368 case SDLK_F14: 369 value = Key::K_F14; 370 break; 371 case SDLK_F15: 372 value = Key::K_F15; 373 break; 374 case SDLK_NUMLOCKCLEAR: 375 value = Key::K_NUM_LOCK; 376 break; 377 case SDLK_CAPSLOCK: 378 value = Key::K_CAPS_LOCK; 379 break; 380 case SDLK_SCROLLLOCK: 381 value = Key::K_SCROLL_LOCK; 382 break; 383 case SDLK_LGUI: 384 value = Key::K_LEFT_SUPER; 385 break; 386 case SDLK_RGUI: 387 value = Key::K_RIGHT_SUPER; 388 break; 389 case SDLK_MODE: 390 value = Key::K_ALT_GR; 391 break; 392 case SDLK_UP: 393 value = Key::K_UP; 394 break; 395 case SDLK_DOWN: 396 value = Key::K_DOWN; 397 break; 398 case SDLK_LEFT: 399 value = Key::K_LEFT; 400 break; 401 case SDLK_RIGHT: 402 value = Key::K_RIGHT; 403 break; 404 case SDLK_RETURN: 405 value = Key::K_ENTER; 406 break; 407 case SDLK_KP_ENTER: 408 value = Key::K_ENTER; 409 break; 410 411 default: 412 value = keysym.sym; 413 break; 414 } 415 416 if (!(keysym.mod & KMOD_NUM)) 417 { 418 switch (keysym.sym) 419 { 420 case SDLK_KP_0: 421 value = Key::K_INSERT; 422 break; 423 case SDLK_KP_1: 424 value = Key::K_END; 425 break; 426 case SDLK_KP_2: 427 value = Key::K_DOWN; 428 break; 429 case SDLK_KP_3: 430 value = Key::K_PAGE_DOWN; 431 break; 432 case SDLK_KP_4: 433 value = Key::K_LEFT; 434 break; 435 case SDLK_KP_5: 436 value = 0; 437 break; 438 case SDLK_KP_6: 439 value = Key::K_RIGHT; 440 break; 441 case SDLK_KP_7: 442 value = Key::K_HOME; 443 break; 444 case SDLK_KP_8: 445 value = Key::K_UP; 446 break; 447 case SDLK_KP_9: 448 value = Key::K_PAGE_UP; 449 break; 450 default: 451 break; 452 } 453 } 454 455 key.setValue(value); 456 key.setShiftPressed((keysym.mod & KMOD_SHIFT) != 0); 457 key.setControlPressed((keysym.mod & KMOD_CTRL) != 0); 458 key.setAltPressed((keysym.mod & KMOD_ALT) != 0); 459 key.setMetaPressed((keysym.mod & KMOD_GUI) != 0); 460 461 if (keysym.sym >= SDLK_KP_0 && keysym.sym <= SDLK_KP_EQUALS) 462 { 463 key.setNumericPad(true); 464 } 465 466 return key; 467 } 468 } 469