123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727 |
- //-----------------------------------------------------------------------------
- // 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 "math/mMath.h"
- #include "gfx/gfxStructs.h"
- #include "windowManager/sdl/sdlWindow.h"
- #include "windowManager/sdl/sdlWindowMgr.h"
- #include "windowManager/sdl/sdlCursorController.h"
- #include "platformSDL/sdlInput.h"
- #include "platform/platformInput.h"
- #include "gfx/gfxDevice.h"
- #ifdef TORQUE_OS_LINUX
- #define SDL_VIDEO_DRIVER_X11 // TODO SDL
- #endif
- #include "SDL.h"
- #include "SDL_syswm.h"
- #define SCREENSAVER_QUERY_DENY 0 // Disable screensaver
- #ifndef IDI_ICON1
- #define IDI_ICON1 107
- #endif
- namespace
- {
- U32 getTorqueModFromSDL(U16 mod)
- {
- U32 ret = 0;
- if (mod & KMOD_LSHIFT)
- {
- ret |= SI_LSHIFT;
- ret |= SI_SHIFT;
- }
- if (mod & KMOD_RSHIFT)
- {
- ret |= SI_RSHIFT;
- ret |= SI_SHIFT;
- }
- if (mod & KMOD_LCTRL)
- {
- ret |= SI_LCTRL;
- ret |= SI_CTRL;
- }
- if (mod & KMOD_RCTRL)
- {
- ret |= SI_RCTRL;
- ret |= SI_CTRL;
- }
- if (mod & KMOD_LALT)
- {
- ret |= SI_LALT;
- ret |= SI_ALT;
- }
- if (mod & KMOD_RALT)
- {
- ret |= SI_RALT;
- ret |= SI_ALT;
- }
- // NOTE: For MacOS, this will treat command as Left or Right CTRL
- #ifdef TORQUE_OS_MAC
- if (mod & KMOD_LGUI)
- {
- ret |= SI_LCTRL;
- ret |= SI_CTRL;
- }
- if (mod & KMOD_RGUI)
- {
- ret |= SI_RCTRL;
- ret |= SI_CTRL;
- }
- #endif
- return ret;
- }
- }
- PlatformWindowSDL::PlatformWindowSDL():
- mOwningManager(NULL),
- mNextWindow(NULL),
- mWindowHandle(NULL),
- mOldParent(NULL),
- mDevice(NULL),
- mTarget(NULL),
- mPosition(0,0),
- mMouseLocked(false),
- mShouldLockMouse(false),
- mSuppressReset(false),
- mMenuHandle(NULL),
- mClosing(false)
- {
- mCursorController = new PlatformCursorControllerSDL( this );
- mVideoMode.bitDepth = 32;
- mVideoMode.fullScreen = false;
- mVideoMode.refreshRate = 60;
- mVideoMode.resolution.set(800,600);
- }
- PlatformWindowSDL::~PlatformWindowSDL()
- {
- // delete our sdl handle..
- SDL_DestroyWindow(mWindowHandle);
- // unlink ourselves from the window list...
- AssertFatal(mOwningManager, "PlatformWindowSDL::~PlatformWindowSDL - orphan window, cannot unlink!");
- mOwningManager->unlinkWindow(this);
- }
- GFXDevice * PlatformWindowSDL::getGFXDevice()
- {
- return mDevice;
- }
- GFXWindowTarget * PlatformWindowSDL::getGFXTarget()
- {
- return mTarget;
- }
- const GFXVideoMode & PlatformWindowSDL::getVideoMode()
- {
- return mVideoMode;
- }
- void* PlatformWindowSDL::getSystemWindow(const WindowSystem system)
- {
- SDL_SysWMinfo info;
- SDL_VERSION(&info.version);
- SDL_GetWindowWMInfo(mWindowHandle,&info);
- #ifdef TORQUE_OS_WIN
- if( system == WindowSystem_Windows && info.subsystem == SDL_SYSWM_WINDOWS)
- return info.info.win.window;
- #endif
- #if defined(TORQUE_OS_LINUX)
- if( system == WindowSystem_X11 && info.subsystem == SDL_SYSWM_X11)
- return (void*)info.info.x11.window;
- #endif
- AssertFatal(0, "");
- return NULL;
- }
- void PlatformWindowSDL::_setVideoMode( const GFXVideoMode &mode )
- {
- mVideoMode = mode;
- mSuppressReset = true;
- S32 newDisplay = Con::getIntVariable("pref::Video::deviceId", 0);
- // Set our window to have the right style based on the mode
- if(mode.fullScreen && !Platform::getWebDeployment() && !mOffscreenRender)
- {
- SDL_Rect rect_sdl;
- // Move the window onto the correct monitor before setting fullscreen
- if (0 == SDL_GetDisplayBounds(newDisplay, &rect_sdl))
- {
- SDL_SetWindowPosition(mWindowHandle, rect_sdl.x, rect_sdl.y);
- }
- setSize(mode.resolution);
- SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
- // When switching to Fullscreen, reset device after setting style
- if(mTarget.isValid())
- mTarget->resetMode();
- }
- else
- {
- // Reset device *first*, so that when we call setSize() and let it
- // access the monitor settings, it won't end up with our fullscreen
- // geometry that is just about to change.
- if(mTarget.isValid())
- mTarget->resetMode();
- if (!mOffscreenRender)
- {
- SDL_SetWindowFullscreen( mWindowHandle, 0);
- }
- // Restore the window to it's original size/position before applying changes
- SDL_RestoreWindow(mWindowHandle);
- // pref::Video::deviceMode values 0-windowed, 1-borderless, 2-fullscreen
- bool hasBorder = (0 == Con::getIntVariable("pref::Video::deviceMode", 0));
- SDL_SetWindowBordered(mWindowHandle, hasBorder ? SDL_TRUE : SDL_FALSE);
- setSize(mode.resolution);
- SDL_SetWindowPosition(mWindowHandle, SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay), SDL_WINDOWPOS_CENTERED_DISPLAY(newDisplay));
- if (hasBorder && Con::getBoolVariable("pref::Video::isMaximized", false))
- SDL_MaximizeWindow(mWindowHandle);
- }
- mSuppressReset = false;
- }
- bool PlatformWindowSDL::clearFullscreen()
- {
- return true;
- }
- bool PlatformWindowSDL::isFullscreen()
- {
- U32 flags = SDL_GetWindowFlags( mWindowHandle );
- if( flags & SDL_WINDOW_FULLSCREEN || flags & SDL_WINDOW_FULLSCREEN_DESKTOP )
- return true;
- return false;
- }
- void PlatformWindowSDL::_setFullscreen(const bool fullscreen)
- {
- if( isFullscreen() )
- return;
- if(fullscreen && !mOffscreenRender)
- {
- Con::printf("PlatformWindowSDL::setFullscreen (full) enter");
- SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN);
- }
- else
- {
- Con::printf("PlatformWindowSDL::setFullscreen (windowed) enter");
- if (!mOffscreenRender)
- {
- SDL_SetWindowFullscreen( mWindowHandle, SDL_WINDOW_FULLSCREEN_DESKTOP);
- }
- setSize(mVideoMode.resolution);
- }
- Con::printf("PlatformWindowSDL::setFullscreen exit");
- }
- bool PlatformWindowSDL::setCaption( const char *cap )
- {
- SDL_SetWindowTitle(mWindowHandle, cap);
- return true;
- }
- const char * PlatformWindowSDL::getCaption()
- {
- return StringTable->insert( SDL_GetWindowTitle(mWindowHandle) );
- }
- void PlatformWindowSDL::setFocus()
- {
- SDL_RaiseWindow(mWindowHandle);
- }
- void PlatformWindowSDL::setClientExtent( const Point2I newExtent )
- {
- Point2I oldExtent = getClientExtent();
- if (oldExtent == newExtent)
- return;
- SDL_SetWindowSize(mWindowHandle, newExtent.x, newExtent.y);
- }
- const Point2I PlatformWindowSDL::getClientExtent()
- {
- // Fetch Client Rect from Windows
- Point2I size;
- SDL_GetWindowSize(mWindowHandle, &size.x, &size.y);
- return size;
- }
- void PlatformWindowSDL::setBounds( const RectI &newBounds )
- {
- // TODO SDL
- }
- const RectI PlatformWindowSDL::getBounds() const
- {
- // TODO SDL
- return RectI(0, 0, 0, 0);
- }
- void PlatformWindowSDL::setPosition( const Point2I newPosition )
- {
- SDL_SetWindowPosition( mWindowHandle, newPosition.x, newPosition.y );
- }
- const Point2I PlatformWindowSDL::getPosition()
- {
- Point2I position;
- SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
- // Return position
- return position;
- }
- Point2I PlatformWindowSDL::clientToScreen( const Point2I& pos )
- {
- Point2I position;
- SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
- return pos + position;
- }
- Point2I PlatformWindowSDL::screenToClient( const Point2I& pos )
- {
- Point2I position;
- SDL_GetWindowPosition( mWindowHandle, &position.x, &position.y );
- return pos - position;
- }
- void PlatformWindowSDL::centerWindow()
- {
- int sizeX, sizeY;
- SDL_GetWindowSize(mWindowHandle, &sizeX, &sizeY);
- SDL_DisplayMode mode;
- SDL_GetDesktopDisplayMode(0, &mode);
-
- U32 posX = (mode.w/2) - (sizeX/2);
- U32 posY = (mode.h/2) - (sizeY/2);
- SDL_SetWindowPosition( mWindowHandle, posX, posY);
- }
- bool PlatformWindowSDL::setSize( const Point2I &newSize )
- {
- SDL_SetWindowSize(mWindowHandle, newSize.x, newSize.y);
- return true;
- }
- bool PlatformWindowSDL::isOpen()
- {
- return mWindowHandle;
- }
- bool PlatformWindowSDL::isVisible()
- {
- // Is the window open and visible, ie. not minimized?
- if(!mWindowHandle)
- return false;
- if (mOffscreenRender)
- return true;
- U32 flags = SDL_GetWindowFlags( mWindowHandle );
- if( flags & SDL_WINDOW_SHOWN)
- return true;
- return false;
- }
- bool PlatformWindowSDL::isFocused()
- {
- if (mOffscreenRender)
- return true;
- U32 flags = SDL_GetWindowFlags( mWindowHandle );
- if( flags & SDL_WINDOW_INPUT_FOCUS || flags & SDL_WINDOW_INPUT_GRABBED || flags & SDL_WINDOW_MOUSE_FOCUS )
- return true;
- return false;
- }
- bool PlatformWindowSDL::isMinimized()
- {
- if (mOffscreenRender)
- return false;
- U32 flags = SDL_GetWindowFlags( mWindowHandle );
- if( flags & SDL_WINDOW_MINIMIZED)
- return true;
- return false;
- }
- bool PlatformWindowSDL::isMaximized()
- {
- if (mOffscreenRender)
- return true;
- U32 flags = SDL_GetWindowFlags( mWindowHandle );
- if( flags & SDL_WINDOW_MAXIMIZED)
- return true;
- return false;
- }
- WindowId PlatformWindowSDL::getWindowId()
- {
- return mWindowId;
- }
- void PlatformWindowSDL::minimize()
- {
- if (mOffscreenRender)
- return;
- SDL_MinimizeWindow( mWindowHandle );
- }
- void PlatformWindowSDL::maximize()
- {
- if (mOffscreenRender)
- return;
- SDL_MaximizeWindow( mWindowHandle );
- }
- void PlatformWindowSDL::restore()
- {
- if (mOffscreenRender)
- return;
- SDL_RestoreWindow( mWindowHandle );
- }
- void PlatformWindowSDL::hide()
- {
- if (mOffscreenRender)
- return;
- SDL_HideWindow( mWindowHandle );
- }
- void PlatformWindowSDL::show()
- {
- if (mOffscreenRender)
- return;
- SDL_ShowWindow( mWindowHandle );
- }
- void PlatformWindowSDL::close()
- {
- delete this;
- }
- void PlatformWindowSDL::defaultRender()
- {
- // TODO SDL
- }
- void PlatformWindowSDL::_triggerMouseLocationNotify(const SDL_Event& evt)
- {
- U32 mods = getTorqueModFromSDL(SDL_GetModState());
- if(!mMouseLocked)
- mouseEvent.trigger(getWindowId(), mods, evt.motion.x, evt.motion.y, false);
- else
- mouseEvent.trigger(getWindowId(), mods, evt.motion.xrel, evt.motion.yrel, true);
- }
- void PlatformWindowSDL::_triggerMouseWheelNotify(const SDL_Event& evt)
- {
- U32 mods = getTorqueModFromSDL(SDL_GetModState());
- S32 wheelDelta = Con::getIntVariable("$pref::Input::MouseWheelSpeed", 120);
- wheelEvent.trigger(getWindowId(), mods, evt.wheel.x * wheelDelta, evt.wheel.y * wheelDelta);
- }
- void PlatformWindowSDL::_triggerMouseButtonNotify(const SDL_Event& event)
- {
- S32 action = (event.type == SDL_MOUSEBUTTONDOWN) ? SI_MAKE : SI_BREAK;
- S32 button = -1;
- switch (event.button.button)
- {
- case SDL_BUTTON_LEFT:
- button = 0;
- break;
- case SDL_BUTTON_RIGHT:
- button = 1;
- break;
- case SDL_BUTTON_MIDDLE:
- button = 2;
- break;
- case SDL_BUTTON_X1:
- button = 3;
- break;
- case SDL_BUTTON_X2:
- button = 4;
- break;
- default:
- return;
- }
-
- U32 mod = getTorqueModFromSDL( SDL_GetModState() );
- buttonEvent.trigger(getWindowId(), mod, action, button );
- }
- void PlatformWindowSDL::_triggerKeyNotify(const SDL_Event& evt)
- {
- U32 inputAction = IA_MAKE;
- SDL_Keysym tKey = evt.key.keysym;
- if(evt.type == SDL_KEYUP)
- {
- inputAction = IA_BREAK;
- }
- if(evt.key.repeat)
- {
- inputAction = IA_REPEAT;
- }
- U32 torqueModifiers = getTorqueModFromSDL(evt.key.keysym.mod);
- U32 torqueKey = KeyMapSDL::getTorqueScanCodeFromSDL(tKey.scancode);
- if(tKey.scancode)
- {
- keyEvent.trigger(getWindowId(), torqueModifiers, inputAction, torqueKey);
- //Con::printf("Key %d : %d", tKey.sym, inputAction);
- if (inputAction == IA_MAKE && SDL_IsTextInputActive())
- {
- // We have to check if we already have a first responder active.
- // We don't want to type the character if it actually creates another responder!
- if (mWindowInputGenerator->lastKeyWasGlobalActionMap())
- {
- // Turn off Text input, and the next frame turn it back on. This tells SDL
- // to not generate a text event for this global action map key.
- SDL_StopTextInput();
- mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::TEXT_INPUT);
- }
- }
- }
- }
- void PlatformWindowSDL::_triggerTextNotify(const SDL_Event& evt)
- {
- U32 mod = getTorqueModFromSDL( SDL_GetModState() );
-
- if( !evt.text.text[1] ) // get a char
- {
- U16 wchar = evt.text.text[0];
- charEvent.trigger(getWindowId(), mod, wchar );
- //Con::printf("Char: %c", wchar);
- return;
- }
- else // get a wchar string
- {
- const dsize_t len = strlen(evt.text.text);
- U16 wchar[16] = {};
- dMemcpy(wchar, evt.text.text, sizeof(char)*len);
- for(int i = 0; i < 16; ++i)
- {
- if( !wchar[i] )
- return;
- charEvent.trigger(getWindowId(), mod, wchar[i] );
- }
- }
- }
- void PlatformWindowSDL::_updateMonitorFromMove(const SDL_Event& evt)
- {
- SDL_Rect sdlRect;
- S32 monitorCount = SDL_GetNumVideoDisplays();
- for (S32 index = 0; index < monitorCount; ++index)
- {
- if (0 == SDL_GetDisplayBounds(index, &sdlRect))
- {
- if ((evt.window.data1 >= sdlRect.x) && (evt.window.data1 < (sdlRect.x + sdlRect.w)) &&
- (evt.window.data2 >= sdlRect.y) && (evt.window.data2 < (sdlRect.y + sdlRect.h)))
- {
- Con::setIntVariable("pref::Video::deviceId", index);
- return;
- }
- }
- }
- }
- void PlatformWindowSDL::_processSDLEvent(SDL_Event &evt)
- {
- switch(evt.type)
- {
- case SDL_KEYDOWN:
- case SDL_KEYUP:
- {
- _triggerKeyNotify(evt);
- break;
- }
- case SDL_TEXTINPUT:
- {
- _triggerTextNotify(evt);
- break;
- }
- case SDL_MOUSEWHEEL:
- {
- _triggerMouseWheelNotify(evt);
- break;
- }
- case SDL_MOUSEMOTION:
- {
- _triggerMouseLocationNotify(evt);
- break;
- }
- case SDL_MOUSEBUTTONDOWN:
- case SDL_MOUSEBUTTONUP:
- {
- _triggerMouseButtonNotify(evt);
- break;
- }
- case SDL_WINDOWEVENT:
- {
- if (!mClosing)
- {
- switch (evt.window.event)
- {
- case SDL_WINDOWEVENT_FOCUS_GAINED:
- appEvent.trigger(getWindowId(), GainFocus);
- break;
- case SDL_WINDOWEVENT_FOCUS_LOST:
- appEvent.trigger(getWindowId(), LoseFocus);
- break;
- case SDL_WINDOWEVENT_MOVED:
- {
- S32 oldDisplay = Con::getIntVariable("pref::Video::deviceId", 0);
- _updateMonitorFromMove(evt);
- // If display device has changed, make sure window params are compatible with the new device.
- if (oldDisplay != Con::getIntVariable("pref::Video::deviceId", 0))
- Con::evaluate("configureCanvas();");
- break;
- }
- case SDL_WINDOWEVENT_RESIZED:
- {
- int width, height;
- SDL_GetWindowSize(mWindowHandle, &width, &height);
- mVideoMode.resolution.set(width, height);
- getGFXTarget()->resetMode();
- resizeEvent.trigger(getWindowId(), width, height);
- getScreenResChangeSignal().trigger(this, true);
- break;
- }
- case SDL_WINDOWEVENT_CLOSE:
- {
- appEvent.trigger(getWindowId(), WindowClose);
- mClosing = true;
- }
- case SDL_WINDOWEVENT_MINIMIZED:
- break;
- case SDL_WINDOWEVENT_MAXIMIZED:
- Con::setBoolVariable("pref::Video::isMaximized", true);
- break;
- case SDL_WINDOWEVENT_RESTORED:
- Con::setBoolVariable("pref::Video::isMaximized", false);
- break;
- default:
- break;
- }
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- // Mouse Locking
- //-----------------------------------------------------------------------------
- void PlatformWindowSDL::setMouseLocked( bool enable )
- {
- if (mOffscreenRender)
- return;
- mMouseLocked = enable;
-
- SDL_SetWindowGrab( mWindowHandle, SDL_bool(enable) );
- SDL_SetRelativeMouseMode( SDL_bool(enable) );
- }
- const UTF16 *PlatformWindowSDL::getWindowClassName()
- {
- // TODO SDL
- static String str("WindowClassName");
- return str.utf16();
- }
- const UTF16 *PlatformWindowSDL::getCurtainWindowClassName()
- {
- // TODO SDL
- static String str("CurtainWindowClassName");
- return str.utf16();
- }
- void PlatformWindowSDL::setKeyboardTranslation(const bool enabled)
- {
- mEnableKeyboardTranslation = enabled;
- // Flag for update. Let SDL know what kind of input state we are changing to.
- if (enabled)
- mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::TEXT_INPUT);
- else
- mOwningManager->updateSDLTextInputState(PlatformWindowManagerSDL::KeyboardInputState::RAW_INPUT);
- }
|