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