Files
eepp/src/eepp/window/backend/SDL3/windowsdl3.cpp
2026-09-04 01:46:17 -03:00

760 lines
20 KiB
C++

#include <eepp/window/backend/SDL3/base.hpp>
#ifdef EE_BACKEND_SDL3
#include <eepp/graphics/globalbatchrenderer.hpp>
#include <eepp/graphics/renderer/renderer.hpp>
#include <eepp/graphics/shaderprogramregistry.hpp>
#include <eepp/graphics/texturefactory.hpp>
#include <eepp/system/filesystem.hpp>
#include <eepp/system/log.hpp>
#include <eepp/window/backend/SDL3/clipboardsdl3.hpp>
#include <eepp/window/backend/SDL3/cursormanagersdl3.hpp>
#include <eepp/window/backend/SDL3/displaymanagersdl3.hpp>
#include <eepp/window/backend/SDL3/inputsdl3.hpp>
#include <eepp/window/backend/SDL3/windowsdl3.hpp>
#include <eepp/window/backend/SDL3/wminfo.hpp>
#include <eepp/window/backend/backendhelper.hpp>
#include <eepp/window/engine.hpp>
#if EE_PLATFORM == EE_PLATFORM_WIN
#include <eepp/window/backend/SDL3/displaymanagersdl3.hpp>
#endif
#if EE_PLATFORM == EE_PLATFORM_WIN || EE_PLATFORM == EE_PLATFORM_MACOS || \
defined( EE_X11_PLATFORM ) || EE_PLATFORM == EE_PLATFORM_IOS || \
EE_PLATFORM == EE_PLATFORM_ANDROID || EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
#define SDL3_THREADED_GLCONTEXT
#endif
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
WindowSDL::WindowSDL( WindowSettings Settings, ContextSettings Context ) :
Window( Settings, Context, eeNew( ClipboardSDL, ( this ) ), eeNew( InputSDL, ( this ) ),
eeNew( CursorManagerSDL, ( this ) ) ) {
create( Settings, Context );
}
WindowSDL::~WindowSDL() {
destroySDLResources();
}
void WindowSDL::destroySDLResources() {
if ( nullptr != mGLContext ) {
SDL_GL_DestroyContext( mGLContext );
mGLContext = nullptr;
}
if ( nullptr != mGLContextThread ) {
SDL_GL_DestroyContext( mGLContextThread );
mGLContextThread = nullptr;
}
eeSAFE_DELETE( mWMinfo );
if ( nullptr != mSDLWindow ) {
SDL_DestroyWindow( mSDLWindow );
mSDLWindow = nullptr;
}
#if defined( EE_X11_PLATFORM )
Backend::BackendHelper::hideOSK();
#endif
}
bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
if ( mWindow.Created )
return false;
mWindow.WindowConfig = Settings;
mWindow.ContextConfig = Context;
#if defined( EE_X11_PLATFORM )
// Unmapped GLX windows do not provide reliable front-buffer storage. Keep hidden windows
// double-buffered so rendering and readback use the drawable's back buffer.
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
mWindow.ContextConfig.DoubleBuffering = true;
#endif
if ( !SDL_WasInit( SDL_INIT_VIDEO ) && !SDL_Init( SDL_INIT_VIDEO ) ) {
Log::error( "Unable to initialize SDL: %s", SDL_GetError() );
logFailureInit( "WindowSDL", getVersion() );
return false;
}
SDL_DisplayID primaryDisplay = SDL_GetPrimaryDisplay();
const SDL_DisplayMode* dpm = SDL_GetDesktopDisplayMode( primaryDisplay );
if ( dpm ) {
mWindow.DesktopResolution = Sizei( dpm->w, dpm->h );
} else {
Log::error( "Failed to get desktop display mode" );
mWindow.DesktopResolution = Sizei( 800, 600 );
}
#if EE_PLATFORM == EE_PLATFORM_ANDROID
mWindow.WindowConfig.Style = WindowStyle::Fullscreen | WindowStyle::UseDesktopResolution;
#endif
if ( mWindow.WindowConfig.Style & WindowStyle::UseDesktopResolution ) {
mWindow.WindowConfig.Width = mWindow.DesktopResolution.getWidth();
mWindow.WindowConfig.Height = mWindow.DesktopResolution.getHeight();
}
mWindow.Flags =
SDL_WINDOW_OPENGL |
( ( mWindow.WindowConfig.Style & WindowStyle::Hidden ) ? SDL_WINDOW_HIDDEN : 0 ) |
( ( !mWindow.WindowConfig.DisableHiDPI ? SDL_WINDOW_HIGH_PIXEL_DENSITY : 0 ) );
if ( mWindow.WindowConfig.Style & WindowStyle::Resize ) {
mWindow.Flags |= SDL_WINDOW_RESIZABLE;
}
if ( mWindow.WindowConfig.Style & WindowStyle::Borderless ) {
mWindow.Flags |= SDL_WINDOW_BORDERLESS;
}
setGLConfig();
Uint32 tmpFlags = mWindow.Flags;
if ( mWindow.WindowConfig.Style & WindowStyle::Fullscreen ) {
tmpFlags |= SDL_WINDOW_FULLSCREEN;
}
if ( mWindow.ContextConfig.Multisamples > 0 ) {
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, mWindow.ContextConfig.Multisamples );
}
#if EE_PLATFORM != EE_PLATFORM_MACOS && EE_PLATFORM != EE_PLATFORM_IOS && \
EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
mWindow.WindowConfig.Width *= mWindow.WindowConfig.PixelDensity;
mWindow.WindowConfig.Height *= mWindow.WindowConfig.PixelDensity;
#endif
mSDLWindow = SDL_CreateWindow( mWindow.WindowConfig.Title.c_str(), mWindow.WindowConfig.Width,
mWindow.WindowConfig.Height, tmpFlags );
if ( nullptr == mSDLWindow ) {
Log::error( "Unable to create window: %s", SDL_GetError() );
logFailureInit( "WindowSDL", getVersion() );
return false;
}
#if EE_PLATFORM == EE_PLATFORM_ANDROID || EE_PLATFORM == EE_PLATFORM_IOS
Log::notice( "Choosing GL Version from: %d", Context.Version );
if ( GLv_default != Context.Version ) {
if ( GLv_ES1 == Context.Version || GLv_2 == Context.Version ) {
if ( GLv_2 == Context.Version )
mWindow.ContextConfig.Version = GLv_ES1;
Log::notice( "Starting GLES1" );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
} else {
Log::notice( "Starting GLES2" );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
}
} else {
#if defined( EE_GLES2 )
Log::notice( "Starting GLES2 default" );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 0 );
#else
Log::notice( "Starting GLES1 default" );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 1 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 );
#endif
}
#else
if ( GLv_3CP == Context.Version ) {
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
}
#endif
#ifdef SDL3_THREADED_GLCONTEXT
if ( mWindow.ContextConfig.SharedGLContext ) {
SDL_GL_SetAttribute( SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1 );
mGLContextThread = SDL_GL_CreateContext( mSDLWindow );
mGLContext = SDL_GL_CreateContext( mSDLWindow );
} else {
mGLContext = SDL_GL_CreateContext( mSDLWindow );
}
#else
mGLContext = SDL_GL_CreateContext( mSDLWindow );
mWindow.ContextConfig.SharedGLContext = false;
#endif
if ( nullptr == mGLContext
#ifdef SDL3_THREADED_GLCONTEXT
|| ( mWindow.ContextConfig.SharedGLContext && nullptr == mGLContextThread )
#endif
) {
Log::error( "Unable to create context: %s", SDL_GetError() );
logFailureInit( "WindowSDL", getVersion() );
return false;
}
int w, h;
SDL_GetWindowSizeInPixels( mSDLWindow, &w, &h );
if ( w > 0 && h > 0 ) {
mWindow.WindowConfig.Width = w;
mWindow.WindowConfig.Height = h;
mWindow.WindowSize = Sizei( mWindow.WindowConfig.Width, mWindow.WindowConfig.Height );
mLastWindowedSize = mWindow.WindowSize;
} else {
Log::error( "Window failed to create!" );
if ( nullptr != SDL_GetError() && SDL_GetError()[0] != '\0' ) {
Log::error( "SDL Error: %s", SDL_GetError() );
}
return false;
}
SDL_GL_SetSwapInterval( ( mWindow.ContextConfig.VSync ? 1 : 0 ) );
SDL_GL_MakeCurrent( mSDLWindow, mGLContext );
mID = SDL_GetWindowID( mSDLWindow );
mWMinfo = eeNew( WMInfo, ( mSDLWindow ) );
if ( nullptr == Renderer::existsSingleton() ) {
Renderer::createSingleton( mWindow.ContextConfig.Version );
Renderer::instance()->init();
if ( mWindow.ContextConfig.Multisamples > 0 )
Renderer::instance()->multisample( true );
}
getMainContext();
setTitle( mWindow.WindowConfig.Title );
createView();
setup2D( false );
mWindow.Created = true;
if ( "" != mWindow.WindowConfig.Icon ) {
setIcon( mWindow.WindowConfig.Icon );
}
static_cast<ClipboardSDL*>( mClipboard )->init();
static_cast<InputSDL*>( mInput )->init();
mCursorManager->set( Cursor::SysArrow );
#if EE_PLATFORM == EE_PLATFORM_WIN
Backend::BackendHelper::setUserTheme( (HWND)getWindowHandler() );
#endif
if ( mWindow.WindowConfig.Style & WindowStyle::Hidden )
SDL_HideWindow( mSDLWindow );
logSuccessfulInit( getVersion() );
return true;
}
Uint32 WindowSDL::getWindowID() const {
return mID;
}
void WindowSDL::makeCurrent() {
SDL_GL_MakeCurrent( mSDLWindow, mGLContext );
}
void WindowSDL::close() {
destroySDLResources();
Window::close();
}
void WindowSDL::setCurrent() {
makeCurrent();
}
bool WindowSDL::isThreadedGLContext() const {
#ifdef SDL3_THREADED_GLCONTEXT
return mWindow.ContextConfig.SharedGLContext;
#else
return false;
#endif
}
void WindowSDL::setGLContextThread() {
mGLContextMutex.lock();
SDL_GL_MakeCurrent( mSDLWindow, mGLContextThread );
}
void WindowSDL::unsetGLContextThread() {
SDL_GL_MakeCurrent( mSDLWindow, nullptr );
#if SDL_VERSION_ATLEAST( 3, 2, 0 )
SDL_CleanupTLS();
#endif
mGLContextMutex.unlock();
}
int WindowSDL::getCurrentDisplayIndex() const {
if ( !mSDLWindow )
return 0;
SDL_DisplayID displayID = SDL_GetDisplayForWindow( mSDLWindow );
// Map display ID to index using the display manager
auto* dispMgr = static_cast<DisplayManagerSDL3*>( Engine::instance()->getDisplayManager() );
int idx = dispMgr->getDisplayIndexFromID( displayID );
return idx >= 0 ? idx : 0;
}
std::string WindowSDL::getVersion() {
int ver = SDL_GetVersion();
return String::format( "SDL %d.%d.%d", SDL_VERSIONNUM_MAJOR( ver ), SDL_VERSIONNUM_MINOR( ver ),
SDL_VERSIONNUM_MICRO( ver ) );
}
void WindowSDL::setGLConfig() {
if ( mWindow.ContextConfig.DepthBufferSize )
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, mWindow.ContextConfig.DepthBufferSize );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, ( mWindow.ContextConfig.DoubleBuffering ? 1 : 0 ) );
if ( mWindow.ContextConfig.StencilBufferSize )
SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, mWindow.ContextConfig.StencilBufferSize );
if ( mWindow.WindowConfig.BitsPerPixel == 16 ) {
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 4 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 4 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 4 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 4 );
} else {
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
}
}
void WindowSDL::toggleFullscreen() {
Log::info( "toggleFullscreen called: %s", isWindowed() ? "is windowed" : "is fullscreen" );
if ( isWindowed() ) {
mWinPos = getPosition();
mWindow.Maximized = isMaximized();
}
SDL_SetWindowFullscreen( mSDLWindow, !isWindowed() ? false : true );
BitOp::setBitFlagValue( &mWindow.WindowConfig.Style, WindowStyle::Fullscreen,
isWindowed() ? 1 : 0 );
getCursorManager()->reload();
if ( isWindowed() ) {
setPosition( mWinPos.x, mWinPos.y );
if ( mWindow.Maximized )
maximize();
}
}
void WindowSDL::setTitle( const std::string& title ) {
if ( mWindow.WindowConfig.Title != title ) {
mWindow.WindowConfig.Title = title;
SDL_SetWindowTitle( mSDLWindow, title.c_str() );
}
}
bool WindowSDL::isActive() const {
Uint64 flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( ( flags & SDL_WINDOW_INPUT_FOCUS ) && ( flags & SDL_WINDOW_MOUSE_FOCUS ) );
}
bool WindowSDL::isVisible() const {
Uint64 flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( !( flags & SDL_WINDOW_HIDDEN ) && !( flags & SDL_WINDOW_MINIMIZED ) );
}
bool WindowSDL::hasFocus() const {
Uint64 flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( flags & ( SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS ) );
}
bool WindowSDL::hasInputFocus() const {
Uint64 flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( flags & SDL_WINDOW_INPUT_FOCUS );
}
bool WindowSDL::hasMouseFocus() const {
Uint64 flags = SDL_GetWindowFlags( mSDLWindow );
return 0 != ( flags & SDL_WINDOW_MOUSE_FOCUS );
}
void WindowSDL::onWindowResize( Uint32 width, Uint32 height ) {
if ( width == mWindow.WindowConfig.Width && height == mWindow.WindowConfig.Height )
return;
Log::debug( "onWindowResize: Width %d Height %d.", width, height );
mWindow.WindowConfig.Width = width;
mWindow.WindowConfig.Height = height;
mWindow.WindowSize = Sizei( width, height );
if ( isWindowed() )
mLastWindowedSize = Sizei( width, height );
mDefaultView.reset( Rectf( 0, 0, mWindow.WindowConfig.Width, mWindow.WindowConfig.Height ) );
setup2D( false );
SDL_PumpEvents();
SDL_FlushEvent( SDL_EVENT_WINDOW_RESIZED );
mCursorManager->reload();
sendVideoResizeCb();
}
void WindowSDL::setSize( Uint32 width, Uint32 height, bool windowed ) {
if ( ( !width || !height ) ) {
width = mWindow.DesktopResolution.getWidth();
height = mWindow.DesktopResolution.getHeight();
}
if ( this->isWindowed() == windowed && width == mWindow.WindowConfig.Width &&
height == mWindow.WindowConfig.Height )
return;
Log::debug( "Switching from %s to %s. Width: %d Height %d.",
this->isWindowed() ? "windowed" : "fullscreen",
windowed ? "windowed" : "fullscreen", width, height );
Uint32 oldWidth = mWindow.WindowConfig.Width;
Uint32 oldHeight = mWindow.WindowConfig.Height;
mWindow.WindowConfig.Width = width;
mWindow.WindowConfig.Height = height;
if ( windowed ) {
mWindow.WindowSize = Sizei( width, height );
} else {
mWindow.WindowSize = Sizei( oldWidth, oldHeight );
}
if ( isWindowed() && !windowed ) {
mWinPos = getPosition();
} else {
SDL_SetWindowFullscreen( mSDLWindow, !windowed );
}
if ( windowed )
mLastWindowedSize = Sizei( width, height );
SDL_SetWindowSize( mSDLWindow, width, height );
if ( isWindowed() && !windowed ) {
mWinPos = getPosition();
setGLConfig();
SDL_SetWindowFullscreen( mSDLWindow, !windowed );
}
if ( isWindowed() && windowed ) {
setPosition( mWinPos.x, mWinPos.y );
}
BitOp::setBitFlagValue( &mWindow.WindowConfig.Style, WindowStyle::Fullscreen, !windowed );
mDefaultView.reset( Rectf( 0, 0, width, height ) );
setup2D( false );
SDL_PumpEvents();
SDL_FlushEvent( SDL_EVENT_WINDOW_RESIZED );
mCursorManager->reload();
sendVideoResizeCb();
}
void WindowSDL::swapBuffers() {
SDL_GL_SwapWindow( mSDLWindow );
}
std::vector<DisplayMode> WindowSDL::getDisplayModes() const {
std::vector<DisplayMode> result;
int displayCount = 0;
SDL_DisplayID* displays = SDL_GetDisplays( &displayCount );
if ( displays ) {
for ( int x = 0; x < displayCount; x++ ) {
int modeCount = 0;
SDL_DisplayMode** modesArray = SDL_GetFullscreenDisplayModes( displays[x], &modeCount );
if ( modesArray ) {
for ( int i = 0; i < modeCount; i++ ) {
SDL_DisplayMode* mode = modesArray[i];
result.push_back( DisplayMode( mode->w, mode->h, (int)mode->refresh_rate, x ) );
}
SDL_free( modesArray );
}
}
SDL_free( displays );
}
return result;
}
void WindowSDL::setGamma( Float Red, Float Green, Float Blue ) {
// SDL3 removed gamma ramp functionality
}
eeWindowHandle WindowSDL::getWindowHandler() const {
if ( nullptr != mWMinfo ) {
return mWMinfo->getWindowHandler();
}
return 0;
}
bool WindowSDL::setIcon( const std::string& Path ) {
int x, y, c;
if ( !mWindow.Created ) {
if ( Image::getInfo( Path.c_str(), &x, &y, &c ) ) {
mWindow.WindowConfig.Icon = Path;
return true;
}
return false;
}
Image Img( Path );
if ( nullptr != Img.getPixelsPtr() ) {
#if EE_PLATFORM == EE_PLATFORM_WIN
if ( Img.getWidth() > 64 || Img.getHeight() > 64 ) {
Img.resize( 64, 64 );
}
#endif
const Uint8* Ptr = Img.getPixelsPtr();
x = Img.getWidth();
y = Img.getHeight();
c = Img.getChannels();
if ( ( x % 8 ) == 0 && ( y % 8 ) == 0 ) {
SDL_Surface* iconSurface = SDL_CreateSurface( x, y, SDL_PIXELFORMAT_RGBA32 );
if ( iconSurface ) {
memcpy( iconSurface->pixels, Ptr, x * y * c );
SDL_SetWindowIcon( mSDLWindow, iconSurface );
SDL_DestroySurface( iconSurface );
return true;
}
}
}
return false;
}
void WindowSDL::minimize() {
SDL_MinimizeWindow( mSDLWindow );
}
void WindowSDL::maximize() {
SDL_MaximizeWindow( mSDLWindow );
}
bool WindowSDL::isMaximized() const {
return SDL_GetWindowFlags( mSDLWindow ) & SDL_WINDOW_MAXIMIZED;
}
bool WindowSDL::isMinimized() const {
return SDL_GetWindowFlags( mSDLWindow ) & SDL_WINDOW_MINIMIZED;
}
void WindowSDL::hide() {
SDL_HideWindow( mSDLWindow );
}
void WindowSDL::raise() {
SDL_RaiseWindow( mSDLWindow );
}
void WindowSDL::restore() {
SDL_RestoreWindow( mSDLWindow );
}
void WindowSDL::flash( WindowFlashOperation op ) {
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN
SDL_FlashOperation sdlOp = SDL_FLASH_BRIEFLY;
if ( op == WindowFlashOperation::Cancel )
sdlOp = SDL_FLASH_CANCEL;
else if ( op == WindowFlashOperation::UntilFocused )
sdlOp = SDL_FLASH_UNTIL_FOCUSED;
SDL_FlashWindow( mSDLWindow, sdlOp );
#endif
}
void WindowSDL::show() {
SDL_ShowWindow( mSDLWindow );
}
void WindowSDL::setPosition( int Left, int Top ) {
SDL_SetWindowPosition( mSDLWindow, Left, Top );
}
Vector2i WindowSDL::getPosition() const {
Vector2i p;
SDL_GetWindowPosition( mSDLWindow, &p.x, &p.y );
return p;
}
void WindowSDL::updateDesktopResolution() const {
SDL_DisplayID displayID = SDL_GetDisplayForWindow( mSDLWindow );
const SDL_DisplayMode* dpm = SDL_GetDesktopDisplayMode( displayID );
if ( dpm ) {
mWindow.DesktopResolution = Sizei( dpm->w, dpm->h );
} else {
Log::warning( "Failed to get desktop display mode for display %u", displayID );
}
}
const Sizei& WindowSDL::getDesktopResolution() const {
updateDesktopResolution();
return Window::getDesktopResolution();
}
Rect WindowSDL::getBorderSize() const {
Rect bordersSize;
SDL_GetWindowBordersSize( mSDLWindow, &bordersSize.Top, &bordersSize.Left, &bordersSize.Bottom,
&bordersSize.Right );
return bordersSize;
}
Float WindowSDL::getScale() const {
if ( nullptr == mSDLWindow )
return PixelDensity::getPixelDensity();
int realX, realY;
int scaledX, scaledY;
SDL_GetWindowSizeInPixels( mSDLWindow, &realX, &realY );
SDL_GetWindowSize( mSDLWindow, &scaledX, &scaledY );
return (Float)realX / (Float)scaledX;
}
bool WindowSDL::hasNativeMessageBox() const {
return true;
}
Uint32 toSDLMsgBoxType( const Window::MessageBoxType& type ) {
switch ( type ) {
case Window::MessageBoxType::Error:
return SDL_MESSAGEBOX_ERROR;
case Window::MessageBoxType::Warning:
return SDL_MESSAGEBOX_WARNING;
case Window::MessageBoxType::Information:
return SDL_MESSAGEBOX_INFORMATION;
}
return SDL_MESSAGEBOX_INFORMATION;
}
bool WindowSDL::showMessageBox( const MessageBoxType& type, const std::string& title,
const std::string& message ) {
return SDL_ShowSimpleMessageBox( toSDLMsgBoxType( type ), title.c_str(), message.c_str(),
mSDLWindow );
}
SDL_Window* WindowSDL::getSDLWindow() const {
return mSDLWindow;
}
void WindowSDL::startOnScreenKeyboard() {
#if EE_PLATFORM == EE_PLATFORM_WIN
Backend::BackendHelper::showOSK( getWindowHandler() );
#elif defined( EE_X11_PLATFORM )
Backend::BackendHelper::showOSK();
#endif
}
void WindowSDL::stopOnScreenKeyboard() {
Backend::BackendHelper::hideOSK();
}
bool WindowSDL::isOnScreenKeyboardActive() const {
return Backend::BackendHelper::isOSKActive();
}
void WindowSDL::startTextInput() {
if ( mWindow.WindowConfig.UseScreenKeyboard ) {
startOnScreenKeyboard();
} else {
SDL_StartTextInput( mSDLWindow );
}
}
bool WindowSDL::isTextInputActive() const {
if ( mWindow.WindowConfig.UseScreenKeyboard )
return isOnScreenKeyboardActive();
return SDL_TextInputActive( mSDLWindow );
}
void WindowSDL::stopTextInput() {
if ( mWindow.WindowConfig.UseScreenKeyboard ) {
stopOnScreenKeyboard();
} else {
SDL_StopTextInput( mSDLWindow );
}
}
void WindowSDL::setTextInputRect( const Rect& rect ) {
SDL_Rect r;
r.x = rect.Left;
r.y = rect.Top;
r.w = rect.getSize().getWidth();
r.h = rect.getSize().getHeight();
SDL_SetTextInputArea( mSDLWindow, &r, 0 );
}
void WindowSDL::clearComposition() {
SDL_ClearComposition( mSDLWindow );
}
bool WindowSDL::hasScreenKeyboardSupport() const {
return SDL_HasScreenKeyboardSupport();
}
bool WindowSDL::isScreenKeyboardShown() const {
return SDL_ScreenKeyboardShown( mSDLWindow );
}
}}}} // namespace EE::Window::Backend::SDL3
#endif