Input.cpp 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656
  1. //
  2. // Copyright (c) 2008-2014 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "Precompiled.h"
  23. #include "Context.h"
  24. #include "CoreEvents.h"
  25. #include "FileSystem.h"
  26. #include "Graphics.h"
  27. #include "GraphicsEvents.h"
  28. #include "GraphicsImpl.h"
  29. #include "Input.h"
  30. #include "Log.h"
  31. #include "Mutex.h"
  32. #include "ProcessUtils.h"
  33. #include "Profiler.h"
  34. #include "ResourceCache.h"
  35. #include "RWOpsWrapper.h"
  36. #include "StringUtils.h"
  37. #include "Text.h"
  38. #include "UI.h"
  39. #include <cstring>
  40. #include <SDL.h>
  41. #include "DebugNew.h"
  42. extern "C" int SDL_AddTouch(SDL_TouchID touchID, const char *name);
  43. // Require a click inside window before re-hiding mouse cursor on OSX, otherwise dragging the window
  44. // can be incorrectly interpreted as mouse movement inside the window
  45. #if defined(__APPLE__) && !defined(IOS)
  46. #define REQUIRE_CLICK_TO_FOCUS
  47. #endif
  48. namespace Urho3D
  49. {
  50. const int SCREEN_JOYSTICK_START_ID = 0x40000000;
  51. const ShortStringHash VAR_BUTTON_KEY_BINDING("VAR_BUTTON_KEY_BINDING");
  52. const ShortStringHash VAR_BUTTON_MOUSE_BUTTON_BINDING("VAR_BUTTON_MOUSE_BUTTON_BINDING");
  53. const ShortStringHash VAR_LAST_KEYSYM("VAR_LAST_KEYSYM");
  54. const ShortStringHash VAR_SCREEN_JOYSTICK_ID("VAR_SCREEN_JOYSTICK_ID");
  55. /// Convert SDL keycode if necessary.
  56. int ConvertSDLKeyCode(int keySym, int scanCode)
  57. {
  58. if (scanCode == SCANCODE_AC_BACK)
  59. return KEY_ESC;
  60. else
  61. return SDL_toupper(keySym);
  62. }
  63. Input::Input(Context* context) :
  64. Object(context),
  65. mouseButtonDown_(0),
  66. mouseButtonPress_(0),
  67. mouseMoveWheel_(0),
  68. windowID_(0),
  69. toggleFullscreen_(true),
  70. mouseVisible_(false),
  71. mouseGrabbed_(false),
  72. touchEmulation_(false),
  73. inputFocus_(false),
  74. minimized_(false),
  75. focusedThisFrame_(false),
  76. suppressNextMouseMove_(false),
  77. initialized_(false)
  78. {
  79. SubscribeToEvent(E_SCREENMODE, HANDLER(Input, HandleScreenMode));
  80. // Try to initialize right now, but skip if screen mode is not yet set
  81. Initialize();
  82. }
  83. Input::~Input()
  84. {
  85. }
  86. void Input::Update()
  87. {
  88. assert(initialized_);
  89. PROFILE(UpdateInput);
  90. // Reset input accumulation for this frame
  91. keyPress_.Clear();
  92. scancodePress_.Clear();
  93. mouseButtonPress_ = 0;
  94. mouseMove_ = IntVector2::ZERO;
  95. mouseMoveWheel_ = 0;
  96. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  97. {
  98. for (unsigned j = 0; j < i->second_.buttonPress_.Size(); ++j)
  99. i->second_.buttonPress_[j] = false;
  100. }
  101. // Reset touch delta movement
  102. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  103. {
  104. TouchState& state = i->second_;
  105. state.lastPosition_ = state.position_;
  106. state.delta_ = IntVector2::ZERO;
  107. }
  108. // Check and handle SDL events
  109. SDL_PumpEvents();
  110. SDL_Event evt;
  111. while (SDL_PeepEvents(&evt, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT) > 0)
  112. HandleSDLEvent(&evt);
  113. // Check for activation and inactivation from SDL window flags. Must nullcheck the window pointer because it may have
  114. // been closed due to input events
  115. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  116. unsigned flags = window ? SDL_GetWindowFlags(window) & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS) : 0;
  117. if (window)
  118. {
  119. #ifdef REQUIRE_CLICK_TO_FOCUS
  120. if (!inputFocus_ && (graphics_->GetFullscreen() || mouseVisible_) && flags == (SDL_WINDOW_INPUT_FOCUS |
  121. SDL_WINDOW_MOUSE_FOCUS))
  122. #else
  123. if (!inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS))
  124. #endif
  125. focusedThisFrame_ = true;
  126. if (focusedThisFrame_)
  127. GainFocus();
  128. if (inputFocus_ && (flags & SDL_WINDOW_INPUT_FOCUS) == 0)
  129. LoseFocus();
  130. }
  131. else
  132. return;
  133. // Check for relative mode mouse move
  134. if (!touchEmulation_ && (graphics_->GetExternalWindow() || (!mouseVisible_ && inputFocus_ && (flags & SDL_WINDOW_MOUSE_FOCUS))))
  135. {
  136. IntVector2 mousePosition = GetMousePosition();
  137. mouseMove_ = mousePosition - lastMousePosition_;
  138. if (graphics_->GetExternalWindow())
  139. lastMousePosition_ = mousePosition;
  140. else
  141. {
  142. // Recenter the mouse cursor manually after move
  143. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  144. if (mousePosition != center)
  145. {
  146. SetMousePosition(center);
  147. lastMousePosition_ = center;
  148. }
  149. }
  150. // Send mouse move event if necessary
  151. if (mouseMove_ != IntVector2::ZERO)
  152. {
  153. if (suppressNextMouseMove_)
  154. {
  155. mouseMove_ = IntVector2::ZERO;
  156. suppressNextMouseMove_ = false;
  157. }
  158. else
  159. {
  160. using namespace MouseMove;
  161. VariantMap& eventData = GetEventDataMap();
  162. if (mouseVisible_)
  163. {
  164. eventData[P_X] = mousePosition.x_;
  165. eventData[P_Y] = mousePosition.y_;
  166. }
  167. eventData[P_DX] = mouseMove_.x_;
  168. eventData[P_DY] = mouseMove_.y_;
  169. eventData[P_BUTTONS] = mouseButtonDown_;
  170. eventData[P_QUALIFIERS] = GetQualifiers();
  171. SendEvent(E_MOUSEMOVE, eventData);
  172. }
  173. }
  174. }
  175. }
  176. void Input::SetMouseVisible(bool enable)
  177. {
  178. // In touch emulation mode only enabled mouse is allowed
  179. if (touchEmulation_)
  180. enable = true;
  181. // SDL Raspberry Pi "video driver" does not have proper OS mouse support yet, so no-op for now
  182. #ifndef RASPI
  183. if (enable != mouseVisible_)
  184. {
  185. mouseVisible_ = enable;
  186. if (initialized_)
  187. {
  188. // External windows can only support visible mouse cursor
  189. if (graphics_->GetExternalWindow())
  190. {
  191. mouseVisible_ = true;
  192. return;
  193. }
  194. if (!mouseVisible_ && inputFocus_)
  195. {
  196. SDL_ShowCursor(SDL_FALSE);
  197. // Recenter the mouse cursor manually when hiding it to avoid erratic mouse move for one frame
  198. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  199. SetMousePosition(center);
  200. lastMousePosition_ = center;
  201. }
  202. else
  203. SDL_ShowCursor(SDL_TRUE);
  204. }
  205. using namespace MouseVisibleChanged;
  206. VariantMap& eventData = GetEventDataMap();
  207. eventData[P_VISIBLE] = mouseVisible_;
  208. SendEvent(E_MOUSEVISIBLECHANGED, eventData);
  209. }
  210. #endif
  211. }
  212. void Input::SetMouseGrabbed(bool grab)
  213. {
  214. mouseGrabbed_ = grab;
  215. }
  216. void Input::SetToggleFullscreen(bool enable)
  217. {
  218. toggleFullscreen_ = enable;
  219. }
  220. static void PopulateKeyBindingMap(HashMap<String, int>& keyBindingMap)
  221. {
  222. if (keyBindingMap.Empty())
  223. {
  224. keyBindingMap.Insert(MakePair<String, int>("SPACE", KEY_SPACE));
  225. keyBindingMap.Insert(MakePair<String, int>("LCTRL", KEY_LCTRL));
  226. keyBindingMap.Insert(MakePair<String, int>("RCTRL", KEY_RCTRL));
  227. keyBindingMap.Insert(MakePair<String, int>("LSHIFT", KEY_LSHIFT));
  228. keyBindingMap.Insert(MakePair<String, int>("RSHIFT", KEY_RSHIFT));
  229. keyBindingMap.Insert(MakePair<String, int>("LALT", KEY_LALT));
  230. keyBindingMap.Insert(MakePair<String, int>("RALT", KEY_RALT));
  231. keyBindingMap.Insert(MakePair<String, int>("LGUI", KEY_LGUI));
  232. keyBindingMap.Insert(MakePair<String, int>("RGUI", KEY_RGUI));
  233. keyBindingMap.Insert(MakePair<String, int>("TAB", KEY_TAB));
  234. keyBindingMap.Insert(MakePair<String, int>("RETURN", KEY_RETURN));
  235. keyBindingMap.Insert(MakePair<String, int>("RETURN2", KEY_RETURN2));
  236. keyBindingMap.Insert(MakePair<String, int>("ENTER", KEY_KP_ENTER));
  237. keyBindingMap.Insert(MakePair<String, int>("SELECT", KEY_SELECT));
  238. keyBindingMap.Insert(MakePair<String, int>("LEFT", KEY_LEFT));
  239. keyBindingMap.Insert(MakePair<String, int>("RIGHT", KEY_RIGHT));
  240. keyBindingMap.Insert(MakePair<String, int>("UP", KEY_UP));
  241. keyBindingMap.Insert(MakePair<String, int>("DOWN", KEY_DOWN));
  242. keyBindingMap.Insert(MakePair<String, int>("PAGEUP", KEY_PAGEUP));
  243. keyBindingMap.Insert(MakePair<String, int>("PAGEDOWN", KEY_PAGEDOWN));
  244. keyBindingMap.Insert(MakePair<String, int>("F1", KEY_F1));
  245. keyBindingMap.Insert(MakePair<String, int>("F2", KEY_F2));
  246. keyBindingMap.Insert(MakePair<String, int>("F3", KEY_F3));
  247. keyBindingMap.Insert(MakePair<String, int>("F4", KEY_F4));
  248. keyBindingMap.Insert(MakePair<String, int>("F5", KEY_F5));
  249. keyBindingMap.Insert(MakePair<String, int>("F6", KEY_F6));
  250. keyBindingMap.Insert(MakePair<String, int>("F7", KEY_F7));
  251. keyBindingMap.Insert(MakePair<String, int>("F8", KEY_F8));
  252. keyBindingMap.Insert(MakePair<String, int>("F9", KEY_F9));
  253. keyBindingMap.Insert(MakePair<String, int>("F10", KEY_F10));
  254. keyBindingMap.Insert(MakePair<String, int>("F11", KEY_F11));
  255. keyBindingMap.Insert(MakePair<String, int>("F12", KEY_F12));
  256. }
  257. }
  258. static void PopulateMouseButtonBindingMap(HashMap<String, int>& mouseButtonBindingMap)
  259. {
  260. if (mouseButtonBindingMap.Empty())
  261. {
  262. mouseButtonBindingMap.Insert(MakePair<String, int>("LEFT", SDL_BUTTON_LEFT));
  263. mouseButtonBindingMap.Insert(MakePair<String, int>("MIDDLE", SDL_BUTTON_MIDDLE));
  264. mouseButtonBindingMap.Insert(MakePair<String, int>("RIGHT", SDL_BUTTON_RIGHT));
  265. mouseButtonBindingMap.Insert(MakePair<String, int>("X1", SDL_BUTTON_X1));
  266. mouseButtonBindingMap.Insert(MakePair<String, int>("X2", SDL_BUTTON_X2));
  267. }
  268. }
  269. SDL_JoystickID Input::AddScreenJoystick(XMLFile* layoutFile, XMLFile* styleFile)
  270. {
  271. static HashMap<String, int> keyBindingMap;
  272. static HashMap<String, int> mouseButtonBindingMap;
  273. if (!graphics_)
  274. {
  275. LOGWARNING("Cannot add screen joystick in headless mode");
  276. return -1;
  277. }
  278. // If layout file is not given, use the default screen joystick layout
  279. if (!layoutFile)
  280. {
  281. ResourceCache* cache = GetSubsystem<ResourceCache>();
  282. layoutFile = cache->GetResource<XMLFile>("UI/ScreenJoystick.xml");
  283. if (!layoutFile) // Error is already logged
  284. return -1;
  285. }
  286. UI* ui = GetSubsystem<UI>();
  287. SharedPtr<UIElement> screenJoystick = ui->LoadLayout(layoutFile, styleFile);
  288. if (!screenJoystick) // Error is already logged
  289. return -1;
  290. screenJoystick->SetSize(ui->GetRoot()->GetSize());
  291. ui->GetRoot()->AddChild(screenJoystick);
  292. // Get an unused ID for the screen joystick
  293. /// \todo After a real joystick has been plugged in 1073741824 times, the ranges will overlap
  294. SDL_JoystickID joystickID = SCREEN_JOYSTICK_START_ID;
  295. while (joysticks_.Contains(joystickID))
  296. ++joystickID;
  297. JoystickState& state = joysticks_[joystickID];
  298. state.joystickID_ = joystickID;
  299. state.name_ = screenJoystick->GetName();
  300. state.screenJoystick_ = screenJoystick;
  301. unsigned numButtons = 0;
  302. unsigned numAxes = 0;
  303. unsigned numHats = 0;
  304. const Vector<SharedPtr<UIElement> >& children = state.screenJoystick_->GetChildren();
  305. for (Vector<SharedPtr<UIElement> >::ConstIterator iter = children.Begin(); iter != children.End(); ++iter)
  306. {
  307. UIElement* element = iter->Get();
  308. String name = element->GetName();
  309. if (name.StartsWith("Button"))
  310. {
  311. ++numButtons;
  312. // Check whether the button has key binding
  313. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  314. if (text)
  315. {
  316. text->SetVisible(false);
  317. const String& key = text->GetText();
  318. int keyBinding;
  319. if (key.Length() == 1)
  320. keyBinding = key[0];
  321. else
  322. {
  323. PopulateKeyBindingMap(keyBindingMap);
  324. HashMap<String, int>::Iterator i = keyBindingMap.Find(key);
  325. if (i != keyBindingMap.End())
  326. keyBinding = i->second_;
  327. else
  328. {
  329. LOGERRORF("Unsupported key binding: %s", key.CString());
  330. keyBinding = M_MAX_INT;
  331. }
  332. }
  333. if (keyBinding != M_MAX_INT)
  334. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  335. }
  336. // Check whether the button has mouse button binding
  337. text = dynamic_cast<Text*>(element->GetChild("MouseButtonBinding", false));
  338. if (text)
  339. {
  340. text->SetVisible(false);
  341. const String& mouseButton = text->GetText();
  342. PopulateMouseButtonBindingMap(mouseButtonBindingMap);
  343. HashMap<String, int>::Iterator i = mouseButtonBindingMap.Find(mouseButton);
  344. if (i != mouseButtonBindingMap.End())
  345. element->SetVar(VAR_BUTTON_MOUSE_BUTTON_BINDING, i->second_);
  346. else
  347. LOGERRORF("Unsupported mouse button binding: %s", mouseButton.CString());
  348. }
  349. }
  350. else if (name.StartsWith("Axis"))
  351. {
  352. ++numAxes;
  353. ///\todo Axis emulation for screen joystick is not fully supported yet.
  354. LOGWARNING("Axis emulation for screen joystick is not fully supported yet");
  355. }
  356. else if (name.StartsWith("Hat"))
  357. {
  358. ++numHats;
  359. Text* text = dynamic_cast<Text*>(element->GetChild("KeyBinding", false));
  360. if (text)
  361. {
  362. text->SetVisible(false);
  363. String keyBinding = text->GetText();
  364. if (keyBinding.Contains(' ')) // e.g.: "UP DOWN LEFT RIGHT"
  365. {
  366. // Attempt to split the text using ' ' as separator
  367. Vector<String>keyBindings(keyBinding.Split(' '));
  368. String mappedKeyBinding;
  369. if (keyBindings.Size() == 4)
  370. {
  371. PopulateKeyBindingMap(keyBindingMap);
  372. for (unsigned j = 0; j < 4; ++j)
  373. {
  374. if (keyBindings[j].Length() == 1)
  375. mappedKeyBinding.Append(keyBindings[j][0]);
  376. else
  377. {
  378. HashMap<String, int>::Iterator i = keyBindingMap.Find(keyBindings[j]);
  379. if (i != keyBindingMap.End())
  380. mappedKeyBinding.Append(i->second_);
  381. else
  382. break;
  383. }
  384. }
  385. }
  386. if (mappedKeyBinding.Length() != 4)
  387. {
  388. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  389. keyBinding = "WSAD";
  390. }
  391. else
  392. keyBinding = mappedKeyBinding;
  393. }
  394. else if (keyBinding.Length() != 4)
  395. {
  396. LOGERRORF("%s has invalid key binding %s, fallback to WSAD", name.CString(), keyBinding.CString());
  397. keyBinding = "WSAD";
  398. }
  399. element->SetVar(VAR_BUTTON_KEY_BINDING, keyBinding);
  400. }
  401. }
  402. element->SetVar(VAR_SCREEN_JOYSTICK_ID, joystickID);
  403. }
  404. // Make sure all the children are non-focusable so they do not mistakenly to be considered as active UI input controls by application
  405. PODVector<UIElement*> allChildren;
  406. state.screenJoystick_->GetChildren(allChildren, true);
  407. for (PODVector<UIElement*>::Iterator iter = allChildren.Begin(); iter != allChildren.End(); ++iter)
  408. (*iter)->SetFocusMode(FM_NOTFOCUSABLE);
  409. state.buttons_.Resize(numButtons);
  410. state.buttonPress_.Resize(numButtons);
  411. state.axes_.Resize(numAxes);
  412. state.hats_.Resize(numHats);
  413. // There could be potentially more than one screen joystick, however they all will be handled by a same handler method
  414. // So there is no harm to replace the old handler with the new handler in each call to SubscribeToEvent()
  415. SubscribeToEvent(E_TOUCHBEGIN, HANDLER(Input, HandleScreenJoystickTouch));
  416. SubscribeToEvent(E_TOUCHMOVE, HANDLER(Input, HandleScreenJoystickTouch));
  417. SubscribeToEvent(E_TOUCHEND, HANDLER(Input, HandleScreenJoystickTouch));
  418. return joystickID;
  419. }
  420. bool Input::RemoveScreenJoystick(SDL_JoystickID id)
  421. {
  422. if (!joysticks_.Contains(id))
  423. {
  424. LOGERRORF("Failed to remove non-existing screen joystick ID #%d", id);
  425. return false;
  426. }
  427. JoystickState& state = joysticks_[id];
  428. if (!state.screenJoystick_)
  429. {
  430. LOGERRORF("Failed to remove joystick with ID #%d which is not a screen joystick", id);
  431. return false;
  432. }
  433. state.screenJoystick_->Remove();
  434. joysticks_.Erase(id);
  435. return true;
  436. }
  437. void Input::SetScreenJoystickVisible(SDL_JoystickID id, bool enable)
  438. {
  439. if (joysticks_.Contains(id))
  440. {
  441. JoystickState& state = joysticks_[id];
  442. if (state.screenJoystick_)
  443. state.screenJoystick_->SetVisible(enable);
  444. }
  445. }
  446. void Input::SetScreenKeyboardVisible(bool enable)
  447. {
  448. if (!graphics_)
  449. return;
  450. if (enable != IsScreenKeyboardVisible())
  451. {
  452. if (enable)
  453. SDL_StartTextInput();
  454. else
  455. SDL_StopTextInput();
  456. }
  457. }
  458. void Input::SetTouchEmulation(bool enable)
  459. {
  460. #if !defined(ANDROID) && !defined(IOS)
  461. if (enable != touchEmulation_)
  462. {
  463. // Touch emulation needs the mouse visible
  464. if (enable)
  465. {
  466. if (!mouseVisible_)
  467. SetMouseVisible(true);
  468. // Add a virtual touch device the first time we are enabling emulated touch
  469. if (enable && !SDL_GetNumTouchDevices())
  470. SDL_AddTouch(0, "Emulated Touch");
  471. }
  472. else
  473. ClearTouches();
  474. touchEmulation_ = enable;
  475. }
  476. #endif
  477. }
  478. bool Input::RecordGesture()
  479. {
  480. // If have no touch devices, fail
  481. if (!SDL_GetNumTouchDevices())
  482. {
  483. LOGERROR("Can not record gesture: no touch devices");
  484. return false;
  485. }
  486. return SDL_RecordGesture(-1);
  487. }
  488. bool Input::SaveGestures(Serializer& dest)
  489. {
  490. RWOpsWrapper<Serializer> wrapper(dest);
  491. return SDL_SaveAllDollarTemplates(wrapper.GetRWOps());
  492. }
  493. bool Input::SaveGesture(Serializer& dest, unsigned gestureID)
  494. {
  495. RWOpsWrapper<Serializer> wrapper(dest);
  496. return SDL_SaveDollarTemplate(gestureID, wrapper.GetRWOps());
  497. }
  498. unsigned Input::LoadGestures(Deserializer& source)
  499. {
  500. // If have no touch devices, fail
  501. if (!SDL_GetNumTouchDevices())
  502. {
  503. LOGERROR("Can not load gestures: no touch devices");
  504. return 0;
  505. }
  506. RWOpsWrapper<Deserializer> wrapper(source);
  507. return SDL_LoadDollarTemplates(-1, wrapper.GetRWOps());
  508. }
  509. SDL_JoystickID Input::OpenJoystick(unsigned index)
  510. {
  511. SDL_Joystick* joystick = SDL_JoystickOpen(index);
  512. if (!joystick)
  513. {
  514. LOGERRORF("Cannot open joystick #%d", index);
  515. return -1;
  516. }
  517. // Create joystick state for the new joystick
  518. int joystickID = SDL_JoystickInstanceID(joystick);
  519. JoystickState& state = joysticks_[joystickID];
  520. state.joystick_ = joystick;
  521. state.joystickID_ = joystickID;
  522. state.name_ = SDL_JoystickName(joystick);
  523. if (SDL_IsGameController(index))
  524. state.controller_ = SDL_GameControllerOpen(index);
  525. state.buttons_.Resize(SDL_JoystickNumButtons(joystick));
  526. state.axes_.Resize(SDL_JoystickNumAxes(joystick));
  527. // When the joystick is a controller, make sure there's enough axes & buttons for the standard controller mappings
  528. if (state.controller_)
  529. {
  530. if (state.buttons_.Size() < SDL_CONTROLLER_BUTTON_MAX)
  531. state.buttons_.Resize(SDL_CONTROLLER_BUTTON_MAX);
  532. if (state.axes_.Size() < SDL_CONTROLLER_AXIS_MAX)
  533. state.axes_.Resize(SDL_CONTROLLER_AXIS_MAX);
  534. }
  535. state.buttonPress_.Resize(state.buttons_.Size());
  536. state.hats_.Resize(SDL_JoystickNumHats(joystick));
  537. for (unsigned i = 0; i < state.buttons_.Size(); ++i)
  538. {
  539. state.buttons_[i] = false;
  540. state.buttonPress_[i] = false;
  541. }
  542. for (unsigned i = 0; i < state.axes_.Size(); ++i)
  543. state.axes_[i] = 0.0f;
  544. for (unsigned i = 0; i < state.hats_.Size(); ++i)
  545. state.hats_[i] = HAT_CENTER;
  546. return joystickID;
  547. }
  548. int Input::GetKeyFromName(const String& name) const
  549. {
  550. return SDL_GetKeyFromName(name.CString());
  551. }
  552. int Input::GetKeyFromScancode(int scancode) const
  553. {
  554. return SDL_GetKeyFromScancode((SDL_Scancode)scancode);
  555. }
  556. String Input::GetKeyName(int key) const
  557. {
  558. return String(SDL_GetKeyName(key));
  559. }
  560. int Input::GetScancodeFromKey(int key) const
  561. {
  562. return SDL_GetScancodeFromKey(key);
  563. }
  564. int Input::GetScancodeFromName(const String& name) const
  565. {
  566. return SDL_GetScancodeFromName(name.CString());
  567. }
  568. String Input::GetScancodeName(int scancode) const
  569. {
  570. return SDL_GetScancodeName((SDL_Scancode)scancode);
  571. }
  572. bool Input::GetKeyDown(int key) const
  573. {
  574. return keyDown_.Contains(SDL_toupper(key));
  575. }
  576. bool Input::GetKeyPress(int key) const
  577. {
  578. return keyPress_.Contains(SDL_toupper(key));
  579. }
  580. bool Input::GetScancodeDown(int scancode) const
  581. {
  582. return scancodeDown_.Contains(scancode);
  583. }
  584. bool Input::GetScancodePress(int scancode) const
  585. {
  586. return scancodePress_.Contains(scancode);
  587. }
  588. bool Input::GetMouseButtonDown(int button) const
  589. {
  590. return (mouseButtonDown_ & button) != 0;
  591. }
  592. bool Input::GetMouseButtonPress(int button) const
  593. {
  594. return (mouseButtonPress_ & button) != 0;
  595. }
  596. bool Input::GetQualifierDown(int qualifier) const
  597. {
  598. if (qualifier == QUAL_SHIFT)
  599. return GetKeyDown(KEY_LSHIFT) || GetKeyDown(KEY_RSHIFT);
  600. if (qualifier == QUAL_CTRL)
  601. return GetKeyDown(KEY_LCTRL) || GetKeyDown(KEY_RCTRL);
  602. if (qualifier == QUAL_ALT)
  603. return GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT);
  604. return false;
  605. }
  606. bool Input::GetQualifierPress(int qualifier) const
  607. {
  608. if (qualifier == QUAL_SHIFT)
  609. return GetKeyPress(KEY_LSHIFT) || GetKeyPress(KEY_RSHIFT);
  610. if (qualifier == QUAL_CTRL)
  611. return GetKeyPress(KEY_LCTRL) || GetKeyPress(KEY_RCTRL);
  612. if (qualifier == QUAL_ALT)
  613. return GetKeyPress(KEY_LALT) || GetKeyPress(KEY_RALT);
  614. return false;
  615. }
  616. int Input::GetQualifiers() const
  617. {
  618. int ret = 0;
  619. if (GetQualifierDown(QUAL_SHIFT))
  620. ret |= QUAL_SHIFT;
  621. if (GetQualifierDown(QUAL_CTRL))
  622. ret |= QUAL_CTRL;
  623. if (GetQualifierDown(QUAL_ALT))
  624. ret |= QUAL_ALT;
  625. return ret;
  626. }
  627. IntVector2 Input::GetMousePosition() const
  628. {
  629. IntVector2 ret = IntVector2::ZERO;
  630. if (!initialized_)
  631. return ret;
  632. SDL_GetMouseState(&ret.x_, &ret.y_);
  633. return ret;
  634. }
  635. TouchState* Input::GetTouch(unsigned index) const
  636. {
  637. if (index >= touches_.Size())
  638. return 0;
  639. HashMap<int, TouchState>::ConstIterator i = touches_.Begin();
  640. while (index--)
  641. ++i;
  642. return const_cast<TouchState*>(&i->second_);
  643. }
  644. JoystickState* Input::GetJoystickByIndex(unsigned index)
  645. {
  646. unsigned compare = 0;
  647. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  648. {
  649. if (compare++ == index)
  650. return &(i->second_);
  651. }
  652. return 0;
  653. }
  654. JoystickState* Input::GetJoystick(SDL_JoystickID id)
  655. {
  656. HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Find(id);
  657. return i != joysticks_.End() ? &(i->second_) : 0;
  658. }
  659. bool Input::IsScreenJoystickVisible(SDL_JoystickID id) const
  660. {
  661. HashMap<SDL_JoystickID, JoystickState>::ConstIterator i = joysticks_.Find(id);
  662. return i != joysticks_.End() && i->second_.screenJoystick_ && i->second_.screenJoystick_->IsVisible();
  663. }
  664. bool Input::GetScreenKeyboardSupport() const
  665. {
  666. return graphics_ ? SDL_HasScreenKeyboardSupport() : false;
  667. }
  668. bool Input::IsScreenKeyboardVisible() const
  669. {
  670. if (graphics_)
  671. {
  672. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  673. return SDL_IsScreenKeyboardShown(window);
  674. }
  675. else
  676. return false;
  677. }
  678. bool Input::IsMinimized() const
  679. {
  680. // Return minimized state also when unfocused in fullscreen
  681. if (!inputFocus_ && graphics_ && graphics_->GetFullscreen())
  682. return true;
  683. else
  684. return minimized_;
  685. }
  686. void Input::Initialize()
  687. {
  688. Graphics* graphics = GetSubsystem<Graphics>();
  689. if (!graphics || !graphics->IsInitialized())
  690. return;
  691. graphics_ = graphics;
  692. // In external window mode only visible mouse is supported
  693. if (graphics_->GetExternalWindow())
  694. mouseVisible_ = true;
  695. // Set the initial activation
  696. focusedThisFrame_ = true;
  697. initialized_ = true;
  698. ResetJoysticks();
  699. ResetState();
  700. SubscribeToEvent(E_BEGINFRAME, HANDLER(Input, HandleBeginFrame));
  701. LOGINFO("Initialized input");
  702. }
  703. void Input::ResetJoysticks()
  704. {
  705. joysticks_.Clear();
  706. // Open each detected joystick automatically on startup
  707. int size = SDL_NumJoysticks();
  708. for (int i = 0; i < size; ++i)
  709. OpenJoystick(i);
  710. }
  711. void Input::GainFocus()
  712. {
  713. ResetState();
  714. inputFocus_ = true;
  715. focusedThisFrame_ = false;
  716. // Re-establish mouse cursor hiding as necessary
  717. if (!mouseVisible_)
  718. {
  719. SDL_ShowCursor(SDL_FALSE);
  720. suppressNextMouseMove_ = true;
  721. }
  722. else
  723. lastMousePosition_ = GetMousePosition();
  724. SendInputFocusEvent();
  725. }
  726. void Input::LoseFocus()
  727. {
  728. ResetState();
  729. inputFocus_ = false;
  730. focusedThisFrame_ = false;
  731. // Show the mouse cursor when inactive
  732. SDL_ShowCursor(SDL_TRUE);
  733. SendInputFocusEvent();
  734. }
  735. void Input::ResetState()
  736. {
  737. keyDown_.Clear();
  738. keyPress_.Clear();
  739. scancodeDown_.Clear();
  740. scancodePress_.Clear();
  741. /// \todo Check if this is necessary
  742. for (HashMap<SDL_JoystickID, JoystickState>::Iterator i = joysticks_.Begin(); i != joysticks_.End(); ++i)
  743. {
  744. for (unsigned j = 0; j < i->second_.axes_.Size(); ++j)
  745. i->second_.axes_[j] = 0.0f;
  746. for (unsigned j = 0; j < i->second_.buttons_.Size(); ++j)
  747. i->second_.buttons_[j] = false;
  748. for (unsigned j = 0; j < i->second_.hats_.Size(); ++j)
  749. i->second_.hats_[j] = HAT_CENTER;
  750. }
  751. ClearTouches();
  752. // Use SetMouseButton() to reset the state so that mouse events will be sent properly
  753. SetMouseButton(MOUSEB_LEFT, false);
  754. SetMouseButton(MOUSEB_RIGHT, false);
  755. SetMouseButton(MOUSEB_MIDDLE, false);
  756. mouseMove_ = IntVector2::ZERO;
  757. mouseMoveWheel_ = 0;
  758. mouseButtonPress_ = 0;
  759. }
  760. void Input::ClearTouches()
  761. {
  762. for (HashMap<int, TouchState>::Iterator i = touches_.Begin(); i != touches_.End(); ++i)
  763. {
  764. TouchState& state = i->second_;
  765. using namespace TouchEnd;
  766. VariantMap& eventData = GetEventDataMap();
  767. eventData[P_TOUCHID] = state.touchID_;
  768. eventData[P_X] = state.position_.x_;
  769. eventData[P_Y] = state.position_.y_;
  770. SendEvent(E_TOUCHEND, eventData);
  771. }
  772. touches_.Clear();
  773. }
  774. void Input::SendInputFocusEvent()
  775. {
  776. using namespace InputFocus;
  777. VariantMap& eventData = GetEventDataMap();
  778. eventData[P_FOCUS] = HasFocus();
  779. eventData[P_MINIMIZED] = IsMinimized();
  780. SendEvent(E_INPUTFOCUS, eventData);
  781. }
  782. void Input::SetMouseButton(int button, bool newState)
  783. {
  784. #ifdef REQUIRE_CLICK_TO_FOCUS
  785. if (!mouseVisible_ && !graphics_->GetFullscreen())
  786. {
  787. if (!inputFocus_ && newState && button == MOUSEB_LEFT)
  788. focusedThisFrame_ = true;
  789. }
  790. #endif
  791. // If we do not have focus yet, do not react to the mouse button down
  792. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  793. return;
  794. if (newState)
  795. {
  796. if (!(mouseButtonDown_ & button))
  797. mouseButtonPress_ |= button;
  798. mouseButtonDown_ |= button;
  799. }
  800. else
  801. {
  802. if (!(mouseButtonDown_ & button))
  803. return;
  804. mouseButtonDown_ &= ~button;
  805. }
  806. using namespace MouseButtonDown;
  807. VariantMap& eventData = GetEventDataMap();
  808. eventData[P_BUTTON] = button;
  809. eventData[P_BUTTONS] = mouseButtonDown_;
  810. eventData[P_QUALIFIERS] = GetQualifiers();
  811. SendEvent(newState ? E_MOUSEBUTTONDOWN : E_MOUSEBUTTONUP, eventData);
  812. }
  813. void Input::SetKey(int key, int scancode, unsigned raw, bool newState)
  814. {
  815. // If we do not have focus yet, do not react to the key down
  816. if (!graphics_->GetExternalWindow() && newState && !inputFocus_)
  817. return;
  818. bool repeat = false;
  819. if (newState)
  820. {
  821. scancodeDown_.Insert(scancode);
  822. scancodePress_.Insert(scancode);
  823. if (!keyDown_.Contains(key))
  824. {
  825. keyDown_.Insert(key);
  826. keyPress_.Insert(key);
  827. }
  828. else
  829. repeat = true;
  830. }
  831. else
  832. {
  833. scancodeDown_.Erase(scancode);
  834. if (!keyDown_.Erase(key))
  835. return;
  836. }
  837. using namespace KeyDown;
  838. VariantMap& eventData = GetEventDataMap();
  839. eventData[P_KEY] = key;
  840. eventData[P_SCANCODE] = scancode;
  841. eventData[P_RAW] = raw;
  842. eventData[P_BUTTONS] = mouseButtonDown_;
  843. eventData[P_QUALIFIERS] = GetQualifiers();
  844. if (newState)
  845. eventData[P_REPEAT] = repeat;
  846. SendEvent(newState ? E_KEYDOWN : E_KEYUP, eventData);
  847. if ((key == KEY_RETURN || key == KEY_RETURN2 || key == KEY_KP_ENTER) && newState && !repeat && toggleFullscreen_ &&
  848. (GetKeyDown(KEY_LALT) || GetKeyDown(KEY_RALT)))
  849. graphics_->ToggleFullscreen();
  850. }
  851. void Input::SetMouseWheel(int delta)
  852. {
  853. // If we do not have focus yet, do not react to the wheel
  854. if (!graphics_->GetExternalWindow() && !inputFocus_)
  855. return;
  856. if (delta)
  857. {
  858. mouseMoveWheel_ += delta;
  859. using namespace MouseWheel;
  860. VariantMap& eventData = GetEventDataMap();
  861. eventData[P_WHEEL] = delta;
  862. eventData[P_BUTTONS] = mouseButtonDown_;
  863. eventData[P_QUALIFIERS] = GetQualifiers();
  864. SendEvent(E_MOUSEWHEEL, eventData);
  865. }
  866. }
  867. void Input::SetMousePosition(const IntVector2& position)
  868. {
  869. if (!graphics_)
  870. return;
  871. SDL_WarpMouseInWindow(graphics_->GetImpl()->GetWindow(), position.x_, position.y_);
  872. }
  873. void Input::HandleSDLEvent(void* sdlEvent)
  874. {
  875. SDL_Event& evt = *static_cast<SDL_Event*>(sdlEvent);
  876. switch (evt.type)
  877. {
  878. case SDL_KEYDOWN:
  879. // Convert to uppercase to match Win32 virtual key codes
  880. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, true);
  881. break;
  882. case SDL_KEYUP:
  883. SetKey(ConvertSDLKeyCode(evt.key.keysym.sym, evt.key.keysym.scancode), evt.key.keysym.scancode, evt.key.keysym.raw, false);
  884. break;
  885. case SDL_TEXTINPUT:
  886. {
  887. textInput_ = &evt.text.text[0];
  888. unsigned unicode = textInput_.AtUTF8(0);
  889. if (unicode)
  890. {
  891. using namespace TextInput;
  892. VariantMap textInputEventData;
  893. textInputEventData[P_TEXT] = textInput_;
  894. textInputEventData[P_BUTTONS] = mouseButtonDown_;
  895. textInputEventData[P_QUALIFIERS] = GetQualifiers();
  896. SendEvent(E_TEXTINPUT, textInputEventData);
  897. }
  898. }
  899. break;
  900. case SDL_MOUSEBUTTONDOWN:
  901. if (!touchEmulation_)
  902. SetMouseButton(1 << (evt.button.button - 1), true);
  903. else if (touchEmulation_ && evt.button.button == 1)
  904. {
  905. int x, y;
  906. SDL_GetMouseState(&x, &y);
  907. SDL_Event event;
  908. event.type = SDL_FINGERDOWN;
  909. event.tfinger.touchId = 0;
  910. event.tfinger.fingerId = 0;
  911. event.tfinger.pressure = 1.0f;
  912. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  913. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  914. event.tfinger.dx = 0;
  915. event.tfinger.dy = 0;
  916. SDL_PushEvent(&event);
  917. }
  918. break;
  919. case SDL_MOUSEBUTTONUP:
  920. if (!touchEmulation_)
  921. SetMouseButton(1 << (evt.button.button - 1), false);
  922. else if (touchEmulation_ && evt.button.button == 1)
  923. {
  924. int x, y;
  925. SDL_GetMouseState(&x, &y);
  926. SDL_Event event;
  927. event.type = SDL_FINGERUP;
  928. event.tfinger.touchId = 0;
  929. event.tfinger.fingerId = 0;
  930. event.tfinger.pressure = 0.0f;
  931. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  932. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  933. event.tfinger.dx = 0;
  934. event.tfinger.dy = 0;
  935. SDL_PushEvent(&event);
  936. }
  937. break;
  938. case SDL_MOUSEMOTION:
  939. if (mouseVisible_ && !touchEmulation_)
  940. {
  941. mouseMove_.x_ += evt.motion.xrel;
  942. mouseMove_.y_ += evt.motion.yrel;
  943. using namespace MouseMove;
  944. VariantMap& eventData = GetEventDataMap();
  945. if (mouseVisible_)
  946. {
  947. eventData[P_X] = evt.motion.x;
  948. eventData[P_Y] = evt.motion.y;
  949. }
  950. eventData[P_DX] = evt.motion.xrel;
  951. eventData[P_DY] = evt.motion.yrel;
  952. eventData[P_BUTTONS] = mouseButtonDown_;
  953. eventData[P_QUALIFIERS] = GetQualifiers();
  954. SendEvent(E_MOUSEMOVE, eventData);
  955. }
  956. else if (touchEmulation_ && touches_.Contains(0))
  957. {
  958. int x, y;
  959. SDL_GetMouseState(&x, &y);
  960. SDL_Event event;
  961. event.type = SDL_FINGERMOTION;
  962. event.tfinger.touchId = 0;
  963. event.tfinger.fingerId = 0;
  964. event.tfinger.pressure = 1.0f;
  965. event.tfinger.x = (float)x / (float)graphics_->GetWidth();
  966. event.tfinger.y = (float)y / (float)graphics_->GetHeight();
  967. event.tfinger.dx = (float)evt.motion.xrel / (float)graphics_->GetWidth();
  968. event.tfinger.dy = (float)evt.motion.yrel / (float)graphics_->GetHeight();
  969. SDL_PushEvent(&event);
  970. }
  971. break;
  972. case SDL_MOUSEWHEEL:
  973. if (!touchEmulation_)
  974. SetMouseWheel(evt.wheel.y);
  975. break;
  976. case SDL_FINGERDOWN:
  977. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  978. {
  979. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  980. TouchState& state = touches_[touchID];
  981. state.touchID_ = touchID;
  982. state.lastPosition_ = state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  983. (int)(evt.tfinger.y * graphics_->GetHeight()));
  984. state.delta_ = IntVector2::ZERO;
  985. state.pressure_ = evt.tfinger.pressure;
  986. using namespace TouchBegin;
  987. VariantMap& eventData = GetEventDataMap();
  988. eventData[P_TOUCHID] = touchID;
  989. eventData[P_X] = state.position_.x_;
  990. eventData[P_Y] = state.position_.y_;
  991. eventData[P_PRESSURE] = state.pressure_;
  992. SendEvent(E_TOUCHBEGIN, eventData);
  993. }
  994. break;
  995. case SDL_FINGERUP:
  996. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  997. {
  998. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  999. TouchState& state = touches_[touchID];
  1000. using namespace TouchEnd;
  1001. VariantMap& eventData = GetEventDataMap();
  1002. // Do not trust the position in the finger up event. Instead use the last position stored in the
  1003. // touch structure
  1004. eventData[P_TOUCHID] = touchID;
  1005. eventData[P_X] = state.position_.x_;
  1006. eventData[P_Y] = state.position_.y_;
  1007. SendEvent(E_TOUCHEND, eventData);
  1008. touches_.Erase(touchID);
  1009. }
  1010. break;
  1011. case SDL_FINGERMOTION:
  1012. if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
  1013. {
  1014. int touchID = evt.tfinger.fingerId & 0x7ffffff;
  1015. TouchState& state = touches_[touchID];
  1016. state.touchID_ = touchID;
  1017. state.position_ = IntVector2((int)(evt.tfinger.x * graphics_->GetWidth()),
  1018. (int)(evt.tfinger.y * graphics_->GetHeight()));
  1019. state.delta_ = state.position_ - state.lastPosition_;
  1020. state.pressure_ = evt.tfinger.pressure;
  1021. using namespace TouchMove;
  1022. VariantMap& eventData = GetEventDataMap();
  1023. eventData[P_TOUCHID] = touchID;
  1024. eventData[P_X] = state.position_.x_;
  1025. eventData[P_Y] = state.position_.y_;
  1026. eventData[P_DX] = (int)(evt.tfinger.dx * graphics_->GetWidth());
  1027. eventData[P_DY] = (int)(evt.tfinger.dy * graphics_->GetHeight());
  1028. eventData[P_PRESSURE] = state.pressure_;
  1029. SendEvent(E_TOUCHMOVE, eventData);
  1030. }
  1031. break;
  1032. case SDL_DOLLARRECORD:
  1033. {
  1034. using namespace GestureRecorded;
  1035. VariantMap& eventData = GetEventDataMap();
  1036. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  1037. SendEvent(E_GESTURERECORDED, eventData);
  1038. }
  1039. break;
  1040. case SDL_DOLLARGESTURE:
  1041. {
  1042. using namespace GestureInput;
  1043. VariantMap& eventData = GetEventDataMap();
  1044. eventData[P_GESTUREID] = (int)evt.dgesture.gestureId;
  1045. eventData[P_CENTERX] = (int)(evt.dgesture.x * graphics_->GetWidth());
  1046. eventData[P_CENTERY] = (int)(evt.dgesture.y * graphics_->GetHeight());
  1047. eventData[P_NUMFINGERS] = (int)evt.dgesture.numFingers;
  1048. eventData[P_ERROR] = evt.dgesture.error;
  1049. SendEvent(E_GESTUREINPUT, eventData);
  1050. }
  1051. break;
  1052. case SDL_MULTIGESTURE:
  1053. {
  1054. using namespace MultiGesture;
  1055. VariantMap& eventData = GetEventDataMap();
  1056. eventData[P_CENTERX] = (int)(evt.mgesture.x * graphics_->GetWidth());
  1057. eventData[P_CENTERY] = (int)(evt.mgesture.y * graphics_->GetHeight());
  1058. eventData[P_NUMFINGERS] = (int)evt.mgesture.numFingers;
  1059. eventData[P_DTHETA] = M_RADTODEG * evt.mgesture.dTheta;
  1060. eventData[P_DDIST] = evt.mgesture.dDist;
  1061. SendEvent(E_MULTIGESTURE, eventData);
  1062. }
  1063. break;
  1064. case SDL_JOYDEVICEADDED:
  1065. {
  1066. using namespace JoystickConnected;
  1067. SDL_JoystickID joystickID = OpenJoystick(evt.jdevice.which);
  1068. VariantMap& eventData = GetEventDataMap();
  1069. eventData[P_JOYSTICKID] = joystickID;
  1070. SendEvent(E_JOYSTICKCONNECTED, eventData);
  1071. }
  1072. break;
  1073. case SDL_JOYDEVICEREMOVED:
  1074. {
  1075. using namespace JoystickDisconnected;
  1076. joysticks_.Erase(evt.jdevice.which);
  1077. VariantMap& eventData = GetEventDataMap();
  1078. eventData[P_JOYSTICKID] = evt.jdevice.which;
  1079. SendEvent(E_JOYSTICKDISCONNECTED, eventData);
  1080. }
  1081. break;
  1082. case SDL_JOYBUTTONDOWN:
  1083. {
  1084. using namespace JoystickButtonDown;
  1085. unsigned button = evt.jbutton.button;
  1086. SDL_JoystickID joystickID = evt.jbutton.which;
  1087. JoystickState& state = joysticks_[joystickID];
  1088. // Skip ordinary joystick event for a controller
  1089. if (!state.controller_)
  1090. {
  1091. VariantMap& eventData = GetEventDataMap();
  1092. eventData[P_JOYSTICKID] = joystickID;
  1093. eventData[P_BUTTON] = button;
  1094. if (button < state.buttons_.Size())
  1095. {
  1096. state.buttons_[button] = true;
  1097. state.buttonPress_[button] = true;
  1098. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  1099. }
  1100. }
  1101. }
  1102. break;
  1103. case SDL_JOYBUTTONUP:
  1104. {
  1105. using namespace JoystickButtonUp;
  1106. unsigned button = evt.jbutton.button;
  1107. SDL_JoystickID joystickID = evt.jbutton.which;
  1108. JoystickState& state = joysticks_[joystickID];
  1109. if (!state.controller_)
  1110. {
  1111. VariantMap& eventData = GetEventDataMap();
  1112. eventData[P_JOYSTICKID] = joystickID;
  1113. eventData[P_BUTTON] = button;
  1114. if (button < state.buttons_.Size())
  1115. {
  1116. if (!state.controller_)
  1117. state.buttons_[button] = false;
  1118. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  1119. }
  1120. }
  1121. }
  1122. break;
  1123. case SDL_JOYAXISMOTION:
  1124. {
  1125. using namespace JoystickAxisMove;
  1126. SDL_JoystickID joystickID = evt.jaxis.which;
  1127. JoystickState& state = joysticks_[joystickID];
  1128. if (!state.controller_)
  1129. {
  1130. VariantMap& eventData = GetEventDataMap();
  1131. eventData[P_JOYSTICKID] = joystickID;
  1132. eventData[P_AXIS] = evt.jaxis.axis;
  1133. eventData[P_POSITION] = Clamp((float)evt.jaxis.value / 32767.0f, -1.0f, 1.0f);
  1134. if (evt.jaxis.axis < state.axes_.Size())
  1135. {
  1136. // If the joystick is a controller, only use the controller axis mappings
  1137. // (we'll also get the controller event)
  1138. if (!state.controller_)
  1139. state.axes_[evt.jaxis.axis] = eventData[P_POSITION].GetFloat();
  1140. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  1141. }
  1142. }
  1143. }
  1144. break;
  1145. case SDL_JOYHATMOTION:
  1146. {
  1147. using namespace JoystickHatMove;
  1148. SDL_JoystickID joystickID = evt.jaxis.which;
  1149. JoystickState& state = joysticks_[joystickID];
  1150. VariantMap& eventData = GetEventDataMap();
  1151. eventData[P_JOYSTICKID] = joystickID;
  1152. eventData[P_HAT] = evt.jhat.hat;
  1153. eventData[P_POSITION] = evt.jhat.value;
  1154. if (evt.jhat.hat < state.hats_.Size())
  1155. {
  1156. state.hats_[evt.jhat.hat] = evt.jhat.value;
  1157. SendEvent(E_JOYSTICKHATMOVE, eventData);
  1158. }
  1159. }
  1160. break;
  1161. case SDL_CONTROLLERBUTTONDOWN:
  1162. {
  1163. using namespace JoystickButtonDown;
  1164. unsigned button = evt.cbutton.button;
  1165. SDL_JoystickID joystickID = evt.cbutton.which;
  1166. JoystickState& state = joysticks_[joystickID];
  1167. VariantMap& eventData = GetEventDataMap();
  1168. eventData[P_JOYSTICKID] = joystickID;
  1169. eventData[P_BUTTON] = button;
  1170. if (button < state.buttons_.Size())
  1171. {
  1172. state.buttons_[button] = true;
  1173. state.buttonPress_[button] = true;
  1174. SendEvent(E_JOYSTICKBUTTONDOWN, eventData);
  1175. }
  1176. }
  1177. break;
  1178. case SDL_CONTROLLERBUTTONUP:
  1179. {
  1180. using namespace JoystickButtonUp;
  1181. unsigned button = evt.cbutton.button;
  1182. SDL_JoystickID joystickID = evt.cbutton.which;
  1183. JoystickState& state = joysticks_[joystickID];
  1184. VariantMap& eventData = GetEventDataMap();
  1185. eventData[P_JOYSTICKID] = joystickID;
  1186. eventData[P_BUTTON] = button;
  1187. if (button < state.buttons_.Size())
  1188. {
  1189. state.buttons_[button] = false;
  1190. SendEvent(E_JOYSTICKBUTTONUP, eventData);
  1191. }
  1192. }
  1193. break;
  1194. case SDL_CONTROLLERAXISMOTION:
  1195. {
  1196. using namespace JoystickAxisMove;
  1197. SDL_JoystickID joystickID = evt.caxis.which;
  1198. JoystickState& state = joysticks_[joystickID];
  1199. VariantMap& eventData = GetEventDataMap();
  1200. eventData[P_JOYSTICKID] = joystickID;
  1201. eventData[P_AXIS] = evt.caxis.axis;
  1202. eventData[P_POSITION] = Clamp((float)evt.caxis.value / 32767.0f, -1.0f, 1.0f);
  1203. if (evt.caxis.axis < state.axes_.Size())
  1204. {
  1205. state.axes_[evt.caxis.axis] = eventData[P_POSITION].GetFloat();
  1206. SendEvent(E_JOYSTICKAXISMOVE, eventData);
  1207. }
  1208. }
  1209. break;
  1210. case SDL_WINDOWEVENT:
  1211. {
  1212. switch (evt.window.event)
  1213. {
  1214. case SDL_WINDOWEVENT_MINIMIZED:
  1215. minimized_ = true;
  1216. SendInputFocusEvent();
  1217. break;
  1218. case SDL_WINDOWEVENT_MAXIMIZED:
  1219. case SDL_WINDOWEVENT_RESTORED:
  1220. minimized_ = false;
  1221. SendInputFocusEvent();
  1222. #ifdef IOS
  1223. // On iOS we never lose the GL context, but may have done GPU object changes that could not be applied yet.
  1224. // Apply them now
  1225. graphics_->Restore();
  1226. #endif
  1227. break;
  1228. #ifdef ANDROID
  1229. case SDL_WINDOWEVENT_FOCUS_GAINED:
  1230. // Restore GPU objects to the new GL context
  1231. graphics_->Restore();
  1232. break;
  1233. #endif
  1234. case SDL_WINDOWEVENT_RESIZED:
  1235. graphics_->WindowResized();
  1236. break;
  1237. }
  1238. }
  1239. break;
  1240. case SDL_DROPFILE:
  1241. {
  1242. using namespace DropFile;
  1243. VariantMap& eventData = GetEventDataMap();
  1244. eventData[P_FILENAME] = GetInternalPath(String(evt.drop.file));
  1245. SDL_free(evt.drop.file);
  1246. SendEvent(E_DROPFILE, eventData);
  1247. }
  1248. break;
  1249. case SDL_QUIT:
  1250. SendEvent(E_EXITREQUESTED);
  1251. break;
  1252. }
  1253. }
  1254. void Input::HandleScreenMode(StringHash eventType, VariantMap& eventData)
  1255. {
  1256. // Reset input state on subsequent initializations
  1257. if (!initialized_)
  1258. Initialize();
  1259. else
  1260. ResetState();
  1261. // Re-enable cursor clipping, and re-center the cursor (if needed) to the new screen size, so that there is no erroneous
  1262. // mouse move event. Also get new window ID if it changed
  1263. SDL_Window* window = graphics_->GetImpl()->GetWindow();
  1264. windowID_ = SDL_GetWindowID(window);
  1265. if (!mouseVisible_)
  1266. {
  1267. IntVector2 center(graphics_->GetWidth() / 2, graphics_->GetHeight() / 2);
  1268. SetMousePosition(center);
  1269. lastMousePosition_ = center;
  1270. }
  1271. focusedThisFrame_ = true;
  1272. // After setting a new screen mode we should not be minimized
  1273. minimized_ = (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) != 0;
  1274. }
  1275. void Input::HandleBeginFrame(StringHash eventType, VariantMap& eventData)
  1276. {
  1277. // Update input right at the beginning of the frame
  1278. Update();
  1279. }
  1280. void Input::HandleScreenJoystickTouch(StringHash eventType, VariantMap& eventData)
  1281. {
  1282. using namespace TouchBegin;
  1283. // Only interested in events from screen joystick(s)
  1284. TouchState& state = touches_[eventData[P_TOUCHID].GetInt()];
  1285. IntVector2 position(state.position_.x_, state.position_.y_);
  1286. UIElement* element = eventType == E_TOUCHBEGIN ? GetSubsystem<UI>()->GetElementAt(position) : state.touchedElement_;
  1287. if (!element)
  1288. return;
  1289. Variant variant = element->GetVar(VAR_SCREEN_JOYSTICK_ID);
  1290. if (variant.IsEmpty())
  1291. return;
  1292. SDL_JoystickID joystickID = variant.GetInt();
  1293. if (eventType == E_TOUCHEND)
  1294. state.touchedElement_.Reset();
  1295. else
  1296. state.touchedElement_ = element;
  1297. // Prepare a fake SDL event
  1298. SDL_Event evt;
  1299. const String& name = element->GetName();
  1300. if (name.StartsWith("Button"))
  1301. {
  1302. if (eventType == E_TOUCHMOVE)
  1303. return;
  1304. // Determine whether to inject a joystick event or keyboard/mouse event
  1305. Variant keyBindingVar = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1306. Variant mouseButtonBindingVar = element->GetVar(VAR_BUTTON_MOUSE_BUTTON_BINDING);
  1307. if (keyBindingVar.IsEmpty() && mouseButtonBindingVar.IsEmpty())
  1308. {
  1309. evt.type = eventType == E_TOUCHBEGIN ? SDL_JOYBUTTONDOWN : SDL_JOYBUTTONUP;
  1310. evt.jbutton.which = joystickID;
  1311. evt.jbutton.button = ToUInt(name.Substring(6));
  1312. }
  1313. else
  1314. {
  1315. if (!keyBindingVar.IsEmpty())
  1316. {
  1317. evt.type = eventType == E_TOUCHBEGIN ? SDL_KEYDOWN : SDL_KEYUP;
  1318. evt.key.keysym.sym = keyBindingVar.GetInt();
  1319. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1320. }
  1321. if (!mouseButtonBindingVar.IsEmpty())
  1322. {
  1323. // Mouse button are sent as extra events besides key events
  1324. SDL_Event evt;
  1325. evt.type = eventType == E_TOUCHBEGIN ? SDL_MOUSEBUTTONDOWN : SDL_MOUSEBUTTONUP;
  1326. evt.button.button = mouseButtonBindingVar.GetInt();
  1327. HandleSDLEvent(&evt);
  1328. }
  1329. }
  1330. }
  1331. else if (name.StartsWith("Hat"))
  1332. {
  1333. Variant keyBindingVar = element->GetVar(VAR_BUTTON_KEY_BINDING);
  1334. if (keyBindingVar.IsEmpty())
  1335. {
  1336. evt.type = SDL_JOYHATMOTION;
  1337. evt.jaxis.which = joystickID;
  1338. evt.jhat.hat = ToUInt(name.Substring(3));
  1339. evt.jhat.value = HAT_CENTER;
  1340. if (eventType != E_TOUCHEND)
  1341. {
  1342. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1343. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1344. evt.jhat.value |= HAT_UP;
  1345. if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1346. evt.jhat.value |= HAT_DOWN;
  1347. if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1348. evt.jhat.value |= HAT_LEFT;
  1349. if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1350. evt.jhat.value |= HAT_RIGHT;
  1351. }
  1352. }
  1353. else
  1354. {
  1355. // Hat is binded by 4 keys, like 'WASD'
  1356. String keyBinding = keyBindingVar.GetString();
  1357. if (eventType == E_TOUCHEND)
  1358. {
  1359. evt.type = SDL_KEYUP;
  1360. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1361. if (!evt.key.keysym.sym)
  1362. return;
  1363. element->SetVar(VAR_LAST_KEYSYM, 0);
  1364. }
  1365. else
  1366. {
  1367. evt.type = SDL_KEYDOWN;
  1368. IntVector2 relPosition = position - element->GetScreenPosition() - element->GetSize() / 2;
  1369. if (relPosition.y_ < 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1370. evt.key.keysym.sym = keyBinding[0];
  1371. else if (relPosition.y_ > 0 && Abs(relPosition.x_ * 3 / 2) < Abs(relPosition.y_))
  1372. evt.key.keysym.sym = keyBinding[1];
  1373. else if (relPosition.x_ < 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1374. evt.key.keysym.sym = keyBinding[2];
  1375. else if (relPosition.x_ > 0 && Abs(relPosition.y_ * 3 / 2) < Abs(relPosition.x_))
  1376. evt.key.keysym.sym = keyBinding[3];
  1377. else
  1378. return;
  1379. if (eventType == E_TOUCHMOVE && evt.key.keysym.sym != element->GetVar(VAR_LAST_KEYSYM).GetInt())
  1380. {
  1381. // Dragging past the directional boundary will cause an additional key up event for previous key symbol
  1382. SDL_Event evt;
  1383. evt.type = SDL_KEYUP;
  1384. evt.key.keysym.sym = element->GetVar(VAR_LAST_KEYSYM).GetInt();
  1385. if (evt.key.keysym.sym)
  1386. {
  1387. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1388. HandleSDLEvent(&evt);
  1389. }
  1390. element->SetVar(VAR_LAST_KEYSYM, 0);
  1391. }
  1392. evt.key.keysym.scancode = SDL_SCANCODE_UNKNOWN;
  1393. element->SetVar(VAR_LAST_KEYSYM, evt.key.keysym.sym);
  1394. }
  1395. }
  1396. }
  1397. else
  1398. return;
  1399. // Handle the fake SDL event to turn it into Urho3D genuine event
  1400. HandleSDLEvent(&evt);
  1401. }
  1402. }