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 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
