ManaPlus
sdlinput.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2011-2018 The ManaPlus Developers
4  *
5  * This file is part of The ManaPlus Client.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 /* _______ __ __ __ ______ __ __ _______ __ __
22  * / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___ /\ / |\/ /\
23  * / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
24  * / / /__ / / // / // / // / / / ___ / // ___ / // /| ' / /
25  * / /_// /\ / /_// / // / // /_/_ / / // / // /\_/ / // / | / /
26  * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
27  * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
28  *
29  * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessén and Per Larsson
30  * Copyright (C) 2007-2010 The Mana World Development Team
31  *
32  * Js_./
33  * Per Larsson a.k.a finalman _RqZ{a<^_aa
34  * Olof Naessén a.k.a jansem/yakslem _asww7!uY`> )\a//
35  * _Qhm`] _f "'c 1!5m
36  * Visit: http://guichan.darkbits.org )Qk<P ` _: :+' .' "{[
37  * .)j(] .d_/ '-( P . S
38  * License: (BSD) <Td/Z <fP"5(\"??"\a. .L
39  * Redistribution and use in source and _dV>ws?a-?' ._/L #'
40  * binary forms, with or without )4d[#7r, . ' )d`)[
41  * modification, are permitted provided _Q-5'5W..j/?' -?!\)cam'
42  * that the following conditions are met: j<<WP+k/);. _W=j f
43  * 1. Redistributions of source code must .$%w\/]Q . ."' . mj$
44  * retain the above copyright notice, ]E.pYY(Q]>. a [email protected]\
45  * this list of conditions and the j(]1u<sE"L,. . ./^ ]{a
46  * following disclaimer. 4'_uomm\. )L);-4 (3=
47  * 2. Redistributions in binary form must )_]X{Z('a_"a7'<a"a, ]"[
48  * reproduce the above copyright notice, #}<]m7`Za??4,P-"'7. ).m
49  * this list of conditions and the ]d2e)Q(<Q( ?94 b- LQ/
50  * following disclaimer in the <B!</]C)d_, '(<' .f. =C+m
51  * documentation and/or other materials .Z!=J ]e []('-4f _ ) -.)m]'
52  * provided with the distribution. .w[5]' _[ /.)_-"+? _/ <W"
53  * 3. Neither the name of Guichan nor the :$we` _! + _/ . j?
54  * names of its contributors may be used =3)= _f (_yQmWW$#( "
55  * to endorse or promote products derived - W, sQQQQmZQ#Wwa]..
56  * from this software without specific (js, \[QQW$QWW#?!V"".
57  * prior written permission. ]y:.<\.. .
58  * -]n w/ ' [.
59  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT )/ )/ !
60  * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY < (; sac , '
61  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, ]^ .- %
62  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF c < r
63  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR aga< <La
64  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 5% )P'-3L
65  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR _bQf` y`..)a
66  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, ,J?4P'.P"_(\?d'.,
67  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES _Pa,)!f/<[]/ ?"
68  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT _2-..:. .r+_,.. .
69  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ?a.<%"' " -'.a_ _,
70  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ^
71  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
72  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
73  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
74  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
75  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76  */
77 
78 #include "sdlshared.h"
79 
80 #include "input/inputmanager.h"
81 
82 #include "gui/gui.h"
83 #include "gui/sdlinput.h"
84 
85 #include "render/graphics.h"
86 
87 PRAGMA48(GCC diagnostic push)
88 PRAGMA48(GCC diagnostic ignored "-Wshadow")
89 #include <SDL_timer.h>
90 PRAGMA48(GCC diagnostic pop)
91 
92 #include "debug.h"
93 
94 extern volatile time_t cur_time;
95 
96 SDLInput *guiInput = nullptr;
97 
99  mKeyInputQueue(),
100  mMouseInputQueue(),
101  mMouseMoveTime(0),
102  mMouseDown(false),
103  mMouseInWindow(true)
104 {
105 }
106 
108 {
109  if (mKeyInputQueue.empty())
110  return KeyInput();
111 
112  KeyInput keyInput = mKeyInputQueue.front();
113  mKeyInputQueue.pop();
114 
115  return keyInput;
116 }
117 
119 {
120  MouseInput mouseInput;
121 
122  if (mMouseInputQueue.empty())
123  return MouseInput();
124 
125  mouseInput = mMouseInputQueue.front();
126  mMouseInputQueue.pop();
127 
128  return mouseInput;
129 }
130 
131 void SDLInput::pushInput(const SDL_Event &event)
132 {
133  BLOCK_START("SDLInput::pushInput")
134  KeyInput keyInput;
135  MouseInput mouseInput;
136 
137  switch (event.type)
138  {
139  case SDL_KEYDOWN:
140  {
141  keyInput.setType(KeyEventType::PRESSED);
142  convertKeyEventToKey(event, keyInput);
143  mKeyInputQueue.push(keyInput);
144  break;
145  }
146 
147  case SDL_KEYUP:
148  {
150  convertKeyEventToKey(event, keyInput);
151  mKeyInputQueue.push(keyInput);
152  break;
153  }
154 
155 #ifdef USE_SDL2
156  case SDL_TEXTINPUT:
157  keyInput.setType(KeyEventType::PRESSED);
158  keyInput.setKey(Key(KeyValue::TEXTINPUT));
159  keyInput.setText(event.text.text);
160  mKeyInputQueue.push(keyInput);
161  break;
162 
163  case SDL_MOUSEWHEEL:
164  {
165  const int y = event.wheel.y;
166  if (y)
167  {
168  mouseInput.setX(gui->getLastMouseX());
169  mouseInput.setY(gui->getLastMouseY());
170 #ifdef ANDROID
171  mouseInput.setReal(0, 0);
172 #endif // ANDROID
173 
174  mouseInput.setButton(MouseButton::WHEEL);
175  if (y > 0)
177  else
179  mouseInput.setTimeStamp(SDL_GetTicks());
180  mMouseInputQueue.push(mouseInput);
181  }
182 
183  break;
184  }
185 #endif // USE_SDL2
186 
187 #ifdef ANDROID
188 #ifndef USE_SDL2
189  case SDL_ACCELEROMETER:
190  break;
191 #endif // USE_SDL2
192 #endif // ANDROID
193 
194  case SDL_MOUSEBUTTONDOWN:
195  {
196  mMouseDown = true;
197  const int scale = mainGraphics->getScale();
198  const int x = event.button.x / scale;
199  const int y = event.button.y / scale;
200  mouseInput.setX(x);
201  mouseInput.setY(y);
202 #ifdef ANDROID
203 #ifdef USE_SDL2
204  mouseInput.setReal(x, y);
205 #else // USE_SDL2
206 
207  mouseInput.setReal(event.button.realx / scale,
208  event.button.realy / scale);
209 #endif // USE_SDL2
210 #endif // ANDROID
211 
212  mouseInput.setButton(convertMouseButton(event.button.button));
213 
214 #ifndef USE_SDL2
215  if (event.button.button == SDL_BUTTON_WHEELDOWN)
217  else if (event.button.button == SDL_BUTTON_WHEELUP)
219  else
220 #endif // USE_SDL2
221  mouseInput.setType(MouseEventType::PRESSED);
222  mouseInput.setTimeStamp(SDL_GetTicks());
223  mMouseInputQueue.push(mouseInput);
224  break;
225  }
226  case SDL_MOUSEBUTTONUP:
227  {
228  mMouseDown = false;
229  const int scale = mainGraphics->getScale();
230  const int x = event.button.x / scale;
231  const int y = event.button.y / scale;
232  mouseInput.setX(x);
233  mouseInput.setY(y);
234 #ifdef ANDROID
235 #ifdef USE_SDL2
236  mouseInput.setReal(x, y);
237 #else // USE_SDL2
238 
239  mouseInput.setReal(event.button.realx / scale,
240  event.button.realy / scale);
241 #endif // USE_SDL2
242 #endif // ANDROID
243 
244  mouseInput.setButton(convertMouseButton(event.button.button));
245  mouseInput.setType(MouseEventType::RELEASED);
246  mouseInput.setTimeStamp(SDL_GetTicks());
247  mMouseInputQueue.push(mouseInput);
248  break;
249  }
250  case SDL_MOUSEMOTION:
251  {
252  const int scale = mainGraphics->getScale();
253  const int x = event.motion.x / scale;
254  const int y = event.motion.y / scale;
255  mouseInput.setX(x);
256  mouseInput.setY(y);
257 #ifdef ANDROID
258 #ifdef USE_SDL2
259  mouseInput.setReal(x, y);
260 #else // USE_SDL2
261 
262  mouseInput.setReal(event.motion.realx / scale,
263  event.motion.realy / scale);
264 #endif // USE_SDL2
265 #endif // ANDROID
266 
267  mouseInput.setButton(MouseButton::EMPTY);
268  mouseInput.setType(MouseEventType::MOVED);
269  mouseInput.setTimeStamp(SDL_GetTicks());
270  mMouseInputQueue.push(mouseInput);
272  break;
273  }
274 #ifndef USE_SDL2
275  case SDL_ACTIVEEVENT:
276  /*
277  * This occurs when the mouse leaves the window and the Gui-chan
278  * application loses its mousefocus.
279  */
280  if ((event.active.state & SDL_APPMOUSEFOCUS) != 0 &&
281  event.active.gain == 0u)
282  {
283  mMouseInWindow = false;
284 
285  if (!mMouseDown)
286  {
287  mouseInput.setX(-1);
288  mouseInput.setY(-1);
289  mouseInput.setButton(MouseButton::EMPTY);
290  mouseInput.setType(MouseEventType::MOVED);
291  mMouseInputQueue.push(mouseInput);
293  }
294  }
295 
296  if ((event.active.state & SDL_APPMOUSEFOCUS) != 0 &&
297  event.active.gain != 0u)
298  {
299  mMouseInWindow = true;
300  }
301  break;
302 #endif // USE_SDL2
303 
304  default:
305  break;
306  } // end switch
307  BLOCK_END("SDLInput::pushInput")
308 }
309 
310 void SDLInput::convertKeyEventToKey(const SDL_Event &event, KeyInput &keyInput)
311 {
312  keyInput.setKey(Key(convertKeyCharacter(event)));
313  const InputActionT actionId = inputManager.getActionByKey(event);
314  if (actionId > InputAction::NO_VALUE)
315  keyInput.setActionId(actionId);
316 }
317 
319 {
320  switch (button)
321  {
322  case SDL_BUTTON_LEFT:
323  return MouseButton::LEFT;
324  case SDL_BUTTON_RIGHT:
325  return MouseButton::RIGHT;
326  case SDL_BUTTON_MIDDLE:
327  return MouseButton::MIDDLE;
328 #ifndef USE_SDL2
329  case SDL_BUTTON_WHEELUP:
330  case SDL_BUTTON_WHEELDOWN:
331  return MouseButton::EMPTY;
332 #endif // USE_SDL2
333 
334  default:
335  // We have an unknown mouse type which is ignored.
336  logger->log("unknown button type: %d", button);
337  return MouseButton::EMPTY;
338  }
339 }
340 
341 void SDLInput::simulateMouseClick(const int x, const int y,
342  const MouseButtonT button)
343 {
344  MouseInput mouseInput;
345  mouseInput.setX(x);
346  mouseInput.setY(y);
347  mouseInput.setReal(x, y);
348  mouseInput.setButton(MouseButton::EMPTY);
349  mouseInput.setType(MouseEventType::MOVED);
350  mouseInput.setTimeStamp(SDL_GetTicks());
351  mMouseInputQueue.push(mouseInput);
352  mouseInput.setButton(button);
353  mouseInput.setType(MouseEventType::PRESSED);
354  mouseInput.setTimeStamp(SDL_GetTicks());
355  mMouseInputQueue.push(mouseInput);
356  mouseInput.setType(MouseEventType::RELEASED);
357  mouseInput.setTimeStamp(SDL_GetTicks());
358  mMouseInputQueue.push(mouseInput);
359 }
360 
362 {
363  if (gui == nullptr)
364  return;
365 
366  if (mMouseMoveTime == cur_time)
367  return;
368 
370  int x, y;
371  Gui::getMouseState(x, y);
372 
373  MouseInput mouseInput;
374  mouseInput.setX(x);
375  mouseInput.setY(y);
376  mouseInput.setReal(x, y);
377  mouseInput.setButton(MouseButton::EMPTY);
378  mouseInput.setType(MouseEventType::MOVED);
379  mouseInput.setTimeStamp(SDL_GetTicks());
380  mMouseInputQueue.push(mouseInput);
381 }
382 
383 void SDLInput::simulateKey(const int guiKey,
384  const InputActionT actionId)
385 {
386  KeyInput keyInput;
387  keyInput.setType(KeyEventType::PRESSED);
388 #ifdef USE_SDL2
389  char str[2];
390  str[0] = CAST_S8(guiKey);
391  str[1] = 0;
392 
393  keyInput.setKey(Key(KeyValue::TEXTINPUT));
394  keyInput.setText(str);
395  if (guiKey >= 32)
396  mKeyInputQueue.push(keyInput);
397 #endif // USE_SDL2
398 
399  keyInput.setKey(Key(guiKey));
400  if (actionId > InputAction::NO_VALUE)
401  keyInput.setActionId(actionId);
402  mKeyInputQueue.push(keyInput);
404  mKeyInputQueue.push(keyInput);
405 }
MouseInput dequeueMouseInput()
Definition: sdlinput.cpp:118
Gui * gui
Definition: gui.cpp:110
void pushInput(const SDL_Event &event)
Definition: sdlinput.cpp:131
void setTimeStamp(int timeStamp)
Definition: mouseinput.h:138
static int convertKeyCharacter(const SDL_Event &event)
Definition: sdlinput.h:156
void simulateKey(const int guiKey, const InputActionT actionId)
Definition: sdlinput.cpp:383
#define BLOCK_START(name)
Definition: perfomance.h:78
void simulateMouseMove()
Definition: sdlinput.cpp:361
#define BLOCK_END(name)
Definition: perfomance.h:79
void setType(KeyEventTypeT type)
Definition: keyinput.h:117
void setType(MouseEventTypeT type)
Definition: mouseinput.h:113
void simulateMouseClick(const int x, const int y, const MouseButtonT button)
Definition: sdlinput.cpp:341
volatile time_t cur_time
Definition: timer.cpp:57
bool mMouseInWindow
Definition: sdlinput.h:386
Logger * logger
Definition: logger.cpp:95
int getLastMouseY() const
Definition: gui.h:226
void setKey(const Key &key)
Definition: keyinput.h:127
void setX(int x)
Definition: mouseinput.h:143
void setY(int y)
Definition: mouseinput.h:153
void setButton(MouseButtonT button)
Definition: mouseinput.h:123
InputAction ::T InputActionT
Definition: inputaction.h:714
Graphics * mainGraphics
Definition: graphics.cpp:108
#define CAST_S8
Definition: cast.h:25
std::queue< MouseInput > mMouseInputQueue
Definition: sdlinput.h:382
#define PRAGMA48(str)
Definition: localconsts.h:214
static uint8_t getMouseState(int &x, int &y)
Definition: gui.cpp:1169
InputActionT getActionByKey(const SDL_Event &event) const
KeyInput dequeueKeyInput()
Definition: sdlinput.cpp:107
static MouseButtonT convertMouseButton(const int button)
Definition: sdlinput.cpp:318
int getScale() const
Definition: graphics.h:365
Definition: key.h:79
std::queue< KeyInput > mKeyInputQueue
Definition: sdlinput.h:381
int getLastMouseX() const
Definition: gui.h:223
InputManager inputManager
SDLInput()
Definition: sdlinput.cpp:98
void log(const char *const log_text,...)
Definition: logger.cpp:243
MouseButton ::T MouseButtonT
Definition: mousebutton.h:77
static void convertKeyEventToKey(const SDL_Event &event, KeyInput &keyInput)
Definition: sdlinput.cpp:310
SDLInput * guiInput
Definition: sdlinput.cpp:96
bool mMouseDown
Definition: sdlinput.h:385
void setActionId(const InputActionT n)
Definition: keyinput.h:137
void setReal(const int x, const int y)
Definition: mouseinput.h:163
time_t mMouseMoveTime
Definition: sdlinput.h:383