X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=source%2FIrrlicht%2FCIrrDeviceSDL.cpp;h=26683a72a347337fbe6c8dc80a4c5b6f3be3ce4b;hb=939b3f7bfb2a9dce8258003347d7d0a5132db844;hp=ea309688892328e714311ddb5b483e5d9657b55b;hpb=2709c937d9ae8c1f1359a90d2112e985cafb2503;p=irrlicht.git diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index ea30968..26683a7 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -2,12 +2,13 @@ // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h -#include "IrrCompileConfig.h" #ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ #include "CIrrDeviceSDL.h" #include "IEventReceiver.h" +#include "IGUIElement.h" +#include "IGUIEnvironment.h" #include "os.h" #include "CTimer.h" #include "irrString.h" @@ -105,13 +106,105 @@ EM_BOOL CIrrDeviceSDL::MouseLeaveCallback(int eventType, const EmscriptenMouseEv } #endif + +bool CIrrDeviceSDL::keyIsKnownSpecial(EKEY_CODE key) +{ + switch ( key ) + { + // keys which are known to have safe special character interpretation + // could need changes over time (removals and additions!) + case KEY_RETURN: + case KEY_PAUSE: + case KEY_ESCAPE: + case KEY_PRIOR: + case KEY_NEXT: + case KEY_HOME: + case KEY_END: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_TAB: + case KEY_PRINT: + case KEY_SNAPSHOT: + case KEY_INSERT: + case KEY_BACK: + case KEY_DELETE: + case KEY_HELP: + case KEY_APPS: + case KEY_SLEEP: + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + case KEY_F13: + case KEY_F14: + case KEY_F15: + case KEY_F16: + case KEY_F17: + case KEY_F18: + case KEY_F19: + case KEY_F20: + case KEY_F21: + case KEY_F22: + case KEY_F23: + case KEY_F24: + case KEY_NUMLOCK: + case KEY_SCROLL: + case KEY_LCONTROL: + case KEY_RCONTROL: + return true; + + default: + return false; + } +} + +int CIrrDeviceSDL::findCharToPassToIrrlicht(int assumedChar, EKEY_CODE key) { + // SDL in-place ORs values with no character representation with 1<<30 + // https://wiki.libsdl.org/SDL2/SDLKeycodeLookup + if (assumedChar & (1<<30)) + return 0; + + switch (key) { + case KEY_PRIOR: + case KEY_NEXT: + case KEY_HOME: + case KEY_END: + case KEY_LEFT: + case KEY_UP: + case KEY_RIGHT: + case KEY_DOWN: + case KEY_NUMLOCK: + return 0; + default: + return assumedChar; + } +} + +void CIrrDeviceSDL::resetReceiveTextInputEvents() { + gui::IGUIElement *elem = GUIEnvironment->getFocus(); + if (elem && elem->acceptsIME()) + SDL_StartTextInput(); + else + SDL_StopTextInput(); +} + //! constructor CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) : CIrrDeviceStub(param), Window((SDL_Window*)param.WindowId), SDL_Flags(0), MouseX(0), MouseY(0), MouseXRel(0), MouseYRel(0), MouseButtonStates(0), Width(param.WindowSize.Width), Height(param.WindowSize.Height), - Resizable(param.WindowResizable == 1 ? true : false), WindowMinimized(false) + Resizable(param.WindowResizable == 1 ? true : false) { #ifdef _DEBUG setDebugName("CIrrDeviceSDL"); @@ -127,7 +220,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) #endif if (SDL_Init(flags) < 0) { - os::Printer::log( "Unable to initialize SDL!", SDL_GetError()); + os::Printer::log("Unable to initialize SDL!", SDL_GetError()); Close = true; } else @@ -139,10 +232,18 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) // create keymap createKeyMap(); - if ( CreationParams.Fullscreen ) + if (CreationParams.Fullscreen) { +#ifdef _IRR_EMSCRIPTEN_PLATFORM_ SDL_Flags |= SDL_WINDOW_FULLSCREEN; - else if ( Resizable ) +#else + SDL_Flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; +#endif + } + if (Resizable) SDL_Flags |= SDL_WINDOW_RESIZABLE; + if (CreationParams.WindowMaximized) + SDL_Flags |= SDL_WINDOW_MAXIMIZED; + if (CreationParams.DriverType == video::EDT_OPENGL) { SDL_Flags |= SDL_WINDOW_OPENGL; @@ -160,6 +261,7 @@ CIrrDeviceSDL::CIrrDeviceSDL(const SIrrlichtCreationParameters& param) createWindow(); } + SDL_VERSION(&Info.version); #ifndef _IRR_EMSCRIPTEN_PLATFORM_ @@ -270,7 +372,7 @@ bool CIrrDeviceSDL::createWindow() { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); - } + } SDL_CreateWindowAndRenderer(0, 0, SDL_Flags, &Window, &Renderer); // 0,0 will use the canvas size @@ -345,7 +447,7 @@ bool CIrrDeviceSDL::createWindow() } if ( !Window ) { - os::Printer::log( "Could not initialize display!" ); + os::Printer::log("Could not initialize display!" ); return false; } @@ -372,22 +474,6 @@ void CIrrDeviceSDL::createDriver() break; - case video::EDT_SOFTWARE: - #ifdef _IRR_COMPILE_WITH_SOFTWARE_ - VideoDriver = video::createSoftwareDriver(CreationParams.WindowSize, CreationParams.Fullscreen, FileSystem, this); - #else - os::Printer::log("No Software driver support compiled in.", ELL_ERROR); - #endif - break; - - case video::EDT_BURNINGSVIDEO: - #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_ - VideoDriver = video::createBurningVideoDriver(CreationParams, FileSystem, this); - #else - os::Printer::log("Burning's video driver was not compiled in.", ELL_ERROR); - #endif - break; - case video::EDT_OPENGL: #ifdef _IRR_COMPILE_WITH_OPENGL_ ContextManager = new video::CSDLManager(this); @@ -463,7 +549,9 @@ bool CIrrDeviceSDL::run() switch ( SDL_event.type ) { - case SDL_MOUSEMOTION: + case SDL_MOUSEMOTION: { + SDL_Keymod keymod = SDL_GetModState(); + irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; MouseX = irrevent.MouseInput.X = SDL_event.motion.x; @@ -471,20 +559,35 @@ bool CIrrDeviceSDL::run() MouseXRel = SDL_event.motion.xrel; MouseYRel = SDL_event.motion.yrel; irrevent.MouseInput.ButtonStates = MouseButtonStates; + irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0; + irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0; postEventFromUser(irrevent); break; - case SDL_MOUSEWHEEL: + } + case SDL_MOUSEWHEEL: { + SDL_Keymod keymod = SDL_GetModState(); + irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.Event = irr::EMIE_MOUSE_WHEEL; irrevent.MouseInput.Wheel = static_cast(SDL_event.wheel.y); + irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0; + irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0; + irrevent.MouseInput.X = MouseX; + irrevent.MouseInput.Y = MouseY; + postEventFromUser(irrevent); break; + } case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONUP: { + SDL_Keymod keymod = SDL_GetModState(); + irrevent.EventType = irr::EET_MOUSE_INPUT_EVENT; irrevent.MouseInput.X = SDL_event.button.x; irrevent.MouseInput.Y = SDL_event.button.y; + irrevent.MouseInput.Shift = (keymod & KMOD_SHIFT) != 0; + irrevent.MouseInput.Control = (keymod & KMOD_CTRL) != 0; irrevent.MouseInput.Event = irr::EMIE_MOUSE_MOVED; @@ -579,6 +682,7 @@ bool CIrrDeviceSDL::run() } } break; + } case SDL_TEXTINPUT: { @@ -604,6 +708,10 @@ bool CIrrDeviceSDL::run() else key = (EKEY_CODE)KeyMap[idx].Win32Key; + // Make sure to only input special characters if something is in focus, as SDL_TEXTINPUT handles normal unicode already + if (SDL_IsTextInputActive() && !keyIsKnownSpecial(key) && (SDL_event.key.keysym.mod & KMOD_CTRL) == 0) + break; + #ifdef _IRR_WINDOWS_API_ // handle alt+f4 in Windows, because SDL seems not to if ( (SDL_event.key.keysym.mod & KMOD_LALT) && key == KEY_F4) @@ -617,12 +725,7 @@ bool CIrrDeviceSDL::run() irrevent.KeyInput.PressedDown = (SDL_event.type == SDL_KEYDOWN); irrevent.KeyInput.Shift = (SDL_event.key.keysym.mod & KMOD_SHIFT) != 0; irrevent.KeyInput.Control = (SDL_event.key.keysym.mod & KMOD_CTRL ) != 0; - // These keys are handled differently in CGUIEditBox.cpp (may become out of date!) - // Control key is used in special character combinations, so keep that too - // Pass through the keysym only then so no extra text gets input - irrevent.KeyInput.Char = 0; - if (mp.SDLKey == SDLK_DELETE || mp.SDLKey == SDLK_RETURN || mp.SDLKey == SDLK_BACKSPACE || irrevent.KeyInput.Control) - irrevent.KeyInput.Char = mp.SDLKey; + irrevent.KeyInput.Char = findCharToPassToIrrlicht(mp.SDLKey, key); postEventFromUser(irrevent); } break; @@ -634,12 +737,6 @@ bool CIrrDeviceSDL::run() case SDL_WINDOWEVENT: switch (SDL_event.window.event) { - case SDL_WINDOWEVENT_MAXIMIZED: - WindowMinimized = true; - break; - case SDL_WINDOWEVENT_RESTORED: - WindowMinimized = false; - break; case SDL_WINDOWEVENT_RESIZED: if ((SDL_event.window.data1 != (int)Width) || (SDL_event.window.data2 != (int)Height)) { @@ -662,7 +759,7 @@ bool CIrrDeviceSDL::run() default: break; } // end switch - + resetReceiveTextInputEvents(); } // end while #if defined(_IRR_COMPILE_WITH_JOYSTICK_EVENTS_) @@ -828,90 +925,6 @@ void CIrrDeviceSDL::setWindowCaption(const wchar_t* text) } -//! presents a surface in the client area -bool CIrrDeviceSDL::present(video::IImage* surface, void* windowId, core::rect* srcClip) -{ -#ifdef _IRR_EMSCRIPTEN_PLATFORM_ - return true; -#else // !_IRR_EMSCRIPTEN_PLATFORM_ - SDL_Surface *sdlSurface = SDL_CreateRGBSurfaceFrom( - surface->getData(), surface->getDimension().Width, surface->getDimension().Height, - surface->getBitsPerPixel(), surface->getPitch(), - surface->getRedMask(), surface->getGreenMask(), surface->getBlueMask(), surface->getAlphaMask()); - if (!sdlSurface) - return false; - SDL_SetSurfaceAlphaMod(sdlSurface, 0); - SDL_SetColorKey(sdlSurface, 0, 0); - sdlSurface->format->BitsPerPixel=surface->getBitsPerPixel(); - sdlSurface->format->BytesPerPixel=surface->getBytesPerPixel(); - if ((surface->getColorFormat()==video::ECF_R8G8B8) || - (surface->getColorFormat()==video::ECF_A8R8G8B8)) - { - sdlSurface->format->Rloss=0; - sdlSurface->format->Gloss=0; - sdlSurface->format->Bloss=0; - sdlSurface->format->Rshift=16; - sdlSurface->format->Gshift=8; - sdlSurface->format->Bshift=0; - if (surface->getColorFormat()==video::ECF_R8G8B8) - { - sdlSurface->format->Aloss=8; - sdlSurface->format->Ashift=32; - } - else - { - sdlSurface->format->Aloss=0; - sdlSurface->format->Ashift=24; - } - } - else if (surface->getColorFormat()==video::ECF_R5G6B5) - { - sdlSurface->format->Rloss=3; - sdlSurface->format->Gloss=2; - sdlSurface->format->Bloss=3; - sdlSurface->format->Aloss=8; - sdlSurface->format->Rshift=11; - sdlSurface->format->Gshift=5; - sdlSurface->format->Bshift=0; - sdlSurface->format->Ashift=16; - } - else if (surface->getColorFormat()==video::ECF_A1R5G5B5) - { - sdlSurface->format->Rloss=3; - sdlSurface->format->Gloss=3; - sdlSurface->format->Bloss=3; - sdlSurface->format->Aloss=7; - sdlSurface->format->Rshift=10; - sdlSurface->format->Gshift=5; - sdlSurface->format->Bshift=0; - sdlSurface->format->Ashift=15; - } - - SDL_Surface* scr = (SDL_Surface* )windowId; - if (!scr) - scr = SDL_GetWindowSurface(Window); - if (scr) - { - if (srcClip) - { - SDL_Rect sdlsrcClip; - sdlsrcClip.x = srcClip->UpperLeftCorner.X; - sdlsrcClip.y = srcClip->UpperLeftCorner.Y; - sdlsrcClip.w = srcClip->getWidth(); - sdlsrcClip.h = srcClip->getHeight(); - SDL_BlitSurface(sdlSurface, &sdlsrcClip, scr, NULL); - } - else - SDL_BlitSurface(sdlSurface, NULL, scr, NULL); - SDL_RenderPresent(SDL_GetRenderer(Window)); - } - - SDL_FreeSurface(sdlSurface); - return (scr != 0); -#endif // !_IRR_EMSCRIPTEN_PLATFORM_ -} - - //! notifies the device that it should close itself void CIrrDeviceSDL::closeDevice() { @@ -926,7 +939,7 @@ void CIrrDeviceSDL::setResizable(bool resize) os::Printer::log("Resizable not available on the web." , ELL_WARNING); return; #else // !_IRR_EMSCRIPTEN_PLATFORM_ - if (resize != Resizable) { + if (resize != Resizable) { if (resize) SDL_Flags |= SDL_WINDOW_RESIZABLE; else @@ -944,16 +957,16 @@ void CIrrDeviceSDL::setResizable(bool resize) //! Minimizes window if possible void CIrrDeviceSDL::minimizeWindow() { - if (Window) { + if (Window) SDL_MinimizeWindow(Window); - } } //! Maximize window void CIrrDeviceSDL::maximizeWindow() { - // do nothing + if (Window) + SDL_MaximizeWindow(Window); } //! Get the position of this window on screen @@ -966,7 +979,13 @@ core::position2di CIrrDeviceSDL::getWindowPosition() //! Restore original window size void CIrrDeviceSDL::restoreWindow() { - // do nothing + if (Window) + SDL_RestoreWindow(Window); +} + +bool CIrrDeviceSDL::isWindowMaximized() const +{ + return Window && (SDL_GetWindowFlags(Window) & SDL_WINDOW_MAXIMIZED) != 0; } bool CIrrDeviceSDL::isFullscreen() const @@ -1001,14 +1020,14 @@ bool CIrrDeviceSDL::isWindowActive() const //! returns if window has focus. bool CIrrDeviceSDL::isWindowFocused() const { - return SDL_GetWindowFlags(Window) & SDL_WINDOW_INPUT_FOCUS; + return Window && (SDL_GetWindowFlags(Window) & SDL_WINDOW_INPUT_FOCUS) != 0; } //! returns if window is minimized. bool CIrrDeviceSDL::isWindowMinimized() const { - return WindowMinimized; + return Window && (SDL_GetWindowFlags(Window) & SDL_WINDOW_MINIMIZED) != 0; } @@ -1179,6 +1198,25 @@ void CIrrDeviceSDL::createKeyMap() KeyMap.sort(); } +void CIrrDeviceSDL::CCursorControl::initCursors() +{ + Cursors.reserve(gui::ECI_COUNT); + + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW)); // ECI_NORMAL + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR)); // ECI_CROSS + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND)); // ECI_HAND + Cursors.emplace_back(nullptr); // ECI_HELP + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM)); // ECI_IBEAM + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO)); // ECI_NO + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT)); // ECI_WAIT + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL)); // ECI_SIZEALL + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW)); // ECI_SIZENESW + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE)); // ECI_SIZENWSE + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS)); // ECI_SIZENS + Cursors.emplace_back(SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE)); // ECI_SIZEWE + Cursors.emplace_back(nullptr); // ECI_UP +} + } // end namespace irr #endif // _IRR_COMPILE_WITH_SDL_DEVICE_