sdlWindow.cpp
Engine/source/windowManager/sdl/sdlWindow.cpp
Public Defines
define
IDI_ICON1() 107
define
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
