123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "windowManager/sdl/sdlWindowMgr.h"
- #include "platformSDL/sdlInputManager.h"
- #include "platform/platformVolume.h"
- #include "core/util/path.h"
- #include "gfx/gfxDevice.h"
- #include "core/util/journal/process.h"
- #include "core/strings/unicode.h"
- #include "gfx/bitmap/gBitmap.h"
- #include "SDL.h"
- // ------------------------------------------------------------------------
- void sdl_CloseSplashWindow(void* hinst);
- #ifdef TORQUE_SDL
- PlatformWindowManager * CreatePlatformWindowManager()
- {
- return new PlatformWindowManagerSDL();
- }
- #endif
- // ------------------------------------------------------------------------
- PlatformWindowManagerSDL::PlatformWindowManagerSDL()
- {
- // Register in the process list.
- mOnProcessSignalSlot.setDelegate( this, &PlatformWindowManagerSDL::_process );
- Process::notify( mOnProcessSignalSlot, PROCESS_INPUT_ORDER );
- // Init our list of allocated windows.
- mWindowListHead = NULL;
- // By default, we have no parent window.
- mParentWindow = NULL;
- mCurtainWindow = NULL;
- mDisplayWindow = true;
- mOffscreenRender = false;
- mInputState = KeyboardInputState::NONE;
- }
- PlatformWindowManagerSDL::~PlatformWindowManagerSDL()
- {
- // Kill all our windows first.
- while(mWindowListHead)
- // The destructors update the list, so this works just fine.
- delete mWindowListHead;
- }
- RectI PlatformWindowManagerSDL::getPrimaryDesktopArea()
- {
- // Primary is monitor 0
- return getMonitorRect(0);
- }
- Point2I PlatformWindowManagerSDL::getDesktopResolution()
- {
- SDL_DisplayMode mode;
- SDL_GetDesktopDisplayMode(0, &mode);
- // Return Resolution
- return Point2I(mode.w, mode.h);
- }
- S32 PlatformWindowManagerSDL::getDesktopBitDepth()
- {
- // Return Bits per Pixel
- SDL_DisplayMode mode;
- SDL_GetDesktopDisplayMode(0, &mode);
- int bbp;
- unsigned int r,g,b,a;
- SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
- return bbp;
- }
- S32 PlatformWindowManagerSDL::findFirstMatchingMonitor(const char* name)
- {
- S32 count = SDL_GetNumVideoDisplays();
- for (U32 index = 0; index < count; ++index)
- {
- if (dStrstr(name, SDL_GetDisplayName(index)) == name)
- return index;
- }
- return 0;
- }
- U32 PlatformWindowManagerSDL::getMonitorCount()
- {
- S32 monitorCount = SDL_GetNumVideoDisplays();
- if (monitorCount < 0)
- {
- Con::errorf("SDL_GetNumVideoDisplays() failed: %s", SDL_GetError());
- monitorCount = 0;
- }
- return (U32)monitorCount;
- }
- const char* PlatformWindowManagerSDL::getMonitorName(U32 index)
- {
- const char* monitorName = SDL_GetDisplayName(index);
- if (monitorName == NULL)
- Con::errorf("SDL_GetDisplayName() failed: %s", SDL_GetError());
- return monitorName;
- }
- RectI PlatformWindowManagerSDL::getMonitorRect(U32 index)
- {
- SDL_Rect sdlRect;
- if (0 != SDL_GetDisplayBounds(index, &sdlRect))
- {
- Con::errorf("SDL_GetDisplayBounds() failed: %s", SDL_GetError());
- return RectI(0, 0, 0, 0);
- }
- return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
- }
- RectI PlatformWindowManagerSDL::getMonitorUsableRect(U32 index)
- {
- SDL_Rect sdlRect;
- if (0 != SDL_GetDisplayUsableBounds(index, &sdlRect))
- {
- Con::errorf("SDL_GetDisplayUsableBounds() failed: %s", SDL_GetError());
- return RectI(0, 0, 0, 0);
- }
- return RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h);
- }
- U32 PlatformWindowManagerSDL::getMonitorModeCount(U32 monitorIndex)
- {
- S32 modeCount = SDL_GetNumDisplayModes(monitorIndex);
- if (modeCount < 0)
- {
- Con::errorf("SDL_GetNumDisplayModes(%d) failed: %s", monitorIndex, SDL_GetError());
- modeCount = 0;
- }
- return (U32)modeCount;
- }
- const String PlatformWindowManagerSDL::getMonitorMode(U32 monitorIndex, U32 modeIndex)
- {
- SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
- if (SDL_GetDisplayMode(monitorIndex, modeIndex, &mode) != 0)
- {
- Con::errorf("SDL_GetDisplayMode(%d, %d) failed: %s", monitorIndex, modeIndex, SDL_GetError());
- return String::EmptyString;
- }
- GFXVideoMode vm;
- vm.resolution.set(mode.w, mode.h);
- vm.refreshRate = mode.refresh_rate;
- vm.bitDepth = 32;
- vm.antialiasLevel = 0;
- vm.fullScreen = false;
- vm.wideScreen = false;
- return vm.toString();
- }
- const String PlatformWindowManagerSDL::getMonitorDesktopMode(U32 monitorIndex)
- {
- SDL_DisplayMode mode = { SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0 };
- if (SDL_GetDesktopDisplayMode(monitorIndex, &mode) != 0)
- {
- Con::errorf("SDL_GetDesktopDisplayMode(%d) failed: %s", monitorIndex, SDL_GetError());
- return String::EmptyString;
- }
- GFXVideoMode vm;
- vm.resolution.set(mode.w, mode.h);
- vm.refreshRate = mode.refresh_rate;
- int bbp;
- unsigned int r, g, b, a;
- SDL_PixelFormatEnumToMasks(mode.format, &bbp, &r, &g, &b, &a);
- vm.bitDepth = bbp;
- vm.antialiasLevel = 0;
- vm.fullScreen = false;
- vm.wideScreen = ((mode.w / 16) * 9) == mode.h;
- return vm.toString();
- }
- void PlatformWindowManagerSDL::getMonitorRegions(Vector<RectI> ®ions)
- {
- SDL_Rect sdlRect;
- S32 monitorCount = SDL_GetNumVideoDisplays();
- for (S32 index = 0; index < monitorCount; ++index)
- {
- if (0 == SDL_GetDisplayBounds(index, &sdlRect))
- regions.push_back(RectI(sdlRect.x, sdlRect.y, sdlRect.w, sdlRect.h));
- }
- }
- void PlatformWindowManagerSDL::getWindows(VectorPtr<PlatformWindow*> &windows)
- {
- PlatformWindowSDL *win = mWindowListHead;
- while(win)
- {
- windows.push_back(win);
- win = win->mNextWindow;
- }
- }
- PlatformWindow *PlatformWindowManagerSDL::createWindow(GFXDevice *device, const GFXVideoMode &mode)
- {
- // Do the allocation.
- PlatformWindowSDL *window = new PlatformWindowSDL();
- U32 windowFlags = /*SDL_WINDOW_SHOWN |*/ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN;
- if(GFX->getAdapterType() == OpenGL)
- windowFlags |= SDL_WINDOW_OPENGL;
- window->mWindowHandle = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, mode.resolution.x, mode.resolution.y, windowFlags );
- window->mWindowId = SDL_GetWindowID( window->mWindowHandle );
- window->mOwningManager = this;
- mWindowMap[ window->mWindowId ] = window;
- //Now, fetch our window icon, if any
- Torque::Path iconPath = Torque::Path(Con::getVariable( "$Core::windowIcon" ));
- if (iconPath.getExtension() == String("bmp"))
- {
- Con::errorf("Unable to use bmp format images for the window icon. Please use a different format.");
- }
- else
- {
- Resource<GBitmap> img = GBitmap::load(iconPath);
- if (img != NULL)
- {
- U32 pitch;
- U32 width = img->getWidth();
- bool hasAlpha = img->getHasTransparency();
- U32 depth;
- if (hasAlpha)
- {
- pitch = 4 * width;
- depth = 32;
- }
- else
- {
- pitch = 3 * width;
- depth = 24;
- }
- Uint32 rmask, gmask, bmask, amask;
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- {
- S32 shift = hasAlpha ? 8 : 0;
- rmask = 0xff000000 >> shift;
- gmask = 0x00ff0000 >> shift;
- bmask = 0x0000ff00 >> shift;
- amask = 0x000000ff >> shift;
- }
- else
- {
- rmask = 0x000000ff;
- gmask = 0x0000ff00;
- bmask = 0x00ff0000;
- amask = hasAlpha ? 0xff000000 : 0;
- }
- SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(img->getAddress(0, 0), img->getWidth(), img->getHeight(), depth, pitch, rmask, gmask, bmask, amask);
- SDL_SetWindowIcon(window->mWindowHandle, iconSurface);
- SDL_FreeSurface(iconSurface);
- }
- }
- if(device)
- {
- window->mDevice = device;
- window->mTarget = device->allocWindowTarget(window);
- AssertISV(window->mTarget, "PlatformWindowManagerSDL::createWindow - failed to get a window target back from the device.");
- }
- else
- {
- Con::warnf("PlatformWindowManagerSDL::createWindow - created a window with no device!");
- }
- //Set it up for drag-n-drop events
- #ifdef TORQUE_TOOLS
- SDL_EventState(SDL_DROPBEGIN, SDL_ENABLE);
- SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
- SDL_EventState(SDL_DROPCOMPLETE, SDL_ENABLE);
- #endif
- linkWindow(window);
- SDL_SetWindowMinimumSize(window->mWindowHandle, Con::getIntVariable("$Video::minimumXResolution", 1024),
- Con::getIntVariable("$Video::minimumYResolution", 720));
- return window;
- }
- void PlatformWindowManagerSDL::setParentWindow(void* newParent)
- {
-
- }
- void* PlatformWindowManagerSDL::getParentWindow()
- {
- return NULL;
- }
- void PlatformWindowManagerSDL::_process()
- {
- SDL_Event evt;
- while( SDL_PollEvent(&evt) )
- {
- if (evt.type >= SDL_JOYAXISMOTION && evt.type <= SDL_CONTROLLERDEVICEREMAPPED)
- {
- SDLInputManager* mgr = static_cast<SDLInputManager*>(Input::getManager());
- if (mgr)
- mgr->processEvent(evt);
- continue;
- }
- switch(evt.type)
- {
- case SDL_QUIT:
- {
- PlatformWindowSDL *window = static_cast<PlatformWindowSDL*>( getFirstWindow() );
- if(window)
- window->appEvent.trigger( window->getWindowId(), WindowClose );
- break;
- }
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- {
- PlatformWindowSDL *window = mWindowMap[evt.key.windowID];
- if(window)
- window->_processSDLEvent(evt);
- break;
- }
- case SDL_MOUSEWHEEL:
- {
- PlatformWindowSDL *window = mWindowMap[evt.wheel.windowID];
- if (window)
- window->_processSDLEvent(evt);
- break;
- }
- case SDL_MOUSEMOTION:
- {
- PlatformWindowSDL *window = mWindowMap[evt.motion.windowID];
- if(window)
- window->_processSDLEvent(evt);
- break;
- }
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- {
- PlatformWindowSDL *window = mWindowMap[evt.button.windowID];
- if(window)
- window->_processSDLEvent(evt);
- break;
- }
- case SDL_TEXTINPUT:
- {
- PlatformWindowSDL *window = mWindowMap[evt.text.windowID];
- if(window)
- window->_processSDLEvent(evt);
- break;
- }
- case SDL_WINDOWEVENT:
- {
- PlatformWindowSDL *window = mWindowMap[evt.window.windowID];
- if(window)
- window->_processSDLEvent(evt);
- break;
- }
- case(SDL_DROPBEGIN):
- {
- if (!Con::isFunction("onDropBegin"))
- break;
- Con::executef("onDropBegin");
- }
- case (SDL_DROPFILE):
- {
- // In case if dropped file
- if (!Con::isFunction("onDropFile"))
- break;
- char* fileName = evt.drop.file;
- if (!Platform::isDirectory(fileName) && !Platform::isFile(fileName))
- break;
- Con::executef("onDropFile", StringTable->insert(fileName));
- SDL_free(fileName); // Free dropped_filedir memory
- break;
- }
- case(SDL_DROPCOMPLETE):
- {
- if (Con::isFunction("onDropEnd"))
- Con::executef("onDropEnd");
- break;
- }
- default:
- {
- #ifdef TORQUE_DEBUG
- Con::warnf("Unhandled SDL input event: 0x%04x", evt.type);
- #endif
- }
- }
- }
- // After the event loop is processed, we can now see if we have to notify
- // SDL that we want text based events. This fixes a bug where text based
- // events would be generated while key presses would still be happening.
- // See KeyboardInputState for further documentation.
- if (mInputState != KeyboardInputState::NONE)
- {
- // Update text mode toggling.
- if (mInputState == KeyboardInputState::TEXT_INPUT)
- SDL_StartTextInput();
- else
- SDL_StopTextInput();
- // Done until we need to update it again.
- mInputState = KeyboardInputState::NONE;
- }
- }
- PlatformWindow * PlatformWindowManagerSDL::getWindowById( WindowId id )
- {
- // Walk the list and find the matching id, if any.
- PlatformWindowSDL *win = mWindowListHead;
- while(win)
- {
- if(win->getWindowId() == id)
- return win;
- win = win->mNextWindow;
- }
- return NULL;
- }
- PlatformWindow * PlatformWindowManagerSDL::getFirstWindow()
- {
- return mWindowListHead != NULL ? mWindowListHead : NULL;
- }
- PlatformWindow* PlatformWindowManagerSDL::getFocusedWindow()
- {
- PlatformWindowSDL* window = mWindowListHead;
- while( window )
- {
- if( window->isFocused() )
- return window;
- window = window->mNextWindow;
- }
- return NULL;
- }
- void PlatformWindowManagerSDL::linkWindow( PlatformWindowSDL *w )
- {
- w->mNextWindow = mWindowListHead;
- mWindowListHead = w;
- }
- void PlatformWindowManagerSDL::unlinkWindow( PlatformWindowSDL *w )
- {
- PlatformWindowSDL **walk = &mWindowListHead;
- while(*walk)
- {
- if(*walk != w)
- {
- // Advance to next item in list.
- walk = &(*walk)->mNextWindow;
- continue;
- }
- // Got a match - unlink and return.
- *walk = (*walk)->mNextWindow;
- return;
- }
- }
- void PlatformWindowManagerSDL::_processCmdLineArgs( const S32 argc, const char **argv )
- {
- // TODO SDL
- }
- void PlatformWindowManagerSDL::lowerCurtain()
- {
- if(mCurtainWindow)
- return;
- // TODO SDL
- }
- void PlatformWindowManagerSDL::raiseCurtain()
- {
- if(!mCurtainWindow)
- return;
- // TODO SDL
- }
- void PlatformWindowManagerSDL::updateSDLTextInputState(KeyboardInputState state)
- {
- // Force update state. This will respond at the end of the event loop.
- mInputState = state;
- }
- void Platform::openFolder(const char* path )
- {
- AssertFatal(0, "Not Implemented");
- }
- void Platform::openFile(const char* path )
- {
- AssertFatal(0, "Not Implemented");
- }
- //------------------------------------------------------------------------------
- namespace GL
- {
- void gglPerformBinds();
- }
- void InitWindowingSystem()
- {
- }
- AFTER_MODULE_INIT(gfx)
- {
- #if !defined(TORQUE_DEDICATED)
- int res = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE);
- AssertFatal(res != -1, avar("SDL error:%s", SDL_GetError()));
- // By default, SDL enables text input. We disable it on initialization, and
- // we will enable it whenever the time is right.
- SDL_StopTextInput();
- #endif
- }
|