Torque3D Documentation / _generateds / sdlWindowMgr.cpp

sdlWindowMgr.cpp

Engine/source/windowManager/sdl/sdlWindowMgr.cpp

More...

Namespaces:

namespace

Detailed Description

Public Functions

AFTER_MODULE_INIT(gfx )

InitWindowingSystem()

sdl_CloseSplashWindow(void * hinst)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "windowManager/sdl/sdlWindowMgr.h"
 25#include "platformSDL/sdlInputManager.h"
 26#include "gfx/gfxDevice.h"
 27#include "core/util/journal/process.h"
 28#include "core/strings/unicode.h"
 29#include "gfx/bitmap/gBitmap.h"
 30
 31#include "SDL.h"
 32
 33// ------------------------------------------------------------------------
 34
 35void sdl_CloseSplashWindow(void* hinst);
 36
 37#ifdef TORQUE_SDL
 38
 39PlatformWindowManager * CreatePlatformWindowManager()
 40{
 41   return new PlatformWindowManagerSDL();
 42}
 43
 44#endif
 45
 46// ------------------------------------------------------------------------
 47
 48PlatformWindowManagerSDL::PlatformWindowManagerSDL()
 49{
 50   // Register in the process list.
 51   mOnProcessSignalSlot.setDelegate( this, &PlatformWindowManagerSDL::_process );
 52   Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER );
 53
 54   // Init our list of allocated windows.
 55   mWindowListHead = NULL;
 56
 57   // By default, we have no parent window.
 58   mParentWindow = NULL;
 59
 60   mCurtainWindow = NULL;
 61
 62   mDisplayWindow = true;
 63   mOffscreenRender = false;
 64
 65   mInputState = KeyboardInputState::NONE;
 66}
 67
 68PlatformWindowManagerSDL::~PlatformWindowManagerSDL()
 69{
 70   // Kill all our windows first.
 71   while(mWindowListHead)
 72      // The destructors update the list, so this works just fine.
 73      delete mWindowListHead;
 74}
 75
 76RectI PlatformWindowManagerSDL::getPrimaryDesktopArea()
 77{
 78   // Primary is monitor 0
 79   return getMonitorRect(0);
 80}
 81
 82Point2I PlatformWindowManagerSDL::getDesktopResolution()
 83{
 84   SDL_DisplayMode mode;
 85   SDL_GetDesktopDisplayMode(0, &mode);
 86
 87   // Return Resolution
 88   return Point2I(mode.w, mode.h);
 89}
 90
 91S32 PlatformWindowManagerSDL::getDesktopBitDepth()
 92{
 93   // Return Bits per Pixel
 94   SDL_DisplayMode mode;
 95   SDL_GetDesktopDisplayMode(0, &mode);
 96   int bbp;
 97   unsigned int r,g,b,a;
 98   SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
 99   return bbp;
100}
101
102S32 PlatformWindowManagerSDL::findFirstMatchingMonitor(const char* name)
103{
104   S32 count = SDL_GetNumVideoDisplays();
105   for (U32 index = 0; index < count; ++index)
106   {
107      if (dStrstr(name, SDL_GetDisplayName(index)) == name)
108         return index;
109   }
110
111   return 0;
112}
113
114U32 PlatformWindowManagerSDL::getMonitorCount()
115{
116   S32 monitorCount = SDL_GetNumVideoDisplays();
117   if (monitorCount < 0)
118   {
119      Con::errorf("SDL_GetNumVideoDisplays() failed: %s", SDL_GetError());
120      monitorCount = 0;
121   }
122
123   return (U32)monitorCount;
124}
125
126const char* PlatformWindowManagerSDL::getMonitorName(U32 index)
127{
128   const char* monitorName = SDL_GetDisplayName(index);
129   if (monitorName == NULL)
130      Con::errorf("SDL_GetDisplayName() failed: %s", SDL_GetError());
131
132   return monitorName;
133}
134
135RectI PlatformWindowManagerSDL::getMonitorRect(U32 index)
136{
137   SDL_Rect sdlRect;
138   if (0 != SDL_GetDisplayBounds(index, &sdlRect))
139   {
140      Con::errorf("SDL_GetDisplayBounds() failed: %s", SDL_GetError());
141      return RectI(0, 0, 0, 0);
142   }
143
144   return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
145}
146
147RectI PlatformWindowManagerSDL::getMonitorUsableRect(U32 index)
148{
149   SDL_Rect sdlRect;
150   if (0 != SDL_GetDisplayUsableBounds(index, &sdlRect))
151   {
152      Con::errorf("SDL_GetDisplayUsableBounds() failed: %s", SDL_GetError());
153      return RectI(0, 0, 0, 0);
154   }
155
156   return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
157}
158
159U32 PlatformWindowManagerSDL::getMonitorModeCount(U32 monitorIndex)
160{
161   S32 modeCount = SDL_GetNumDisplayModes(monitorIndex);
162   if (modeCount < 0)
163   {
164      Con::errorf("SDL_GetNumDisplayModes(%d) failed: %s", monitorIndex, SDL_GetError());
165      modeCount = 0;
166   }
167
168   return (U32)modeCount;
169}
170
171const String PlatformWindowManagerSDL::getMonitorMode(U32 monitorIndex, U32 modeIndex)
172{
173   SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
174   if (SDL_GetDisplayMode(monitorIndex, modeIndex, &mode) != 0)
175   {
176      Con::errorf("SDL_GetDisplayMode(%d, %d) failed: %s", monitorIndex, modeIndex, SDL_GetError());
177      return String::EmptyString;
178   }
179
180   GFXVideoMode vm;
181   vm.resolution.set(mode.w, mode.h);
182   vm.refreshRate = mode.refresh_rate;
183   vm.bitDepth = 32;
184   vm.antialiasLevel = 0;
185   vm.fullScreen = false;
186   vm.wideScreen = false;
187
188   return vm.toString();
189}
190
191const String PlatformWindowManagerSDL::getMonitorDesktopMode(U32 monitorIndex)
192{
193   SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
194   if (SDL_GetDesktopDisplayMode(monitorIndex, &mode) != 0)
195   {
196      Con::errorf("SDL_GetDesktopDisplayMode(%d) failed: %s", monitorIndex, SDL_GetError());
197      return String::EmptyString;
198   }
199
200   GFXVideoMode vm;
201   vm.resolution.set(mode.w, mode.h);
202   vm.refreshRate = mode.refresh_rate;
203
204   int bbp;
205   unsigned int r, g, b, a;
206   SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
207   vm.bitDepth = bbp;
208   vm.antialiasLevel = 0;
209   vm.fullScreen = false;
210   vm.wideScreen = ((mode.w / 16) * 9) == mode.h;
211
212   return vm.toString();
213}
214
215void PlatformWindowManagerSDL::getMonitorRegions(Vector<RectI> &regions)
216{
217   SDL_Rect sdlRect;
218   S32 monitorCount = SDL_GetNumVideoDisplays();
219   for (S32 index = 0; index < monitorCount; ++index)
220   {
221      if (0 == SDL_GetDisplayBounds(index, &sdlRect))
222         regions.push_back(RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h));
223   }
224}
225
226void PlatformWindowManagerSDL::getWindows(VectorPtr<PlatformWindow*> &windows)
227{
228   PlatformWindowSDL *win = mWindowListHead;
229   while(win)
230   {
231      windows.push_back(win);
232      win = win->mNextWindow;
233   }
234}
235
236PlatformWindow *PlatformWindowManagerSDL::createWindow(GFXDevice *device, const GFXVideoMode &mode)
237{
238   // Do the allocation.
239   PlatformWindowSDL *window = new PlatformWindowSDL();   
240   U32 windowFlags = /*SDL_WINDOW_SHOWN |*/ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
241
242   if(GFX->getAdapterType() == OpenGL)
243       windowFlags |= SDL_WINDOW_OPENGL;
244
245   window->mWindowHandle = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mode.resolution.x, mode.resolution.y, windowFlags );
246   window->mWindowId = SDL_GetWindowID( window->mWindowHandle );
247   window->mOwningManager = this;
248   mWindowMap[ window->mWindowId ] = window;
249
250   //Now, fetch our window icon, if any
251   Torque::Path iconPath = Torque::Path(Con::getVariable( "$Core::windowIcon" ));
252
253   if (iconPath.getExtension() == String("bmp"))
254   {
255      Con::errorf("Unable to use bmp format images for the window icon. Please use a different format.");
256   }
257   else
258   {
259      Resource<GBitmap> img = GBitmap::load(iconPath);
260      if (img != NULL)
261      {
262         U32 pitch;
263         U32 width = img->getWidth();
264         bool hasAlpha = img->getHasTransparency();
265         U32 depth;
266
267         if (hasAlpha)
268         {
269            pitch = 4 * width;
270            depth = 32;
271         }
272         else
273         {
274            pitch = 3 * width;
275            depth = 24;
276         }
277
278         Uint32 rmask, gmask, bmask, amask;
279         if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
280         {
281            S32 shift = hasAlpha ? 8 : 0;
282            rmask = 0xff000000 >> shift;
283            gmask = 0x00ff0000 >> shift;
284            bmask = 0x0000ff00 >> shift;
285            amask = 0x000000ff >> shift;
286         }
287         else
288         {
289            rmask = 0x000000ff;
290            gmask = 0x0000ff00;
291            bmask = 0x00ff0000;
292            amask = hasAlpha ? 0xff000000 : 0;
293         }
294
295         SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(img->getAddress(0, 0), img->getWidth(), img->getHeight(), depth, pitch, rmask, gmask, bmask, amask);
296
297         SDL_SetWindowIcon(window->mWindowHandle, iconSurface);
298
299         SDL_FreeSurface(iconSurface);
300      }
301   }
302
303   if(device)
304   {
305      window->mDevice = device;
306      window->mTarget = device->allocWindowTarget(window);
307      AssertISV(window->mTarget, "PlatformWindowManagerSDL::createWindow - failed to get a window target back from the device.");
308   }
309   else
310   {
311      Con::warnf("PlatformWindowManagerSDL::createWindow - created a window with no device!");
312   }
313
314   //Set it up for drag-n-drop events 
315#ifdef TORQUE_TOOLS
316   SDL_EventState(SDL_DROPBEGIN, SDL_ENABLE);
317   SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
318   SDL_EventState(SDL_DROPCOMPLETE, SDL_ENABLE);
319#endif
320
321   linkWindow(window);
322
323   SDL_SetWindowMinimumSize(window->mWindowHandle, Con::getIntVariable("$Video::minimumXResolution", 1024),
324         Con::getIntVariable("$Video::minimumYResolution", 720));
325
326   return window;
327}
328
329
330void PlatformWindowManagerSDL::setParentWindow(void* newParent)
331{
332   
333}
334
335void* PlatformWindowManagerSDL::getParentWindow()
336{
337   return NULL;
338}
339
340void PlatformWindowManagerSDL::_process()
341{
342   SDL_Event evt;
343   while( SDL_PollEvent(&evt) )
344   {      
345      if (evt.type >= SDL_JOYAXISMOTION && evt.type <= SDL_CONTROLLERDEVICEREMAPPED)
346      {
347         SDLInputManager* mgr = static_cast<SDLInputManager*>(Input::getManager());
348         if (mgr)
349            mgr->processEvent(evt);
350         continue;
351      }
352      switch(evt.type)
353      {
354          case SDL_QUIT:
355          {
356             PlatformWindowSDL *window = static_cast<PlatformWindowSDL*>( getFirstWindow() );
357             if(window)
358               window->appEvent.trigger( window->getWindowId(), WindowClose );
359             break;
360          }
361
362         case SDL_KEYDOWN:
363         case SDL_KEYUP:
364         {
365            PlatformWindowSDL *window = mWindowMap[evt.key.windowID];
366            if(window)
367               window->_processSDLEvent(evt);
368            break;
369         }
370
371         case SDL_MOUSEWHEEL:
372         {
373            PlatformWindowSDL *window = mWindowMap[evt.wheel.windowID];
374            if (window)
375               window->_processSDLEvent(evt);
376            break;
377         }
378
379         case SDL_MOUSEMOTION:
380         {
381            PlatformWindowSDL *window = mWindowMap[evt.motion.windowID];
382            if(window)
383               window->_processSDLEvent(evt);
384            break;
385         }
386
387         case SDL_MOUSEBUTTONDOWN:
388         case SDL_MOUSEBUTTONUP:
389         {
390            PlatformWindowSDL *window = mWindowMap[evt.button.windowID];
391            if(window)
392               window->_processSDLEvent(evt);
393            break;
394         }
395
396         case SDL_TEXTINPUT:
397         {
398            PlatformWindowSDL *window = mWindowMap[evt.text.windowID];
399            if(window)
400               window->_processSDLEvent(evt);
401            break;
402         }
403
404         case SDL_WINDOWEVENT:
405         {
406            PlatformWindowSDL *window = mWindowMap[evt.window.windowID];
407            if(window)
408               window->_processSDLEvent(evt);
409            break;
410         }
411
412         case(SDL_DROPBEGIN):
413         {
414            if (!Con::isFunction("onDropBegin"))
415               break;
416
417            Con::executef("onDropBegin");
418         }
419
420         case (SDL_DROPFILE):
421         {
422            // In case if dropped file
423            if (!Con::isFunction("onDropFile"))
424               break;
425
426            char* fileName = evt.drop.file;
427
428            if (!Platform::isDirectory(fileName) && !Platform::isFile(fileName))
429               break;
430
431            Con::executef("onDropFile", StringTable->insert(fileName));
432
433            SDL_free(fileName);    // Free dropped_filedir memory
434            break;
435         }
436
437         case(SDL_DROPCOMPLETE):
438         {
439            if (Con::isFunction("onDropEnd"))
440               Con::executef("onDropEnd");
441            break;
442         }
443
444         default:
445         {
446#ifdef TORQUE_DEBUG
447            Con::warnf("Unhandled SDL input event: 0x%04x", evt.type);
448#endif
449         }
450      }
451   }
452
453   // After the event loop is processed, we can now see if we have to notify
454   // SDL that we want text based events. This fixes a bug where text based
455   // events would be generated while key presses would still be happening.
456   // See KeyboardInputState for further documentation.
457   if (mInputState != KeyboardInputState::NONE)
458   {
459      // Update text mode toggling.
460      if (mInputState == KeyboardInputState::TEXT_INPUT)
461         SDL_StartTextInput();
462      else
463         SDL_StopTextInput();
464
465      // Done until we need to update it again.
466      mInputState = KeyboardInputState::NONE;
467   }
468}
469
470PlatformWindow * PlatformWindowManagerSDL::getWindowById( WindowId id )
471{
472   // Walk the list and find the matching id, if any.
473   PlatformWindowSDL *win = mWindowListHead;
474   while(win)
475   {
476      if(win->getWindowId() == id)
477         return win;
478
479      win = win->mNextWindow;
480   }
481
482   return NULL; 
483}
484
485PlatformWindow * PlatformWindowManagerSDL::getFirstWindow()
486{
487   return mWindowListHead != NULL ? mWindowListHead : NULL;
488}
489
490PlatformWindow* PlatformWindowManagerSDL::getFocusedWindow()
491{
492   PlatformWindowSDL* window = mWindowListHead;
493   while( window )
494   {
495      if( window->isFocused() )
496         return window;
497
498      window = window->mNextWindow;
499   }
500
501   return NULL;
502}
503
504void PlatformWindowManagerSDL::linkWindow( PlatformWindowSDL *w )
505{
506   w->mNextWindow = mWindowListHead;
507   mWindowListHead = w;
508}
509
510void PlatformWindowManagerSDL::unlinkWindow( PlatformWindowSDL *w )
511{
512   PlatformWindowSDL **walk = &mWindowListHead;
513   while(*walk)
514   {
515      if(*walk != w)
516      {
517         // Advance to next item in list.
518         walk = &(*walk)->mNextWindow;
519         continue;
520      }
521
522      // Got a match - unlink and return.
523      *walk = (*walk)->mNextWindow;
524      return;
525   }
526}
527
528void PlatformWindowManagerSDL::_processCmdLineArgs( const S32 argc, const char **argv )
529{
530   // TODO SDL
531}
532
533void PlatformWindowManagerSDL::lowerCurtain()
534{
535   if(mCurtainWindow)
536      return;
537
538   // TODO SDL
539}
540
541void PlatformWindowManagerSDL::raiseCurtain()
542{
543   if(!mCurtainWindow)
544      return;
545
546   // TODO SDL
547}
548
549void PlatformWindowManagerSDL::updateSDLTextInputState(KeyboardInputState state)
550{
551   // Force update state. This will respond at the end of the event loop.
552   mInputState = state;
553}
554
555void Platform::openFolder(const char* path )
556{
557    AssertFatal(0, "Not Implemented");
558}
559
560void Platform::openFile(const char* path )
561{
562    AssertFatal(0, "Not Implemented");
563}
564
565//------------------------------------------------------------------------------
566
567namespace GL
568{
569   void gglPerformBinds();
570}
571
572void InitWindowingSystem()
573{
574
575}
576
577AFTER_MODULE_INIT(gfx)
578{
579#if !defined(TORQUE_DEDICATED)
580   int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE);
581   AssertFatal(res != -1, avar("SDL error:%s", SDL_GetError()));
582
583   // By default, SDL enables text input. We disable it on initialization, and
584   // we will enable it whenever the time is right.
585   SDL_StopTextInput();
586#endif
587}
588
589