2 // Copyright (C) 2007 by Martin Moracek
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (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. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 // TODO: event filter should be critical section for threaded filtering
34 #include "input/input.h"
35 #include "vfs/logfile.h"
37 #include "memory/mmgr.h"
42 * Local helper functions & vars
50 SDLKey
KeysymToSDL(KeySym key
)
54 case ksEscape
: ksm
= SDLK_ESCAPE
; break;
55 case ks1
: ksm
= SDLK_1
; break;
56 case ks2
: ksm
= SDLK_2
; break;
57 case ks3
: ksm
= SDLK_3
; break;
58 case ks4
: ksm
= SDLK_4
; break;
59 case ks5
: ksm
= SDLK_5
; break;
60 case ks6
: ksm
= SDLK_6
; break;
61 case ks7
: ksm
= SDLK_7
; break;
62 case ks8
: ksm
= SDLK_8
; break;
63 case ks9
: ksm
= SDLK_9
; break;
64 case ks0
: ksm
= SDLK_0
; break;
65 case ksMinus
: ksm
= SDLK_MINUS
; break;
66 case ksEquals
: ksm
= SDLK_EQUALS
; break;
67 case ksBack
: ksm
= SDLK_BACKSPACE
; break;
68 case ksTab
: ksm
= SDLK_TAB
; break;
69 case ksQ
: ksm
= SDLK_q
; break;
70 case ksW
: ksm
= SDLK_w
; break;
71 case ksE
: ksm
= SDLK_e
; break;
72 case ksR
: ksm
= SDLK_r
; break;
73 case ksT
: ksm
= SDLK_t
; break;
74 case ksY
: ksm
= SDLK_y
; break;
75 case ksU
: ksm
= SDLK_u
; break;
76 case ksI
: ksm
= SDLK_i
; break;
77 case ksO
: ksm
= SDLK_o
; break;
78 case ksP
: ksm
= SDLK_p
; break;
79 case ksA
: ksm
= SDLK_a
; break;
80 case ksS
: ksm
= SDLK_s
; break;
81 case ksD
: ksm
= SDLK_d
; break;
82 case ksF
: ksm
= SDLK_f
; break;
83 case ksG
: ksm
= SDLK_g
; break;
84 case ksH
: ksm
= SDLK_h
; break;
85 case ksJ
: ksm
= SDLK_j
; break;
86 case ksK
: ksm
= SDLK_k
; break;
87 case ksL
: ksm
= SDLK_l
; break;
88 case ksZ
: ksm
= SDLK_z
; break;
89 case ksX
: ksm
= SDLK_x
; break;
90 case ksC
: ksm
= SDLK_c
; break;
91 case ksV
: ksm
= SDLK_v
; break;
92 case ksB
: ksm
= SDLK_b
; break;
93 case ksN
: ksm
= SDLK_n
; break;
94 case ksM
: ksm
= SDLK_m
; break;
95 case ksLBrack
: ksm
= SDLK_LEFTBRACKET
; break;
96 case ksRBrack
: ksm
= SDLK_RIGHTBRACKET
; break;
97 case ksReturn
: ksm
= SDLK_RETURN
; break;
98 case ksLCtrl
: ksm
= SDLK_LCTRL
; break;
99 case ksSemicol
: ksm
= SDLK_SEMICOLON
; break;
100 case ksApos
: ksm
= SDLK_QUOTE
; break;
101 case ksGrave
: ksm
= SDLK_BACKQUOTE
; break;
102 case ksLShift
: ksm
= SDLK_LSHIFT
; break;
103 case ksBacksl
: ksm
= SDLK_BACKSLASH
; break;
104 case ksComma
: ksm
= SDLK_COMMA
; break;
105 case ksPer
: ksm
= SDLK_PERIOD
; break;
106 case ksSlash
: ksm
= SDLK_SLASH
; break;
107 case ksRShift
: ksm
= SDLK_RSHIFT
; break;
108 case ksKpMul
: ksm
= SDLK_KP_MULTIPLY
; break;
109 case ksLMenu
: ksm
= SDLK_LALT
; break;
110 case ksSpace
: ksm
= SDLK_SPACE
; break;
111 case ksCap
: ksm
= SDLK_CAPSLOCK
; break;
112 case ksF1
: ksm
= SDLK_F1
; break;
113 case ksF2
: ksm
= SDLK_F2
; break;
114 case ksF3
: ksm
= SDLK_F3
; break;
115 case ksF4
: ksm
= SDLK_F4
; break;
116 case ksF5
: ksm
= SDLK_F5
; break;
117 case ksF6
: ksm
= SDLK_F6
; break;
118 case ksF7
: ksm
= SDLK_F7
; break;
119 case ksF8
: ksm
= SDLK_F8
; break;
120 case ksF9
: ksm
= SDLK_F9
; break;
121 case ksF10
: ksm
= SDLK_F10
; break;
122 case ksF11
: ksm
= SDLK_F11
; break;
123 case ksF12
: ksm
= SDLK_F12
; break;
124 case ksF13
: ksm
= SDLK_F13
; break;
125 case ksF14
: ksm
= SDLK_F14
; break;
126 case ksF15
: ksm
= SDLK_F15
; break;
127 case ksNum
: ksm
= SDLK_NUMLOCK
; break;
128 case ksScroll
: ksm
= SDLK_SCROLLOCK
; break;
129 case ksKp0
: ksm
= SDLK_KP0
; break;
130 case ksKp1
: ksm
= SDLK_KP1
; break;
131 case ksKp2
: ksm
= SDLK_KP2
; break;
132 case ksKp3
: ksm
= SDLK_KP3
; break;
133 case ksKp4
: ksm
= SDLK_KP4
; break;
134 case ksKp5
: ksm
= SDLK_KP5
; break;
135 case ksKp6
: ksm
= SDLK_KP6
; break;
136 case ksKp7
: ksm
= SDLK_KP7
; break;
137 case ksKp8
: ksm
= SDLK_KP8
; break;
138 case ksKp9
: ksm
= SDLK_KP9
; break;
139 case ksKpSub
: ksm
= SDLK_KP_MINUS
; break;
140 case ksKpAdd
: ksm
= SDLK_KP_PLUS
; break;
141 case ksKpDec
: ksm
= SDLK_KP_PERIOD
; break;
142 case ksRCtrl
: ksm
= SDLK_RCTRL
; break;
143 case ksKpEquals
: ksm
= SDLK_KP_EQUALS
; break;
144 case ksKpDiv
: ksm
= SDLK_KP_DIVIDE
; break;
145 case ksSysRq
: ksm
= SDLK_SYSREQ
; break;
146 case ksRMenu
: ksm
= SDLK_RALT
; break;
147 case ksPause
: ksm
= SDLK_PAUSE
; break;
148 case ksHome
: ksm
= SDLK_HOME
; break;
149 case ksUp
: ksm
= SDLK_UP
; break;
150 case ksPgUp
: ksm
= SDLK_PAGEUP
; break;
151 case ksLeft
: ksm
= SDLK_LEFT
; break;
152 case ksRight
: ksm
= SDLK_RIGHT
; break;
153 case ksEnd
: ksm
= SDLK_END
; break;
154 case ksDown
: ksm
= SDLK_DOWN
; break;
155 case ksPgDown
: ksm
= SDLK_PAGEDOWN
; break;
156 case ksIns
: ksm
= SDLK_INSERT
; break;
157 case ksDel
: ksm
= SDLK_DELETE
; break;
158 case ksPower
: ksm
= SDLK_POWER
; break;
159 case ksLWin
: ksm
= SDLK_LSUPER
; break;
160 case ksRWin
: ksm
= SDLK_RSUPER
; break;
161 default: ksm
= SDLK_a
; break;
166 KeySym
SDLToKeysym(SDLKey key
)
170 case SDLK_BACKSPACE
: ksm
= ksBack
; break;
171 case SDLK_TAB
: ksm
= ksTab
; break;
172 case SDLK_RETURN
: ksm
= ksReturn
; break;
173 case SDLK_PAUSE
: ksm
= ksPause
; break;
174 case SDLK_ESCAPE
: ksm
= ksEscape
; break;
175 case SDLK_SPACE
: ksm
= ksSpace
; break;
176 case SDLK_QUOTE
: ksm
= ksApos
; break;
177 case SDLK_COMMA
: ksm
= ksComma
; break;
178 case SDLK_MINUS
: ksm
= ksMinus
; break;
179 case SDLK_PERIOD
: ksm
= ksPer
; break;
180 case SDLK_SLASH
: ksm
= ksSlash
; break;
181 case SDLK_0
: ksm
= ks0
; break;
182 case SDLK_1
: ksm
= ks1
; break;
183 case SDLK_2
: ksm
= ks2
; break;
184 case SDLK_3
: ksm
= ks3
; break;
185 case SDLK_4
: ksm
= ks4
; break;
186 case SDLK_5
: ksm
= ks5
; break;
187 case SDLK_6
: ksm
= ks6
; break;
188 case SDLK_7
: ksm
= ks7
; break;
189 case SDLK_8
: ksm
= ks8
; break;
190 case SDLK_9
: ksm
= ks9
; break;
191 case SDLK_SEMICOLON
: ksm
= ksSemicol
; break;
192 case SDLK_EQUALS
: ksm
= ksEquals
; break;
193 case SDLK_LEFTBRACKET
: ksm
= ksLBrack
; break;
194 case SDLK_BACKSLASH
: ksm
= ksBacksl
; break;
195 case SDLK_RIGHTBRACKET
: ksm
= ksRBrack
; break;
196 case SDLK_BACKQUOTE
: ksm
= ksGrave
; break;
197 case SDLK_a
: ksm
= ksA
; break;
198 case SDLK_b
: ksm
= ksB
; break;
199 case SDLK_c
: ksm
= ksC
; break;
200 case SDLK_d
: ksm
= ksD
; break;
201 case SDLK_e
: ksm
= ksE
; break;
202 case SDLK_f
: ksm
= ksF
; break;
203 case SDLK_g
: ksm
= ksG
; break;
204 case SDLK_h
: ksm
= ksH
; break;
205 case SDLK_i
: ksm
= ksI
; break;
206 case SDLK_j
: ksm
= ksJ
; break;
207 case SDLK_k
: ksm
= ksK
; break;
208 case SDLK_l
: ksm
= ksL
; break;
209 case SDLK_m
: ksm
= ksM
; break;
210 case SDLK_n
: ksm
= ksN
; break;
211 case SDLK_o
: ksm
= ksO
; break;
212 case SDLK_p
: ksm
= ksP
; break;
213 case SDLK_q
: ksm
= ksQ
; break;
214 case SDLK_r
: ksm
= ksR
; break;
215 case SDLK_s
: ksm
= ksS
; break;
216 case SDLK_t
: ksm
= ksT
; break;
217 case SDLK_u
: ksm
= ksU
; break;
218 case SDLK_v
: ksm
= ksV
; break;
219 case SDLK_w
: ksm
= ksW
; break;
220 case SDLK_x
: ksm
= ksX
; break;
221 case SDLK_y
: ksm
= ksY
; break;
222 case SDLK_z
: ksm
= ksZ
; break;
223 case SDLK_DELETE
: ksm
= ksDel
; break;
224 case SDLK_KP0
: ksm
= ksKp0
; break;
225 case SDLK_KP1
: ksm
= ksKp1
; break;
226 case SDLK_KP2
: ksm
= ksKp2
; break;
227 case SDLK_KP3
: ksm
= ksKp3
; break;
228 case SDLK_KP4
: ksm
= ksKp4
; break;
229 case SDLK_KP5
: ksm
= ksKp5
; break;
230 case SDLK_KP6
: ksm
= ksKp6
; break;
231 case SDLK_KP7
: ksm
= ksKp7
; break;
232 case SDLK_KP8
: ksm
= ksKp8
; break;
233 case SDLK_KP9
: ksm
= ksKp9
; break;
234 case SDLK_KP_PERIOD
: ksm
= ksKpDec
; break;
235 case SDLK_KP_DIVIDE
: ksm
= ksKpDiv
; break;
236 case SDLK_KP_MULTIPLY
: ksm
= ksKpMul
; break;
237 case SDLK_KP_MINUS
: ksm
= ksKpSub
; break;
238 case SDLK_KP_PLUS
: ksm
= ksKpAdd
; break;
239 case SDLK_KP_ENTER
: ksm
= ksKpEnter
; break;
240 case SDLK_KP_EQUALS
: ksm
= ksKpEquals
; break;
241 case SDLK_UP
: ksm
= ksUp
; break;
242 case SDLK_DOWN
: ksm
= ksDown
; break;
243 case SDLK_RIGHT
: ksm
= ksRight
; break;
244 case SDLK_LEFT
: ksm
= ksLeft
; break;
245 case SDLK_INSERT
: ksm
= ksIns
; break;
246 case SDLK_HOME
: ksm
= ksHome
; break;
247 case SDLK_END
: ksm
= ksEnd
; break;
248 case SDLK_PAGEUP
: ksm
= ksPgUp
; break;
249 case SDLK_PAGEDOWN
: ksm
= ksPgDown
; break;
250 case SDLK_F1
: ksm
= ksF1
; break;
251 case SDLK_F2
: ksm
= ksF2
; break;
252 case SDLK_F3
: ksm
= ksF3
; break;
253 case SDLK_F4
: ksm
= ksF4
; break;
254 case SDLK_F5
: ksm
= ksF5
; break;
255 case SDLK_F6
: ksm
= ksF6
; break;
256 case SDLK_F7
: ksm
= ksF7
; break;
257 case SDLK_F8
: ksm
= ksF8
; break;
258 case SDLK_F9
: ksm
= ksF9
; break;
259 case SDLK_F10
: ksm
= ksF10
; break;
260 case SDLK_F11
: ksm
= ksF11
; break;
261 case SDLK_F12
: ksm
= ksF12
; break;
262 case SDLK_F13
: ksm
= ksF13
; break;
263 case SDLK_F14
: ksm
= ksF14
; break;
264 case SDLK_F15
: ksm
= ksF15
; break;
265 case SDLK_NUMLOCK
: ksm
= ksNum
; break;
266 case SDLK_CAPSLOCK
: ksm
= ksCap
; break;
267 case SDLK_SCROLLOCK
: ksm
= ksScroll
; break;
268 case SDLK_RSHIFT
: ksm
= ksRShift
; break;
269 case SDLK_LSHIFT
: ksm
= ksLShift
; break;
270 case SDLK_RCTRL
: ksm
= ksRCtrl
; break;
271 case SDLK_LCTRL
: ksm
= ksLCtrl
; break;
272 case SDLK_RALT
: ksm
= ksRMenu
; break;
273 case SDLK_LALT
: ksm
= ksLMenu
; break;
274 case SDLK_LSUPER
: ksm
= ksLWin
; break;
275 case SDLK_RSUPER
: ksm
= ksRWin
; break;
276 case SDLK_SYSREQ
: ksm
= ksSysRq
; break;
277 case SDLK_POWER
: ksm
= ksPower
; break;
278 default: ksm
= ksNone
;
285 int EventFilter(const SDL_Event
*event
)
290 if(event
->type
== SDL_MOUSEMOTION
) {
291 sMouseDelta
.x
+= event
->motion
.xrel
;
292 sMouseDelta
.y
+= event
->motion
.yrel
;
293 sMousePos
.x
= event
->motion
.x
;
294 sMousePos
.y
= event
->motion
.y
;
298 return event
->type
== SDL_QUIT
|| event
->type
== SDL_MOUSEBUTTONDOWN
||
299 event
->type
== SDL_MOUSEBUTTONUP
|| event
->type
== SDL_KEYDOWN
||
300 event
->type
== SDL_KEYUP
;
304 * InputInternals class
307 const uint maxButtons
= 5;
309 class Input::InputInternals
{
311 typedef std::deque
<InputEvent
> InputQueue
;
316 bool buttons
[maxButtons
];
322 void ProcessEvent(const SDL_Event
& event
);
324 friend int EventFilter(const SDL_Event
*event
);
327 Input::InputInternals::InputInternals()
329 SDL_EventState(SDL_ACTIVEEVENT
, SDL_IGNORE
);
330 SDL_EventState(SDL_JOYAXISMOTION
, SDL_IGNORE
);
331 SDL_EventState(SDL_JOYBALLMOTION
, SDL_IGNORE
);
332 SDL_EventState(SDL_JOYHATMOTION
, SDL_IGNORE
);
333 SDL_EventState(SDL_JOYBUTTONDOWN
, SDL_IGNORE
);
334 SDL_EventState(SDL_JOYBUTTONUP
, SDL_IGNORE
);
335 SDL_EventState(SDL_VIDEORESIZE
, SDL_IGNORE
);
336 SDL_EventState(SDL_VIDEOEXPOSE
, SDL_IGNORE
);
337 SDL_EventState(SDL_USEREVENT
, SDL_IGNORE
);
338 SDL_EventState(SDL_SYSWMEVENT
, SDL_IGNORE
);
340 // SDL_EnableUNICODE(1);
341 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY
, SDL_DEFAULT_REPEAT_INTERVAL
);
344 sMousePos
.Set(0.0f
, 0.0f
);
345 sMouseDelta
.Set(0.0f
, 0.0f
);
347 std::fill(buttons
, buttons
+ maxButtons
, false);
349 SDL_SetEventFilter(EventFilter
);
352 Input::InputInternals::~InputInternals()
354 SDL_SetEventFilter(NULL
);
357 void Input::InputInternals::ProcessEvent(const SDL_Event
& event
)
363 iqueue
.push_back(ev
);
365 case SDL_MOUSEBUTTONDOWN
:
366 if(event
.button
.button
> 0 && event
.button
.button
<= maxButtons
) {
367 buttons
[event
.button
.button
- 1] = true;
368 ev
.type
= etButtonOn
;
369 ev
.button
= event
.button
.button
- 1;
370 iqueue
.push_back(ev
);
373 case SDL_MOUSEBUTTONUP
:
374 if(event
.button
.button
> 0 && event
.button
.button
<= 3) {
375 buttons
[event
.button
.button
- 1] = false;
376 ev
.type
= etButtonOff
;
377 ev
.button
= event
.button
.button
- 1;
378 iqueue
.push_back(ev
);
383 ev
.key
.sym
= SDLToKeysym(event
.key
.keysym
.sym
);
384 ev
.key
.chr
= event
.key
.keysym
.sym
> 255 ?
385 0 : static_cast<char>(event
.key
.keysym
.sym
);
386 iqueue
.push_back(ev
);
390 ev
.key
.sym
= SDLToKeysym(event
.key
.keysym
.sym
);
391 ev
.key
.chr
= event
.key
.keysym
.sym
> 255 ?
392 0 : static_cast<char>(event
.key
.keysym
.sym
);
393 iqueue
.push_back(ev
);
399 * Input class implementation
409 Input::Input() : internals_(new InputInternals
)
411 #ifdef LOG_SINGLETONS
412 vLog
<< info() << "Initializing input." << std::endl
;
413 #endif /* LOG_SINGLETONS */
418 #ifdef LOG_SINGLETONS
419 vLog
<< info() << "Releasing input." << std::endl
;
420 #endif /* LOG_SINGLETONS */
424 const Vector2f
Input::GetPosition(void)
429 const Vector2f
Input::GetPositionChange(void)
431 Vector2f res
= sMouseDelta
;
432 sMouseDelta
.Set(0.0f
, 0.0f
);
436 void Input::SetPosition(const Vector2f
& v
)
438 sMouseDelta
.Set(0.0f
, 0.0f
);
442 bool Input::GetButtonState(uint id
)
444 if(id
< maxButtons
) {
445 return internals_
->buttons
[id
];
447 vLog
<< warn("Input")
448 << "Indexing unavailable mouse button." << std::endl
;
453 bool Input::GetCharacterState(char chr
)
455 uint8
* keystate
= SDL_GetKeyState(NULL
);
456 return (keystate
[SDLK_a
+tolower(chr
)] == 1);
459 bool Input::GetKeysymState(KeySym sym
)
461 uint8
* keystate
= SDL_GetKeyState(NULL
);
462 return (keystate
[KeysymToSDL(sym
)] == 1);
465 KeyMod
Input::GetKeyMod(void)
467 return SDL_GetModState();
470 void Input::PumpEvents(void)
474 // process events and fill up the queue
476 while(SDL_PeepEvents(&event
, 1, SDL_GETEVENT
, SDL_ALLEVENTS
) > 0) {
477 internals_
->ProcessEvent(event
);
481 void Input::DropEvents(void)
483 internals_
->iqueue
.resize(0);
486 InputEvent
Input::GetNextEvent(void)
490 if(internals_
->iqueue
.empty()) {
493 event
= internals_
->iqueue
.front();
494 internals_
->iqueue
.pop_front();