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