sdlWindowMgr.cpp
Engine/source/windowManager/sdl/sdlWindowMgr.cpp
Namespaces:
namespace
Public Functions
Detailed Description
Public Functions
AFTER_MODULE_INIT(gfx )
InitWindowingSystem()
sdl_CloseSplashWindow(void * hinst)
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 "windowManager/sdl/sdlWindowMgr.h" 25#include "platformSDL/sdlInputManager.h" 26#include "gfx/gfxDevice.h" 27#include "core/util/journal/process.h" 28#include "core/strings/unicode.h" 29#include "gfx/bitmap/gBitmap.h" 30 31#include "SDL.h" 32 33// ------------------------------------------------------------------------ 34 35void sdl_CloseSplashWindow(void* hinst); 36 37#ifdef TORQUE_SDL 38 39PlatformWindowManager * CreatePlatformWindowManager() 40{ 41 return new PlatformWindowManagerSDL(); 42} 43 44#endif 45 46// ------------------------------------------------------------------------ 47 48PlatformWindowManagerSDL::PlatformWindowManagerSDL() 49{ 50 // Register in the process list. 51 mOnProcessSignalSlot.setDelegate( this, &PlatformWindowManagerSDL::_process ); 52 Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER ); 53 54 // Init our list of allocated windows. 55 mWindowListHead = NULL; 56 57 // By default, we have no parent window. 58 mParentWindow = NULL; 59 60 mCurtainWindow = NULL; 61 62 mDisplayWindow = true; 63 mOffscreenRender = false; 64 65 mInputState = KeyboardInputState::NONE; 66} 67 68PlatformWindowManagerSDL::~PlatformWindowManagerSDL() 69{ 70 // Kill all our windows first. 71 while(mWindowListHead) 72 // The destructors update the list, so this works just fine. 73 delete mWindowListHead; 74} 75 76RectI PlatformWindowManagerSDL::getPrimaryDesktopArea() 77{ 78 // Primary is monitor 0 79 return getMonitorRect(0); 80} 81 82Point2I PlatformWindowManagerSDL::getDesktopResolution() 83{ 84 SDL_DisplayMode mode; 85 SDL_GetDesktopDisplayMode(0, &mode); 86 87 // Return Resolution 88 return Point2I(mode.w, mode.h); 89} 90 91S32 PlatformWindowManagerSDL::getDesktopBitDepth() 92{ 93 // Return Bits per Pixel 94 SDL_DisplayMode mode; 95 SDL_GetDesktopDisplayMode(0, &mode); 96 int bbp; 97 unsigned int r,g,b,a; 98 SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a); 99 return bbp; 100} 101 102S32 PlatformWindowManagerSDL::findFirstMatchingMonitor(const char* name) 103{ 104 S32 count = SDL_GetNumVideoDisplays(); 105 for (U32 index = 0; index < count; ++index) 106 { 107 if (dStrstr(name, SDL_GetDisplayName(index)) == name) 108 return index; 109 } 110 111 return 0; 112} 113 114U32 PlatformWindowManagerSDL::getMonitorCount() 115{ 116 S32 monitorCount = SDL_GetNumVideoDisplays(); 117 if (monitorCount < 0) 118 { 119 Con::errorf("SDL_GetNumVideoDisplays() failed: %s", SDL_GetError()); 120 monitorCount = 0; 121 } 122 123 return (U32)monitorCount; 124} 125 126const char* PlatformWindowManagerSDL::getMonitorName(U32 index) 127{ 128 const char* monitorName = SDL_GetDisplayName(index); 129 if (monitorName == NULL) 130 Con::errorf("SDL_GetDisplayName() failed: %s", SDL_GetError()); 131 132 return monitorName; 133} 134 135RectI PlatformWindowManagerSDL::getMonitorRect(U32 index) 136{ 137 SDL_Rect sdlRect; 138 if (0 != SDL_GetDisplayBounds(index, &sdlRect)) 139 { 140 Con::errorf("SDL_GetDisplayBounds() failed: %s", SDL_GetError()); 141 return RectI(0, 0, 0, 0); 142 } 143 144 return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h); 145} 146 147RectI PlatformWindowManagerSDL::getMonitorUsableRect(U32 index) 148{ 149 SDL_Rect sdlRect; 150 if (0 != SDL_GetDisplayUsableBounds(index, &sdlRect)) 151 { 152 Con::errorf("SDL_GetDisplayUsableBounds() failed: %s", SDL_GetError()); 153 return RectI(0, 0, 0, 0); 154 } 155 156 return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h); 157} 158 159U32 PlatformWindowManagerSDL::getMonitorModeCount(U32 monitorIndex) 160{ 161 S32 modeCount = SDL_GetNumDisplayModes(monitorIndex); 162 if (modeCount < 0) 163 { 164 Con::errorf("SDL_GetNumDisplayModes(%d) failed: %s", monitorIndex, SDL_GetError()); 165 modeCount = 0; 166 } 167 168 return (U32)modeCount; 169} 170 171const String PlatformWindowManagerSDL::getMonitorMode(U32 monitorIndex, U32 modeIndex) 172{ 173 SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; 174 if (SDL_GetDisplayMode(monitorIndex, modeIndex, &mode) != 0) 175 { 176 Con::errorf("SDL_GetDisplayMode(%d, %d) failed: %s", monitorIndex, modeIndex, SDL_GetError()); 177 return String::EmptyString; 178 } 179 180 GFXVideoMode vm; 181 vm.resolution.set(mode.w, mode.h); 182 vm.refreshRate = mode.refresh_rate; 183 vm.bitDepth = 32; 184 vm.antialiasLevel = 0; 185 vm.fullScreen = false; 186 vm.wideScreen = false; 187 188 return vm.toString(); 189} 190 191const String PlatformWindowManagerSDL::getMonitorDesktopMode(U32 monitorIndex) 192{ 193 SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 }; 194 if (SDL_GetDesktopDisplayMode(monitorIndex, &mode) != 0) 195 { 196 Con::errorf("SDL_GetDesktopDisplayMode(%d) failed: %s", monitorIndex, SDL_GetError()); 197 return String::EmptyString; 198 } 199 200 GFXVideoMode vm; 201 vm.resolution.set(mode.w, mode.h); 202 vm.refreshRate = mode.refresh_rate; 203 204 int bbp; 205 unsigned int r, g, b, a; 206 SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a); 207 vm.bitDepth = bbp; 208 vm.antialiasLevel = 0; 209 vm.fullScreen = false; 210 vm.wideScreen = ((mode.w / 16) * 9) == mode.h; 211 212 return vm.toString(); 213} 214 215void PlatformWindowManagerSDL::getMonitorRegions(Vector<RectI> ®ions) 216{ 217 SDL_Rect sdlRect; 218 S32 monitorCount = SDL_GetNumVideoDisplays(); 219 for (S32 index = 0; index < monitorCount; ++index) 220 { 221 if (0 == SDL_GetDisplayBounds(index, &sdlRect)) 222 regions.push_back(RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h)); 223 } 224} 225 226void PlatformWindowManagerSDL::getWindows(VectorPtr<PlatformWindow*> &windows) 227{ 228 PlatformWindowSDL *win = mWindowListHead; 229 while(win) 230 { 231 windows.push_back(win); 232 win = win->mNextWindow; 233 } 234} 235 236PlatformWindow *PlatformWindowManagerSDL::createWindow(GFXDevice *device, const GFXVideoMode &mode) 237{ 238 // Do the allocation. 239 PlatformWindowSDL *window = new PlatformWindowSDL(); 240 U32 windowFlags = /*SDL_WINDOW_SHOWN |*/ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN; 241 242 if(GFX->getAdapterType() == OpenGL) 243 windowFlags |= SDL_WINDOW_OPENGL; 244 245 window->mWindowHandle = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mode.resolution.x, mode.resolution.y, windowFlags ); 246 window->mWindowId = SDL_GetWindowID( window->mWindowHandle ); 247 window->mOwningManager = this; 248 mWindowMap[ window->mWindowId ] = window; 249 250 //Now, fetch our window icon, if any 251 Torque::Path iconPath = Torque::Path(Con::getVariable( "$Core::windowIcon" )); 252 253 if (iconPath.getExtension() == String("bmp")) 254 { 255 Con::errorf("Unable to use bmp format images for the window icon. Please use a different format."); 256 } 257 else 258 { 259 Resource<GBitmap> img = GBitmap::load(iconPath); 260 if (img != NULL) 261 { 262 U32 pitch; 263 U32 width = img->getWidth(); 264 bool hasAlpha = img->getHasTransparency(); 265 U32 depth; 266 267 if (hasAlpha) 268 { 269 pitch = 4 * width; 270 depth = 32; 271 } 272 else 273 { 274 pitch = 3 * width; 275 depth = 24; 276 } 277 278 Uint32 rmask, gmask, bmask, amask; 279 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) 280 { 281 S32 shift = hasAlpha ? 8 : 0; 282 rmask = 0xff000000 >> shift; 283 gmask = 0x00ff0000 >> shift; 284 bmask = 0x0000ff00 >> shift; 285 amask = 0x000000ff >> shift; 286 } 287 else 288 { 289 rmask = 0x000000ff; 290 gmask = 0x0000ff00; 291 bmask = 0x00ff0000; 292 amask = hasAlpha ? 0xff000000 : 0; 293 } 294 295 SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(img->getAddress(0, 0), img->getWidth(), img->getHeight(), depth, pitch, rmask, gmask, bmask, amask); 296 297 SDL_SetWindowIcon(window->mWindowHandle, iconSurface); 298 299 SDL_FreeSurface(iconSurface); 300 } 301 } 302 303 if(device) 304 { 305 window->mDevice = device; 306 window->mTarget = device->allocWindowTarget(window); 307 AssertISV(window->mTarget, "PlatformWindowManagerSDL::createWindow - failed to get a window target back from the device."); 308 } 309 else 310 { 311 Con::warnf("PlatformWindowManagerSDL::createWindow - created a window with no device!"); 312 } 313 314 //Set it up for drag-n-drop events 315#ifdef TORQUE_TOOLS 316 SDL_EventState(SDL_DROPBEGIN, SDL_ENABLE); 317 SDL_EventState(SDL_DROPFILE, SDL_ENABLE); 318 SDL_EventState(SDL_DROPCOMPLETE, SDL_ENABLE); 319#endif 320 321 linkWindow(window); 322 323 SDL_SetWindowMinimumSize(window->mWindowHandle, Con::getIntVariable("$Video::minimumXResolution", 1024), 324 Con::getIntVariable("$Video::minimumYResolution", 720)); 325 326 return window; 327} 328 329 330void PlatformWindowManagerSDL::setParentWindow(void* newParent) 331{ 332 333} 334 335void* PlatformWindowManagerSDL::getParentWindow() 336{ 337 return NULL; 338} 339 340void PlatformWindowManagerSDL::_process() 341{ 342 SDL_Event evt; 343 while( SDL_PollEvent(&evt) ) 344 { 345 if (evt.type >= SDL_JOYAXISMOTION && evt.type <= SDL_CONTROLLERDEVICEREMAPPED) 346 { 347 SDLInputManager* mgr = static_cast<SDLInputManager*>(Input::getManager()); 348 if (mgr) 349 mgr->processEvent(evt); 350 continue; 351 } 352 switch(evt.type) 353 { 354 case SDL_QUIT: 355 { 356 PlatformWindowSDL *window = static_cast<PlatformWindowSDL*>( getFirstWindow() ); 357 if(window) 358 window->appEvent.trigger( window->getWindowId(), WindowClose ); 359 break; 360 } 361 362 case SDL_KEYDOWN: 363 case SDL_KEYUP: 364 { 365 PlatformWindowSDL *window = mWindowMap[evt.key.windowID]; 366 if(window) 367 window->_processSDLEvent(evt); 368 break; 369 } 370 371 case SDL_MOUSEWHEEL: 372 { 373 PlatformWindowSDL *window = mWindowMap[evt.wheel.windowID]; 374 if (window) 375 window->_processSDLEvent(evt); 376 break; 377 } 378 379 case SDL_MOUSEMOTION: 380 { 381 PlatformWindowSDL *window = mWindowMap[evt.motion.windowID]; 382 if(window) 383 window->_processSDLEvent(evt); 384 break; 385 } 386 387 case SDL_MOUSEBUTTONDOWN: 388 case SDL_MOUSEBUTTONUP: 389 { 390 PlatformWindowSDL *window = mWindowMap[evt.button.windowID]; 391 if(window) 392 window->_processSDLEvent(evt); 393 break; 394 } 395 396 case SDL_TEXTINPUT: 397 { 398 PlatformWindowSDL *window = mWindowMap[evt.text.windowID]; 399 if(window) 400 window->_processSDLEvent(evt); 401 break; 402 } 403 404 case SDL_WINDOWEVENT: 405 { 406 PlatformWindowSDL *window = mWindowMap[evt.window.windowID]; 407 if(window) 408 window->_processSDLEvent(evt); 409 break; 410 } 411 412 case(SDL_DROPBEGIN): 413 { 414 if (!Con::isFunction("onDropBegin")) 415 break; 416 417 Con::executef("onDropBegin"); 418 } 419 420 case (SDL_DROPFILE): 421 { 422 // In case if dropped file 423 if (!Con::isFunction("onDropFile")) 424 break; 425 426 char* fileName = evt.drop.file; 427 428 if (!Platform::isDirectory(fileName) && !Platform::isFile(fileName)) 429 break; 430 431 Con::executef("onDropFile", StringTable->insert(fileName)); 432 433 SDL_free(fileName); // Free dropped_filedir memory 434 break; 435 } 436 437 case(SDL_DROPCOMPLETE): 438 { 439 if (Con::isFunction("onDropEnd")) 440 Con::executef("onDropEnd"); 441 break; 442 } 443 444 default: 445 { 446#ifdef TORQUE_DEBUG 447 Con::warnf("Unhandled SDL input event: 0x%04x", evt.type); 448#endif 449 } 450 } 451 } 452 453 // After the event loop is processed, we can now see if we have to notify 454 // SDL that we want text based events. This fixes a bug where text based 455 // events would be generated while key presses would still be happening. 456 // See KeyboardInputState for further documentation. 457 if (mInputState != KeyboardInputState::NONE) 458 { 459 // Update text mode toggling. 460 if (mInputState == KeyboardInputState::TEXT_INPUT) 461 SDL_StartTextInput(); 462 else 463 SDL_StopTextInput(); 464 465 // Done until we need to update it again. 466 mInputState = KeyboardInputState::NONE; 467 } 468} 469 470PlatformWindow * PlatformWindowManagerSDL::getWindowById( WindowId id ) 471{ 472 // Walk the list and find the matching id, if any. 473 PlatformWindowSDL *win = mWindowListHead; 474 while(win) 475 { 476 if(win->getWindowId() == id) 477 return win; 478 479 win = win->mNextWindow; 480 } 481 482 return NULL; 483} 484 485PlatformWindow * PlatformWindowManagerSDL::getFirstWindow() 486{ 487 return mWindowListHead != NULL ? mWindowListHead : NULL; 488} 489 490PlatformWindow* PlatformWindowManagerSDL::getFocusedWindow() 491{ 492 PlatformWindowSDL* window = mWindowListHead; 493 while( window ) 494 { 495 if( window->isFocused() ) 496 return window; 497 498 window = window->mNextWindow; 499 } 500 501 return NULL; 502} 503 504void PlatformWindowManagerSDL::linkWindow( PlatformWindowSDL *w ) 505{ 506 w->mNextWindow = mWindowListHead; 507 mWindowListHead = w; 508} 509 510void PlatformWindowManagerSDL::unlinkWindow( PlatformWindowSDL *w ) 511{ 512 PlatformWindowSDL **walk = &mWindowListHead; 513 while(*walk) 514 { 515 if(*walk != w) 516 { 517 // Advance to next item in list. 518 walk = &(*walk)->mNextWindow; 519 continue; 520 } 521 522 // Got a match - unlink and return. 523 *walk = (*walk)->mNextWindow; 524 return; 525 } 526} 527 528void PlatformWindowManagerSDL::_processCmdLineArgs( const S32 argc, const char **argv ) 529{ 530 // TODO SDL 531} 532 533void PlatformWindowManagerSDL::lowerCurtain() 534{ 535 if(mCurtainWindow) 536 return; 537 538 // TODO SDL 539} 540 541void PlatformWindowManagerSDL::raiseCurtain() 542{ 543 if(!mCurtainWindow) 544 return; 545 546 // TODO SDL 547} 548 549void PlatformWindowManagerSDL::updateSDLTextInputState(KeyboardInputState state) 550{ 551 // Force update state. This will respond at the end of the event loop. 552 mInputState = state; 553} 554 555void Platform::openFolder(const char* path ) 556{ 557 AssertFatal(0, "Not Implemented"); 558} 559 560void Platform::openFile(const char* path ) 561{ 562 AssertFatal(0, "Not Implemented"); 563} 564 565//------------------------------------------------------------------------------ 566 567namespace GL 568{ 569 void gglPerformBinds(); 570} 571 572void InitWindowingSystem() 573{ 574 575} 576 577AFTER_MODULE_INIT(gfx) 578{ 579#if !defined(TORQUE_DEDICATED) 580 int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE); 581 AssertFatal(res != -1, avar("SDL error:%s", SDL_GetError())); 582 583 // By default, SDL enables text input. We disable it on initialization, and 584 // we will enable it whenever the time is right. 585 SDL_StopTextInput(); 586#endif 587} 588 589