sdlWindow.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  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
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell 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
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "math/mMath.h"
  23. #include "gfx/gfxStructs.h"
  24. #include "windowManager/sdl/sdlWindow.h"
  25. #include "windowManager/sdl/sdlWindowMgr.h"
  26. #include "windowManager/sdl/sdlCursorController.h"
  27. #include "platformSDL/sdlInput.h"
  28. #include "platform/menus/popupMenu.h"
  29. #include "platform/platformInput.h"
  30. #include "gfx/gfxDevice.h"
  31. #ifdef TORQUE_OS_LINUX
  32. #define SDL_VIDEO_DRIVER_X11 // TODO SDL
  33. #endif
  34. #include "SDL.h"
  35. #include "SDL_syswm.h"
  36. #define SCREENSAVER_QUERY_DENY 0 // Disable screensaver
  37. #ifndef IDI_ICON1
  38. #define IDI_ICON1 107
  39. #endif
  40. namespace
  41. {
  42. U32 getTorqueModFromSDL(U16 mod)
  43. {
  44. U32 ret = 0;
  45. if(mod & KMOD_LSHIFT)
  46. ret |= IM_LSHIFT;
  47. if(mod & KMOD_RSHIFT)
  48. ret |= IM_RSHIFT;
  49. if(mod & KMOD_LCTRL)
  50. ret |= IM_LCTRL;
  51. if(mod & KMOD_RCTRL)
  52. ret |= IM_RCTRL;
  53. if(mod & KMOD_LALT)
  54. ret |= IM_LALT;
  55. if(mod & KMOD_RALT)
  56. ret |= IM_RALT;
  57. return ret;
  58. }
  59. }
  60. PlatformWindowSDL::PlatformWindowSDL():
  61. mShouldLockMouse(false),
  62. mMouseLocked(false),
  63. mOwningManager(NULL),
  64. mNextWindow(NULL),
  65. mWindowHandle(NULL),
  66. mOldParent(NULL),
  67. mTarget(NULL),
  68. mDevice(NULL),
  69. mSuppressReset(false),
  70. mMenuHandle(NULL),
  71. mPosition(0,0)
  72. {
  73. mCursorController = new PlatformCursorControllerSDL( this );
  74. mVideoMode.bitDepth = 32;
  75. mVideoMode.fullScreen = false;
  76. mVideoMode.refreshRate = 60;
  77. mVideoMode.resolution.set(800,600);
  78. }
  79. PlatformWindowSDL::~PlatformWindowSDL()
  80. {
  81. // delete our sdl handle..
  82. SDL_DestroyWindow(mWindowHandle);
  83. // unlink ourselves from the window list...
  84. AssertFatal(mOwningManager, "PlatformWindowSDL::~PlatformWindowSDL - orphan window, cannot unlink!");
  85. mOwningManager->unlinkWindow(this);
  86. }
  87. GFXDevice * PlatformWindowSDL::getGFXDevice()
  88. {
  89. return mDevice;
  90. }
  91. GFXWindowTarget * PlatformWindowSDL::getGFXTarget()
  92. {
  93. return mTarget;
  94. }
  95. const GFXVideoMode & PlatformWindowSDL::getVideoMode()
  96. {
  97. return mVideoMode;
  98. }
  99. void* PlatformWindowSDL::getSystemWindow(const WindowSystem system)
  100. {
  101. SDL_SysWMinfo info;
  102. SDL_VERSION(&info.version);
  103. SDL_GetWindowWMInfo(mWindowHandle,&info);
  104. #ifdef TORQUE_OS_WIN
  105. if( system == WindowSystem_Windows && info.subsystem == SDL_SYSWM_WINDOWS)
  106. return info.info.win.window;
  107. #endif
  108. #if defined(TORQUE_OS_LINUX)
  109. if( system == WindowSystem_X11 && info.subsystem == SDL_SYSWM_X11)
  110. return (void*)info.info.x11.window;
  111. #endif
  112. AssertFatal(0, "");
  113. return NULL;
  114. }
  115. void PlatformWindowSDL::setVideoMode( const GFXVideoMode &mode )
  116. {
  117. mVideoMode = mode;
  118. mSuppressReset = true;
  119. // Set our window to have the right style based on the mode
  120. if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender)
  121. {
  122. setSize(mode.resolution);
  123. SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
  124. // When switching to Fullscreen, reset device after setting style
  125. if(mTarget.isValid())
  126. mTarget->resetMode();
  127. }
  128. else
  129. {
  130. // Reset device *first*, so that when we call setSize() and let it
  131. // access the monitor settings, it won't end up with our fullscreen
  132. // geometry that is just about to change.
  133. if(mTarget.isValid())
  134. mTarget->resetMode();
  135. if (!mOffscreenRender)
  136. {
  137. SDL_SetWindowFullscreen( mWindowHandle, 0);
  138. }
  139. setSize(mode.resolution);
  140. centerWindow();
  141. }
  142. mSuppressReset = false;
  143. }
  144. bool PlatformWindowSDL::clearFullscreen()
  145. {
  146. return true;
  147. }
  148. bool PlatformWindowSDL::isFullscreen()
  149. {
  150. U32 flags = SDL_GetWindowFlags( mWindowHandle );
  151. if( flags & SDL_WINDOW_FULLSCREEN || flags & SDL_WINDOW_FULLSCREEN_DESKTOP )
  152. return true;
  153. return false;
  154. }
  155. void PlatformWindowSDL::_setFullscreen(const bool fullscreen)
  156. {
  157. if( isFullscreen() )
  158. return;
  159. if(fullscreen && !mOffscreenRender)
  160. {
  161. Con::printf("PlatformWindowSDL::setFullscreen (full) enter");
  162. SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
  163. }
  164. else
  165. {
  166. Con::printf("PlatformWindowSDL::setFullscreen (windowed) enter");
  167. if (!mOffscreenRender)
  168. {
  169. SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN_DESKTOP);
  170. }
  171. setSize(mVideoMode.resolution);
  172. }
  173. Con::printf("PlatformWindowSDL::setFullscreen exit");
  174. }
  175. bool PlatformWindowSDL::setCaption( const char *cap )
  176. {
  177. SDL_SetWindowTitle(mWindowHandle, cap);
  178. return true;
  179. }
  180. const char * PlatformWindowSDL::getCaption()
  181. {
  182. return StringTable->insert( SDL_GetWindowTitle(mWindowHandle) );
  183. }
  184. void PlatformWindowSDL::setFocus()
  185. {
  186. SDL_SetWindowGrab( mWindowHandle, SDL_TRUE );
  187. }
  188. void PlatformWindowSDL::setClientExtent( const Point2I newExtent )
  189. {
  190. Point2I oldExtent = getClientExtent();
  191. if (oldExtent == newExtent)
  192. return;
  193. SDL_SetWindowSize(mWindowHandle, newExtent.x, newExtent.y);
  194. }
  195. const Point2I PlatformWindowSDL::getClientExtent()
  196. {
  197. // Fetch Client Rect from Windows
  198. Point2I size;
  199. SDL_GetWindowSize(mWindowHandle, &size.x, &size.y);
  200. return size;
  201. }
  202. void PlatformWindowSDL::setBounds( const RectI &newBounds )
  203. {
  204. // TODO SDL
  205. }
  206. const RectI PlatformWindowSDL::getBounds() const
  207. {
  208. // TODO SDL
  209. return RectI(0, 0, 0, 0);
  210. }
  211. void PlatformWindowSDL::setPosition( const Point2I newPosition )
  212. {
  213. SDL_SetWindowPosition( mWindowHandle, newPosition.x, newPosition.y );
  214. }
  215. const Point2I PlatformWindowSDL::getPosition()
  216. {
  217. Point2I position;
  218. SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
  219. // Return position
  220. return position;
  221. }
  222. Point2I PlatformWindowSDL::clientToScreen( const Point2I& pos )
  223. {
  224. Point2I position;
  225. SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
  226. return pos + position;
  227. }
  228. Point2I PlatformWindowSDL::screenToClient( const Point2I& pos )
  229. {
  230. Point2I position;
  231. SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
  232. return pos - position;
  233. }
  234. void PlatformWindowSDL::centerWindow()
  235. {
  236. int sizeX, sizeY;
  237. SDL_GetWindowSize(mWindowHandle, &sizeX, &sizeY);
  238. SDL_DisplayMode mode;
  239. SDL_GetDesktopDisplayMode(0, &mode);
  240. U32 posX = (mode.w/2) - (sizeX/2);
  241. U32 posY = (mode.h/2) - (sizeY/2);
  242. SDL_SetWindowPosition( mWindowHandle, posX, posY);
  243. }
  244. bool PlatformWindowSDL::setSize( const Point2I &newSize )
  245. {
  246. SDL_SetWindowSize(mWindowHandle, newSize.x, newSize.y);
  247. // Let GFX get an update about the new resolution
  248. if (mTarget.isValid())
  249. mTarget->resetMode();
  250. return true;
  251. }
  252. bool PlatformWindowSDL::isOpen()
  253. {
  254. return mWindowHandle;
  255. }
  256. bool PlatformWindowSDL::isVisible()
  257. {
  258. // Is the window open and visible, ie. not minimized?
  259. if(!mWindowHandle)
  260. return false;
  261. if (mOffscreenRender)
  262. return true;
  263. U32 flags = SDL_GetWindowFlags( mWindowHandle );
  264. if( flags & SDL_WINDOW_SHOWN)
  265. return true;
  266. return false;
  267. }
  268. bool PlatformWindowSDL::isFocused()
  269. {
  270. if (mOffscreenRender)
  271. return true;
  272. U32 flags = SDL_GetWindowFlags( mWindowHandle );
  273. if( flags & SDL_WINDOW_INPUT_FOCUS || flags & SDL_WINDOW_INPUT_GRABBED || flags & SDL_WINDOW_MOUSE_FOCUS )
  274. return true;
  275. return true;
  276. }
  277. bool PlatformWindowSDL::isMinimized()
  278. {
  279. if (mOffscreenRender)
  280. return false;
  281. U32 flags = SDL_GetWindowFlags( mWindowHandle );
  282. if( flags & SDL_WINDOW_MINIMIZED)
  283. return true;
  284. return false;
  285. }
  286. bool PlatformWindowSDL::isMaximized()
  287. {
  288. if (mOffscreenRender)
  289. return true;
  290. U32 flags = SDL_GetWindowFlags( mWindowHandle );
  291. if( flags & SDL_WINDOW_MAXIMIZED)
  292. return true;
  293. return false;
  294. }
  295. WindowId PlatformWindowSDL::getWindowId()
  296. {
  297. return mWindowId;
  298. }
  299. void PlatformWindowSDL::minimize()
  300. {
  301. if (mOffscreenRender)
  302. return;
  303. SDL_MinimizeWindow( mWindowHandle );
  304. }
  305. void PlatformWindowSDL::maximize()
  306. {
  307. if (mOffscreenRender)
  308. return;
  309. SDL_MaximizeWindow( mWindowHandle );
  310. }
  311. void PlatformWindowSDL::restore()
  312. {
  313. if (mOffscreenRender)
  314. return;
  315. SDL_RestoreWindow( mWindowHandle );
  316. }
  317. void PlatformWindowSDL::hide()
  318. {
  319. if (mOffscreenRender)
  320. return;
  321. SDL_HideWindow( mWindowHandle );
  322. }
  323. void PlatformWindowSDL::show()
  324. {
  325. if (mOffscreenRender)
  326. return;
  327. SDL_ShowWindow( mWindowHandle );
  328. }
  329. void PlatformWindowSDL::close()
  330. {
  331. delete this;
  332. }
  333. void PlatformWindowSDL::defaultRender()
  334. {
  335. // TODO SDL
  336. }
  337. void PlatformWindowSDL::_triggerMouseLocationNotify(const SDL_Event& evt)
  338. {
  339. U32 mods = getTorqueModFromSDL(SDL_GetModState());
  340. if(!mMouseLocked)
  341. mouseEvent.trigger(getWindowId(), mods, evt.motion.x, evt.motion.y, false);
  342. else
  343. mouseEvent.trigger(getWindowId(), mods, evt.motion.xrel, evt.motion.yrel, true);
  344. }
  345. void PlatformWindowSDL::_triggerMouseWheelNotify(const SDL_Event& evt)
  346. {
  347. U32 mods = getTorqueModFromSDL(SDL_GetModState());
  348. S32 wheelDelta = Con::getIntVariable("$pref::Input::MouseWheelSpeed", 120);
  349. wheelEvent.trigger(getWindowId(), mods, evt.wheel.x * wheelDelta, evt.wheel.y * wheelDelta);
  350. }
  351. void PlatformWindowSDL::_triggerMouseButtonNotify(const SDL_Event& event)
  352. {
  353. S32 action = (event.type == SDL_MOUSEBUTTONDOWN) ? SI_MAKE : SI_BREAK;
  354. S32 button = -1;
  355. switch (event.button.button)
  356. {
  357. case SDL_BUTTON_LEFT:
  358. button = 0;
  359. break;
  360. case SDL_BUTTON_RIGHT:
  361. button = 1;
  362. break;
  363. case SDL_BUTTON_MIDDLE:
  364. button = 2;
  365. break;
  366. default:
  367. return;
  368. }
  369. U32 mod = getTorqueModFromSDL( SDL_GetModState() );
  370. buttonEvent.trigger(getWindowId(), mod, action, button );
  371. }
  372. void PlatformWindowSDL::_triggerKeyNotify(const SDL_Event& evt)
  373. {
  374. U32 inputAction = IA_MAKE;
  375. SDL_Keysym tKey = evt.key.keysym;
  376. if(evt.type == SDL_KEYUP)
  377. {
  378. inputAction = IA_BREAK;
  379. }
  380. if(evt.key.repeat)
  381. {
  382. inputAction = IA_REPEAT;
  383. }
  384. U32 torqueModifiers = getTorqueModFromSDL(evt.key.keysym.mod);
  385. U32 torqueKey = KeyMapSDL::getTorqueScanCodeFromSDL(tKey.scancode);
  386. if(tKey.scancode)
  387. {
  388. keyEvent.trigger(getWindowId(), torqueModifiers, inputAction, torqueKey);
  389. //Con::printf("Key %d : %d", tKey.sym, inputAction);
  390. }
  391. }
  392. void PlatformWindowSDL::_triggerTextNotify(const SDL_Event& evt)
  393. {
  394. U32 mod = getTorqueModFromSDL( SDL_GetModState() );
  395. if( !evt.text.text[1] ) // get a char
  396. {
  397. U16 wchar = evt.text.text[0];
  398. charEvent.trigger(getWindowId(), mod, wchar );
  399. //Con::printf("Char: %c", wchar);
  400. return;
  401. }
  402. else // get a wchar string
  403. {
  404. const U32 len = strlen(evt.text.text);
  405. U16 wchar[16] = {};
  406. dMemcpy(wchar, evt.text.text, sizeof(char)*len);
  407. for(int i = 0; i < 16; ++i)
  408. {
  409. if( !wchar[i] )
  410. return;
  411. charEvent.trigger(getWindowId(), mod, wchar[i] );
  412. }
  413. }
  414. }
  415. void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
  416. {
  417. switch(evt.type)
  418. {
  419. case SDL_KEYDOWN:
  420. case SDL_KEYUP:
  421. {
  422. _triggerKeyNotify(evt);
  423. break;
  424. }
  425. case SDL_TEXTINPUT:
  426. {
  427. _triggerTextNotify(evt);
  428. break;
  429. }
  430. case SDL_MOUSEWHEEL:
  431. {
  432. _triggerMouseWheelNotify(evt);
  433. break;
  434. }
  435. case SDL_MOUSEMOTION:
  436. {
  437. _triggerMouseLocationNotify(evt);
  438. break;
  439. }
  440. case SDL_MOUSEBUTTONDOWN:
  441. case SDL_MOUSEBUTTONUP:
  442. {
  443. appEvent.trigger(getWindowId(), GainFocus);
  444. _triggerMouseButtonNotify(evt);
  445. break;
  446. }
  447. case SDL_WINDOWEVENT:
  448. {
  449. switch( evt.window.event )
  450. {
  451. case SDL_WINDOWEVENT_MAXIMIZED:
  452. case SDL_WINDOWEVENT_RESIZED:
  453. {
  454. int width, height;
  455. SDL_GetWindowSize( mWindowHandle, &width, &height );
  456. mVideoMode.resolution.set( width, height );
  457. getGFXTarget()->resetMode();
  458. break;
  459. }
  460. default:
  461. break;
  462. }
  463. }
  464. }
  465. }
  466. //-----------------------------------------------------------------------------
  467. // Mouse Locking
  468. //-----------------------------------------------------------------------------
  469. void PlatformWindowSDL::setMouseLocked( bool enable )
  470. {
  471. if (mOffscreenRender)
  472. return;
  473. mMouseLocked = enable;
  474. SDL_SetWindowGrab( mWindowHandle, SDL_bool(enable) );
  475. SDL_SetRelativeMouseMode( SDL_bool(enable) );
  476. }
  477. const UTF16 *PlatformWindowSDL::getWindowClassName()
  478. {
  479. // TODO SDL
  480. static String str("WindowClassName");
  481. return str.utf16();
  482. }
  483. const UTF16 *PlatformWindowSDL::getCurtainWindowClassName()
  484. {
  485. // TODO SDL
  486. static String str("CurtainWindowClassName");
  487. return str.utf16();
  488. }
  489. void PlatformWindowSDL::setKeyboardTranslation(const bool enabled)
  490. {
  491. mEnableKeyboardTranslation = enabled;
  492. if (mEnableKeyboardTranslation)
  493. SDL_StartTextInput();
  494. else
  495. SDL_StopTextInput();
  496. }