sdlWindowMgr.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  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 "windowManager/sdl/sdlWindowMgr.h"
  23. #include "gfx/gfxDevice.h"
  24. #include "core/util/journal/process.h"
  25. #include "core/strings/unicode.h"
  26. #include "gfx/bitmap/gBitmap.h"
  27. #include "SDL.h"
  28. // ------------------------------------------------------------------------
  29. void sdl_CloseSplashWindow(void* hinst);
  30. #ifdef TORQUE_SDL
  31. PlatformWindowManager * CreatePlatformWindowManager()
  32. {
  33. return new PlatformWindowManagerSDL();
  34. }
  35. #endif
  36. // ------------------------------------------------------------------------
  37. PlatformWindowManagerSDL::PlatformWindowManagerSDL()
  38. {
  39. // Register in the process list.
  40. mOnProcessSignalSlot.setDelegate( this, &PlatformWindowManagerSDL::_process );
  41. Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER );
  42. // Init our list of allocated windows.
  43. mWindowListHead = NULL;
  44. // By default, we have no parent window.
  45. mParentWindow = NULL;
  46. mCurtainWindow = NULL;
  47. mDisplayWindow = true;
  48. mOffscreenRender = false;
  49. mInputState = KeyboardInputState::NONE;
  50. buildMonitorsList();
  51. }
  52. PlatformWindowManagerSDL::~PlatformWindowManagerSDL()
  53. {
  54. // Kill all our windows first.
  55. while(mWindowListHead)
  56. // The destructors update the list, so this works just fine.
  57. delete mWindowListHead;
  58. }
  59. RectI PlatformWindowManagerSDL::getPrimaryDesktopArea()
  60. {
  61. // TODO SDL
  62. AssertFatal(0, "");
  63. return RectI(0,0,0,0);
  64. }
  65. Point2I PlatformWindowManagerSDL::getDesktopResolution()
  66. {
  67. SDL_DisplayMode mode;
  68. SDL_GetDesktopDisplayMode(0, &mode);
  69. // Return Resolution
  70. return Point2I(mode.w, mode.h);
  71. }
  72. S32 PlatformWindowManagerSDL::getDesktopBitDepth()
  73. {
  74. // Return Bits per Pixel
  75. SDL_DisplayMode mode;
  76. SDL_GetDesktopDisplayMode(0, &mode);
  77. int bbp;
  78. unsigned int r,g,b,a;
  79. SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
  80. return bbp;
  81. }
  82. void PlatformWindowManagerSDL::buildMonitorsList()
  83. {
  84. // TODO SDL
  85. }
  86. S32 PlatformWindowManagerSDL::findFirstMatchingMonitor(const char* name)
  87. {
  88. /// TODO SDL
  89. AssertFatal(0, "");
  90. return 0;
  91. }
  92. U32 PlatformWindowManagerSDL::getMonitorCount()
  93. {
  94. // TODO SDL
  95. AssertFatal(0, "");
  96. return 1;
  97. }
  98. const char* PlatformWindowManagerSDL::getMonitorName(U32 index)
  99. {
  100. // TODO SDL
  101. AssertFatal(0, "");
  102. return "Monitor";
  103. }
  104. RectI PlatformWindowManagerSDL::getMonitorRect(U32 index)
  105. {
  106. // TODO SDL
  107. AssertFatal(0, "");
  108. return RectI(0, 0, 0,0 );
  109. }
  110. void PlatformWindowManagerSDL::getMonitorRegions(Vector<RectI> &regions)
  111. {
  112. // TODO SDL
  113. AssertFatal(0, "");
  114. }
  115. void PlatformWindowManagerSDL::getWindows(VectorPtr<PlatformWindow*> &windows)
  116. {
  117. PlatformWindowSDL *win = mWindowListHead;
  118. while(win)
  119. {
  120. windows.push_back(win);
  121. win = win->mNextWindow;
  122. }
  123. }
  124. PlatformWindow *PlatformWindowManagerSDL::createWindow(GFXDevice *device, const GFXVideoMode &mode)
  125. {
  126. // Do the allocation.
  127. PlatformWindowSDL *window = new PlatformWindowSDL();
  128. U32 windowFlags = /*SDL_WINDOW_SHOWN |*/ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
  129. if(GFX->getAdapterType() == OpenGL)
  130. windowFlags |= SDL_WINDOW_OPENGL;
  131. window->mWindowHandle = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mode.resolution.x, mode.resolution.y, windowFlags );
  132. window->mWindowId = SDL_GetWindowID( window->mWindowHandle );
  133. window->mOwningManager = this;
  134. mWindowMap[ window->mWindowId ] = window;
  135. //Now, fetch our window icon, if any
  136. Torque::Path iconPath = Torque::Path(Con::getVariable( "$Core::windowIcon" ));
  137. if (iconPath.getExtension() == String("bmp"))
  138. {
  139. Con::errorf("Unable to use bmp format images for the window icon. Please use a different format.");
  140. }
  141. else
  142. {
  143. Resource<GBitmap> img = GBitmap::load(iconPath);
  144. if (img != NULL)
  145. {
  146. U32 pitch;
  147. U32 width = img->getWidth();
  148. bool hasAlpha = img->getHasTransparency();
  149. U32 depth;
  150. if (hasAlpha)
  151. {
  152. pitch = 4 * width;
  153. depth = 32;
  154. }
  155. else
  156. {
  157. pitch = 3 * width;
  158. depth = 24;
  159. }
  160. Uint32 rmask, gmask, bmask, amask;
  161. if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
  162. {
  163. S32 shift = hasAlpha ? 8 : 0;
  164. rmask = 0xff000000 >> shift;
  165. gmask = 0x00ff0000 >> shift;
  166. bmask = 0x0000ff00 >> shift;
  167. amask = 0x000000ff >> shift;
  168. }
  169. else
  170. {
  171. rmask = 0x000000ff;
  172. gmask = 0x0000ff00;
  173. bmask = 0x00ff0000;
  174. amask = hasAlpha ? 0xff000000 : 0;
  175. }
  176. SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(img->getAddress(0, 0), img->getWidth(), img->getHeight(), depth, pitch, rmask, gmask, bmask, amask);
  177. SDL_SetWindowIcon(window->mWindowHandle, iconSurface);
  178. SDL_FreeSurface(iconSurface);
  179. }
  180. }
  181. if(device)
  182. {
  183. window->mDevice = device;
  184. window->mTarget = device->allocWindowTarget(window);
  185. AssertISV(window->mTarget, "PlatformWindowManagerSDL::createWindow - failed to get a window target back from the device.");
  186. }
  187. else
  188. {
  189. Con::warnf("PlatformWindowManagerSDL::createWindow - created a window with no device!");
  190. }
  191. linkWindow(window);
  192. return window;
  193. }
  194. void PlatformWindowManagerSDL::setParentWindow(void* newParent)
  195. {
  196. }
  197. void* PlatformWindowManagerSDL::getParentWindow()
  198. {
  199. return NULL;
  200. }
  201. void PlatformWindowManagerSDL::_process()
  202. {
  203. SDL_Event evt;
  204. while( SDL_PollEvent(&evt) )
  205. {
  206. switch(evt.type)
  207. {
  208. case SDL_QUIT:
  209. {
  210. PlatformWindowSDL *window = static_cast<PlatformWindowSDL*>( getFirstWindow() );
  211. if(window)
  212. window->appEvent.trigger( window->getWindowId(), WindowClose );
  213. break;
  214. }
  215. case SDL_KEYDOWN:
  216. case SDL_KEYUP:
  217. {
  218. PlatformWindowSDL *window = mWindowMap[evt.key.windowID];
  219. if(window)
  220. window->_processSDLEvent(evt);
  221. break;
  222. }
  223. case SDL_MOUSEWHEEL:
  224. {
  225. PlatformWindowSDL *window = mWindowMap[evt.wheel.windowID];
  226. if (window)
  227. window->_processSDLEvent(evt);
  228. break;
  229. }
  230. case SDL_MOUSEMOTION:
  231. {
  232. PlatformWindowSDL *window = mWindowMap[evt.motion.windowID];
  233. if(window)
  234. window->_processSDLEvent(evt);
  235. break;
  236. }
  237. case SDL_MOUSEBUTTONDOWN:
  238. case SDL_MOUSEBUTTONUP:
  239. {
  240. PlatformWindowSDL *window = mWindowMap[evt.button.windowID];
  241. if(window)
  242. window->_processSDLEvent(evt);
  243. break;
  244. }
  245. case SDL_TEXTINPUT:
  246. {
  247. PlatformWindowSDL *window = mWindowMap[evt.text.windowID];
  248. if(window)
  249. window->_processSDLEvent(evt);
  250. break;
  251. }
  252. case SDL_WINDOWEVENT:
  253. {
  254. PlatformWindowSDL *window = mWindowMap[evt.window.windowID];
  255. if(window)
  256. window->_processSDLEvent(evt);
  257. break;
  258. }
  259. default:
  260. {
  261. //Con::printf("Event: %d", evt.type);
  262. }
  263. }
  264. }
  265. // After the event loop is processed, we can now see if we have to notify
  266. // SDL that we want text based events. This fixes a bug where text based
  267. // events would be generated while key presses would still be happening.
  268. // See KeyboardInputState for further documentation.
  269. if (mInputState != KeyboardInputState::NONE)
  270. {
  271. // Update text mode toggling.
  272. if (mInputState == KeyboardInputState::TEXT_INPUT)
  273. SDL_StartTextInput();
  274. else
  275. SDL_StopTextInput();
  276. // Done until we need to update it again.
  277. mInputState = KeyboardInputState::NONE;
  278. }
  279. }
  280. PlatformWindow * PlatformWindowManagerSDL::getWindowById( WindowId id )
  281. {
  282. // Walk the list and find the matching id, if any.
  283. PlatformWindowSDL *win = mWindowListHead;
  284. while(win)
  285. {
  286. if(win->getWindowId() == id)
  287. return win;
  288. win = win->mNextWindow;
  289. }
  290. return NULL;
  291. }
  292. PlatformWindow * PlatformWindowManagerSDL::getFirstWindow()
  293. {
  294. return mWindowListHead != NULL ? mWindowListHead : NULL;
  295. }
  296. PlatformWindow* PlatformWindowManagerSDL::getFocusedWindow()
  297. {
  298. PlatformWindowSDL* window = mWindowListHead;
  299. while( window )
  300. {
  301. if( window->isFocused() )
  302. return window;
  303. window = window->mNextWindow;
  304. }
  305. return NULL;
  306. }
  307. void PlatformWindowManagerSDL::linkWindow( PlatformWindowSDL *w )
  308. {
  309. w->mNextWindow = mWindowListHead;
  310. mWindowListHead = w;
  311. }
  312. void PlatformWindowManagerSDL::unlinkWindow( PlatformWindowSDL *w )
  313. {
  314. PlatformWindowSDL **walk = &mWindowListHead;
  315. while(*walk)
  316. {
  317. if(*walk != w)
  318. {
  319. // Advance to next item in list.
  320. walk = &(*walk)->mNextWindow;
  321. continue;
  322. }
  323. // Got a match - unlink and return.
  324. *walk = (*walk)->mNextWindow;
  325. return;
  326. }
  327. }
  328. void PlatformWindowManagerSDL::_processCmdLineArgs( const S32 argc, const char **argv )
  329. {
  330. // TODO SDL
  331. }
  332. void PlatformWindowManagerSDL::lowerCurtain()
  333. {
  334. if(mCurtainWindow)
  335. return;
  336. // TODO SDL
  337. }
  338. void PlatformWindowManagerSDL::raiseCurtain()
  339. {
  340. if(!mCurtainWindow)
  341. return;
  342. // TODO SDL
  343. }
  344. void PlatformWindowManagerSDL::updateSDLTextInputState(KeyboardInputState state)
  345. {
  346. // Force update state. This will respond at the end of the event loop.
  347. mInputState = state;
  348. }
  349. void Platform::openFolder(const char* path )
  350. {
  351. AssertFatal(0, "Not Implemented");
  352. }
  353. void Platform::openFile(const char* path )
  354. {
  355. AssertFatal(0, "Not Implemented");
  356. }
  357. //------------------------------------------------------------------------------
  358. namespace GL
  359. {
  360. void gglPerformBinds();
  361. }
  362. void InitWindowingSystem()
  363. {
  364. }
  365. AFTER_MODULE_INIT(gfx)
  366. {
  367. int res = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE );
  368. AssertFatal(res != -1, "SDL init error");
  369. // By default, SDL enables text input. We disable it on initialization, and
  370. // we will enable it whenever the time is right.
  371. SDL_StopTextInput();
  372. }