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