sdlWindow.cpp

Engine/source/windowManager/sdl/sdlWindow.cpp

More...

Public Defines

define
IDI_ICON1() 107

Detailed Description

Public Defines

IDI_ICON1() 107
SCREENSAVER_QUERY_DENY() 0
  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 "math/mMath.h"
 25#include "gfx/gfxStructs.h"
 26
 27#include "windowManager/sdl/sdlWindow.h"
 28#include "windowManager/sdl/sdlWindowMgr.h"
 29#include "windowManager/sdl/sdlCursorController.h"
 30#include "platformSDL/sdlInput.h"
 31#include "platform/platformInput.h"
 32
 33#include "gfx/gfxDevice.h"
 34
 35#ifdef TORQUE_OS_LINUX
 36#define SDL_VIDEO_DRIVER_X11  // TODO SDL
 37#endif
 38
 39#include "SDL.h"
 40#include "SDL_syswm.h"
 41
 42#define SCREENSAVER_QUERY_DENY 0 // Disable screensaver
 43
 44#ifndef IDI_ICON1 
 45#define IDI_ICON1 107
 46#endif
 47
 48namespace 
 49{
 50   U32 getTorqueModFromSDL(U16 mod)
 51   {
 52      U32 ret = 0;
 53
 54      if (mod & KMOD_LSHIFT)
 55      {
 56         ret |= SI_LSHIFT;
 57         ret |= SI_SHIFT;
 58      }
 59
 60      if (mod & KMOD_RSHIFT)
 61      {
 62         ret |= SI_RSHIFT;
 63         ret |= SI_SHIFT;
 64      }
 65
 66      if (mod & KMOD_LCTRL)
 67      {
 68         ret |= SI_LCTRL;
 69         ret |= SI_CTRL;
 70      }
 71
 72      if (mod & KMOD_RCTRL)
 73      {
 74         ret |= SI_RCTRL;
 75         ret |= SI_CTRL;
 76      }
 77
 78      if (mod & KMOD_LALT)
 79      {
 80         ret |= SI_LALT;
 81         ret |= SI_ALT;
 82      }
 83
 84      if (mod & KMOD_RALT)
 85      {
 86         ret |= SI_RALT;
 87         ret |= SI_ALT;
 88      }
 89
 90      return ret;
 91   }
 92}
 93
 94PlatformWindowSDL::PlatformWindowSDL():
 95mOwningManager(NULL),
 96mNextWindow(NULL),
 97mWindowHandle(NULL),
 98mOldParent(NULL),
 99mDevice(NULL),
100mTarget(NULL),
101mPosition(0,0),
102mMouseLocked(false),
103mShouldLockMouse(false),
104mSuppressReset(false),
105mMenuHandle(NULL),
106mClosing(false)
107{
108   mCursorController = new PlatformCursorControllerSDL( this );
109
110   mVideoMode.bitDepth = 32;
111   mVideoMode.fullScreen = false;
112   mVideoMode.refreshRate = 60;
113   mVideoMode.resolution.set(800,600);
114}
115
116PlatformWindowSDL::~PlatformWindowSDL()
117{
118   // delete our sdl handle..
119   SDL_DestroyWindow(mWindowHandle);
120
121   // unlink ourselves from the window list...
122   AssertFatal(mOwningManager, "PlatformWindowSDL::~PlatformWindowSDL - orphan window, cannot unlink!");
123   mOwningManager->unlinkWindow(this);
124}
125
126GFXDevice * PlatformWindowSDL::getGFXDevice()
127{
128   return mDevice;
129}
130
131GFXWindowTarget * PlatformWindowSDL::getGFXTarget()
132{
133   return mTarget;
134}
135
136const GFXVideoMode & PlatformWindowSDL::getVideoMode()
137{
138   return mVideoMode;
139}
140
141void* PlatformWindowSDL::getSystemWindow(const WindowSystem system)
142{
143     SDL_SysWMinfo info;
144     SDL_VERSION(&info.version);
145     SDL_GetWindowWMInfo(mWindowHandle,&info);     
146
147#ifdef TORQUE_OS_WIN
148     if( system == WindowSystem_Windows && info.subsystem == SDL_SYSWM_WINDOWS)
149        return info.info.win.window;
150#endif
151
152#if defined(TORQUE_OS_LINUX)
153     if( system == WindowSystem_X11 && info.subsystem == SDL_SYSWM_X11)
154        return (void*)info.info.x11.window;
155#endif
156
157    AssertFatal(0, "");
158    return NULL;
159}
160
161void PlatformWindowSDL::_setVideoMode( const GFXVideoMode &mode )
162{
163   mVideoMode = mode;
164   mSuppressReset = true;
165   S32 newDisplay = Con::getIntVariable("pref::Video::deviceId", 0);
166
167   // Set our window to have the right style based on the mode
168   if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender)
169   {
170      SDL_Rect rect_sdl;
171      // Move the window onto the correct monitor before setting fullscreen
172      if (0 == SDL_GetDisplayBounds(newDisplay, &rect_sdl))
173      {
174         SDL_SetWindowPosition(mWindowHandle, rect_sdl.x, rect_sdl.y);
175      }
176
177      setSize(mode.resolution);
178
179      SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
180
181      // When switching to Fullscreen, reset device after setting style
182      if(mTarget.isValid())
183         mTarget->resetMode();
184   }
185   else
186   {
187      // Reset device *first*, so that when we call setSize() and let it
188      // access the monitor settings, it won't end up with our fullscreen
189      // geometry that is just about to change.
190
191      if(mTarget.isValid())
192         mTarget->resetMode();
193
194      if (!mOffscreenRender)
195      {
196         SDL_SetWindowFullscreen( mWindowHandle, 0);
197      }
198
199      // Restore the window to it's original size/position before applying changes
200      SDL_RestoreWindow(mWindowHandle);
201
202      // pref::Video::deviceMode values 0-windowed, 1-borderless, 2-fullscreen
203      bool hasBorder = (0 == Con::getIntVariable("pref::Video::deviceMode", 0));
204      SDL_SetWindowBordered(mWindowHandle, hasBorder ? SDL_TRUE : SDL_FALSE);
205      setSize(mode.resolution);
206      SDL_SetWindowPosition(mWindowHandle, SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay), SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay));
207      if (hasBorder && Con::getBoolVariable("pref::Video::isMaximized", false))
208         SDL_MaximizeWindow(mWindowHandle);
209   }
210
211   getScreenResChangeSignal().trigger(this, true);
212   mSuppressReset = false;
213}
214
215bool PlatformWindowSDL::clearFullscreen()
216{
217   return true;
218}
219
220bool PlatformWindowSDL::isFullscreen()
221{   
222   U32 flags = SDL_GetWindowFlags( mWindowHandle );   
223   if( flags & SDL_WINDOW_FULLSCREEN || flags & SDL_WINDOW_FULLSCREEN_DESKTOP )
224      return true;
225
226   return false;
227}
228
229void PlatformWindowSDL::_setFullscreen(const bool fullscreen)
230{
231   if( isFullscreen() )
232      return;
233
234   if(fullscreen && !mOffscreenRender)
235   {
236      Con::printf("PlatformWindowSDL::setFullscreen (full) enter");
237      SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
238   }
239   else
240   {
241      Con::printf("PlatformWindowSDL::setFullscreen (windowed) enter");
242      if (!mOffscreenRender)
243      {
244         SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN_DESKTOP);
245      }
246
247      setSize(mVideoMode.resolution);
248
249   }
250   Con::printf("PlatformWindowSDL::setFullscreen exit");   
251}
252
253bool PlatformWindowSDL::setCaption( const char *cap )
254{
255   SDL_SetWindowTitle(mWindowHandle, cap);
256   return true;
257}
258
259const char * PlatformWindowSDL::getCaption()
260{
261   return StringTable->insert( SDL_GetWindowTitle(mWindowHandle) );
262}
263
264void PlatformWindowSDL::setFocus()
265{
266   SDL_RaiseWindow(mWindowHandle);
267}
268
269void PlatformWindowSDL::setClientExtent( const Point2I newExtent )
270{
271   Point2I oldExtent = getClientExtent();
272   if (oldExtent == newExtent)
273      return;   
274
275   SDL_SetWindowSize(mWindowHandle, newExtent.x, newExtent.y);
276}
277
278const Point2I PlatformWindowSDL::getClientExtent()
279{
280   // Fetch Client Rect from Windows
281   Point2I size;
282   SDL_GetWindowSize(mWindowHandle, &size.x, &size.y);
283
284   return size;
285}
286
287void PlatformWindowSDL::setBounds( const RectI &newBounds )
288{
289   // TODO SDL
290}
291
292const RectI PlatformWindowSDL::getBounds() const
293{
294   // TODO SDL
295   return RectI(0, 0, 0, 0);   
296}
297
298void PlatformWindowSDL::setPosition( const Point2I newPosition )
299{
300   SDL_SetWindowPosition( mWindowHandle, newPosition.x, newPosition.y );
301}
302
303const Point2I PlatformWindowSDL::getPosition()
304{
305   Point2I position;
306   SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
307
308   // Return position
309   return position;
310}
311
312Point2I PlatformWindowSDL::clientToScreen( const Point2I& pos )
313{
314   Point2I position;
315   SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
316   return pos + position;
317}
318
319Point2I PlatformWindowSDL::screenToClient( const Point2I& pos )
320{
321   Point2I position;
322   SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
323   return pos - position;
324}
325
326void PlatformWindowSDL::centerWindow()
327{
328   int sizeX, sizeY;
329   SDL_GetWindowSize(mWindowHandle, &sizeX, &sizeY);
330
331   SDL_DisplayMode mode;
332   SDL_GetDesktopDisplayMode(0, &mode);
333   
334   U32 posX = (mode.w/2) - (sizeX/2);
335   U32 posY = (mode.h/2) - (sizeY/2);
336
337   SDL_SetWindowPosition( mWindowHandle, posX, posY);
338}
339
340bool PlatformWindowSDL::setSize( const Point2I &newSize )
341{
342   SDL_SetWindowSize(mWindowHandle, newSize.x, newSize.y);
343   return true;
344}
345
346bool PlatformWindowSDL::isOpen()
347{
348   return mWindowHandle;
349}
350
351bool PlatformWindowSDL::isVisible()
352{
353   // Is the window open and visible, ie. not minimized?
354   if(!mWindowHandle)
355      return false;
356
357   if (mOffscreenRender)
358      return true;
359
360   U32 flags = SDL_GetWindowFlags( mWindowHandle );   
361   if( flags & SDL_WINDOW_SHOWN)
362      return true;
363
364   return false;
365}
366
367bool PlatformWindowSDL::isFocused()
368{
369   if (mOffscreenRender)
370      return true;
371
372   U32 flags = SDL_GetWindowFlags( mWindowHandle );   
373   if( flags & SDL_WINDOW_INPUT_FOCUS || flags & SDL_WINDOW_INPUT_GRABBED || flags & SDL_WINDOW_MOUSE_FOCUS )
374      return true;
375
376   return false;
377}
378
379bool PlatformWindowSDL::isMinimized()
380{
381   if (mOffscreenRender)
382      return false;
383
384   U32 flags = SDL_GetWindowFlags( mWindowHandle );   
385   if( flags & SDL_WINDOW_MINIMIZED)
386      return true;
387
388    return false;
389}
390
391bool PlatformWindowSDL::isMaximized()
392{
393   if (mOffscreenRender)
394      return true;
395
396   U32 flags = SDL_GetWindowFlags( mWindowHandle );   
397   if( flags & SDL_WINDOW_MAXIMIZED)
398      return true;
399
400    return false;
401}
402
403WindowId PlatformWindowSDL::getWindowId()
404{
405   return mWindowId;
406}
407
408void PlatformWindowSDL::minimize()
409{
410   if (mOffscreenRender)
411      return;
412
413   SDL_MinimizeWindow( mWindowHandle );
414}
415
416void PlatformWindowSDL::maximize()
417{
418   if (mOffscreenRender)
419      return;
420
421   SDL_MaximizeWindow( mWindowHandle );
422}
423
424void PlatformWindowSDL::restore()
425{
426   if (mOffscreenRender)
427      return;
428
429   SDL_RestoreWindow( mWindowHandle );
430}
431
432void PlatformWindowSDL::hide()
433{
434   if (mOffscreenRender)
435      return;
436
437   SDL_HideWindow( mWindowHandle );
438}
439
440void PlatformWindowSDL::show()
441{
442   if (mOffscreenRender)
443      return;
444
445   SDL_ShowWindow( mWindowHandle );
446}
447
448void PlatformWindowSDL::close()
449{
450   delete this;
451}
452
453void PlatformWindowSDL::defaultRender()
454{
455   // TODO SDL
456}
457
458void PlatformWindowSDL::_triggerMouseLocationNotify(const SDL_Event& evt)
459{
460   U32 mods = getTorqueModFromSDL(SDL_GetModState());
461
462   if(!mMouseLocked)
463      mouseEvent.trigger(getWindowId(), mods, evt.motion.x, evt.motion.y, false);
464   else
465      mouseEvent.trigger(getWindowId(), mods, evt.motion.xrel, evt.motion.yrel, true);
466}
467
468void PlatformWindowSDL::_triggerMouseWheelNotify(const SDL_Event& evt)
469{
470   U32 mods = getTorqueModFromSDL(SDL_GetModState());
471   S32 wheelDelta = Con::getIntVariable("$pref::Input::MouseWheelSpeed", 120);
472   wheelEvent.trigger(getWindowId(), mods, evt.wheel.x * wheelDelta, evt.wheel.y * wheelDelta);
473}
474
475void PlatformWindowSDL::_triggerMouseButtonNotify(const SDL_Event& event)
476{
477   S32 action = (event.type == SDL_MOUSEBUTTONDOWN) ? SI_MAKE : SI_BREAK;
478   S32 button = -1;
479
480   switch (event.button.button)
481   {
482      case SDL_BUTTON_LEFT:
483         button = 0;
484         break;
485      case SDL_BUTTON_RIGHT:
486         button = 1;
487         break;
488      case SDL_BUTTON_MIDDLE:
489         button = 2;
490         break;
491      case SDL_BUTTON_X1:
492         button = 3;
493         break;
494      case SDL_BUTTON_X2:
495         button = 4;
496         break;
497      default:
498         return;
499   }
500   
501   U32 mod = getTorqueModFromSDL( SDL_GetModState() );
502   buttonEvent.trigger(getWindowId(), mod, action, button );
503}
504
505void PlatformWindowSDL::_triggerKeyNotify(const SDL_Event& evt)
506{
507   U32 inputAction = IA_MAKE;
508   SDL_Keysym tKey = evt.key.keysym;
509
510   if(evt.type == SDL_KEYUP)
511   {
512      inputAction = IA_BREAK;
513   }
514
515   if(evt.key.repeat)
516   {
517      inputAction = IA_REPEAT;
518   }
519
520   U32 torqueModifiers = getTorqueModFromSDL(evt.key.keysym.mod);
521   U32 torqueKey = KeyMapSDL::getTorqueScanCodeFromSDL(tKey.scancode);
522   if(tKey.scancode)
523   {
524      keyEvent.trigger(getWindowId(), torqueModifiers, inputAction, torqueKey);
525      //Con::printf("Key %d : %d", tKey.sym, inputAction);
526
527      if (inputAction == IA_MAKE && SDL_IsTextInputActive())
528      {
529         // We have to check if we already have a first responder active.
530         // We don't want to type the character if it actually creates another responder!
531         if (mWindowInputGenerator->lastKeyWasGlobalActionMap())
532         {
533            // Turn off Text input, and the next frame turn it back on. This tells SDL
534            // to not generate a text event for this global action map key.
535            SDL_StopTextInput();
536            mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::TEXT_INPUT);
537         }
538      }
539   }
540}
541
542void PlatformWindowSDL::_triggerTextNotify(const SDL_Event& evt)
543{
544    U32 mod = getTorqueModFromSDL( SDL_GetModState() );
545   
546   if( !evt.text.text[1] ) // get a char
547   {
548      U16 wchar = evt.text.text[0];
549      charEvent.trigger(getWindowId(), mod, wchar );
550      //Con::printf("Char: %c", wchar);
551      return;
552   }
553   else // get a wchar string
554   {
555      const U32 len = strlen(evt.text.text);
556      U16 wchar[16] = {};
557      dMemcpy(wchar, evt.text.text, sizeof(char)*len);
558
559      for(int i = 0; i < 16; ++i)
560      {
561         if( !wchar[i] )
562            return;
563
564         charEvent.trigger(getWindowId(), mod, wchar[i] );
565      }
566   }
567}
568
569void PlatformWindowSDL::_updateMonitorFromMove(const SDL_Event& evt)
570{
571   SDL_Rect sdlRect;
572   S32 monitorCount = SDL_GetNumVideoDisplays();
573   for (S32 index = 0; index < monitorCount; ++index)
574   {
575      if (0 == SDL_GetDisplayBounds(index, &sdlRect))
576      {
577         if ((evt.window.data1 >= sdlRect.x) && (evt.window.data1 < (sdlRect.x + sdlRect.w)) &&
578            (evt.window.data2 >= sdlRect.y) && (evt.window.data2 < (sdlRect.y + sdlRect.h)))
579         {
580            Con::setIntVariable("pref::Video::deviceId", index);
581            return;
582         }
583      }
584   }
585}
586
587void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
588{
589   switch(evt.type)
590   {        
591      case SDL_KEYDOWN:
592      case SDL_KEYUP:
593      {
594         _triggerKeyNotify(evt);
595         break;
596      }
597
598      case SDL_TEXTINPUT:
599      {         
600         _triggerTextNotify(evt);
601         break;
602      }
603
604      case SDL_MOUSEWHEEL:
605      {
606         _triggerMouseWheelNotify(evt);
607         break;
608      }
609
610      case SDL_MOUSEMOTION:
611      {
612         _triggerMouseLocationNotify(evt);
613         break;
614      }
615      case SDL_MOUSEBUTTONDOWN:
616      case SDL_MOUSEBUTTONUP:
617      {
618         _triggerMouseButtonNotify(evt);
619         break;
620      }
621
622      case SDL_WINDOWEVENT:
623      {
624         if (!mClosing)
625         {
626            switch (evt.window.event)
627            {
628            case SDL_WINDOWEVENT_FOCUS_GAINED:
629               appEvent.trigger(getWindowId(), GainFocus);
630               break;
631            case SDL_WINDOWEVENT_FOCUS_LOST:
632               appEvent.trigger(getWindowId(), LoseFocus);
633               break;
634            case SDL_WINDOWEVENT_MOVED:
635            {
636               _updateMonitorFromMove(evt);
637               break;
638            }
639            case SDL_WINDOWEVENT_RESIZED:
640            {
641               int width, height;
642               SDL_GetWindowSize(mWindowHandle, &width, &height);
643               mVideoMode.resolution.set(width, height);
644               getGFXTarget()->resetMode();
645               resizeEvent.trigger(getWindowId(), width, height);
646               getScreenResChangeSignal().trigger(this, true);
647               break;
648            }
649            case SDL_WINDOWEVENT_CLOSE:
650            {
651               appEvent.trigger(getWindowId(), WindowClose);
652               mClosing = true;
653            }
654            case SDL_WINDOWEVENT_MINIMIZED:
655               break;
656            case SDL_WINDOWEVENT_MAXIMIZED:
657               Con::setBoolVariable("pref::Video::isMaximized", true);
658               break;
659            case SDL_WINDOWEVENT_RESTORED:
660               Con::setBoolVariable("pref::Video::isMaximized", false);
661               break;
662
663            default:
664               break;
665            }
666         }
667      }
668   }
669
670}
671
672//-----------------------------------------------------------------------------
673// Mouse Locking
674//-----------------------------------------------------------------------------
675
676void PlatformWindowSDL::setMouseLocked( bool enable )
677{
678   if (mOffscreenRender)
679      return;
680
681   mMouseLocked = enable;
682   
683   SDL_SetWindowGrab( mWindowHandle, SDL_bool(enable) );
684   SDL_SetRelativeMouseMode( SDL_bool(enable) );
685}
686
687const UTF16 *PlatformWindowSDL::getWindowClassName()
688{
689   // TODO SDL
690   static String str("WindowClassName");
691   return str.utf16();
692}
693
694const UTF16 *PlatformWindowSDL::getCurtainWindowClassName()
695{
696   // TODO SDL
697   static String str("CurtainWindowClassName");
698   return str.utf16();
699}
700
701void PlatformWindowSDL::setKeyboardTranslation(const bool enabled)
702{
703   mEnableKeyboardTranslation = enabled;
704
705   // Flag for update. Let SDL know what kind of input state we are changing to.
706   if (enabled)
707      mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::TEXT_INPUT);
708   else
709      mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::RAW_INPUT);
710}
711