mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
SDL3 port WIP.
This commit is contained in:
@@ -172,7 +172,7 @@
|
||||
"eepp-linux": {
|
||||
"build": [
|
||||
{
|
||||
"args": "--disable-static-build --with-mold-linker --with-debug-symbols --address-sanitizer gmake",
|
||||
"args": "--disable-static-build --with-mold-linker --with-debug-symbols --address-sanitizer --with-backend=SDL3 gmake",
|
||||
"command": "premake4",
|
||||
"working_dir": "${project_root}"
|
||||
},
|
||||
@@ -464,7 +464,7 @@
|
||||
"eepp-linux-ninja": {
|
||||
"build": [
|
||||
{
|
||||
"args": "--disable-static-build --with-debug-symbols ninja",
|
||||
"args": "--disable-static-build --with-debug-symbols --with-backend=SDL3 ninja",
|
||||
"command": "premake5",
|
||||
"working_dir": "${project_root}"
|
||||
},
|
||||
|
||||
@@ -166,6 +166,13 @@ class EE_API Engine {
|
||||
EE::Window::Window* createSDL2Window( const WindowSettings& Settings,
|
||||
const ContextSettings& Context );
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
Backend::WindowBackendLibrary* createSDL3Backend( const WindowSettings& Settings );
|
||||
|
||||
EE::Window::Window* createSDL3Window( const WindowSettings& Settings,
|
||||
const ContextSettings& Context );
|
||||
#endif
|
||||
|
||||
EE::Window::Window* createDefaultWindow( const WindowSettings& Settings,
|
||||
const ContextSettings& Context );
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ enum class WindowFlashOperation {
|
||||
UntilFocused,
|
||||
};
|
||||
|
||||
enum class WindowBackend : Uint32 { SDL2, Default };
|
||||
enum class WindowBackend : Uint32 { SDL2, SDL3, Default };
|
||||
|
||||
#ifndef EE_SCREEN_KEYBOARD_ENABLED
|
||||
#define EE_SCREEN_KEYBOARD_ENABLED false
|
||||
@@ -89,7 +89,8 @@ class WindowSettings {
|
||||
/** @brief ContextSettings Small class that contains the renderer context information */
|
||||
class ContextSettings {
|
||||
public:
|
||||
static constexpr Int32 FrameRateLimitScreenRefreshRate = (std::numeric_limits<Int32>::max)() - 1;
|
||||
static constexpr Int32 FrameRateLimitScreenRefreshRate =
|
||||
( std::numeric_limits<Int32>::max )() - 1;
|
||||
|
||||
inline ContextSettings( bool vsync, Int32 frameRateLimit = FrameRateLimitScreenRefreshRate,
|
||||
Uint32 multisamples = 0, GraphicsLibraryVersion version = GLv_default,
|
||||
|
||||
50
premake4.lua
50
premake4.lua
@@ -171,7 +171,8 @@ newoption {
|
||||
trigger = "with-backend",
|
||||
description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.",
|
||||
allowed = {
|
||||
{ "SDL2", "SDL2" }
|
||||
{ "SDL2", "SDL2" },
|
||||
{ "SDL3", "SDL3" },
|
||||
}
|
||||
}
|
||||
newoption {
|
||||
@@ -802,17 +803,47 @@ function add_sdl2()
|
||||
end
|
||||
end
|
||||
|
||||
function add_sdl3()
|
||||
print("Using SDL3 backend");
|
||||
files { "src/eepp/window/backend/SDL3/*.cpp" }
|
||||
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_3" }
|
||||
|
||||
if not can_add_static_backend("SDL3") then
|
||||
if not os.is_real("emscripten") then
|
||||
table.insert( link_list, get_backend_link_name( "SDL3" ) )
|
||||
end
|
||||
else
|
||||
insert_static_backend( "SDL3" )
|
||||
end
|
||||
end
|
||||
|
||||
function set_apple_config()
|
||||
if is_xcode() or _OPTIONS["use-frameworks"] then
|
||||
linkoptions { "-F /Library/Frameworks" }
|
||||
buildoptions { "-F /Library/Frameworks" }
|
||||
includedirs { "/Library/Frameworks/SDL2.framework/Headers" }
|
||||
if table.contains(backends, "SDL2") then
|
||||
includedirs { "/Library/Frameworks/SDL2.framework/Headers" }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
includedirs { "/Library/Frameworks/SDL3.framework/Headers" }
|
||||
end
|
||||
end
|
||||
if os.is("macosx") then
|
||||
defines { "EE_SDL2_FROM_ROOTPATH" }
|
||||
if table.contains(backends, "SDL2") then
|
||||
defines { "EE_SDL2_FROM_ROOTPATH" }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
defines { "EE_SDL3_FROM_ROOTPATH" }
|
||||
end
|
||||
if not is_xcode() and not _OPTIONS["use-frameworks"] then
|
||||
local sdl2flags = popen("sdl2-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl2flags }
|
||||
if table.contains(backends, "SDL2") then
|
||||
local sdl2flags = popen("sdl2-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl2flags }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
local sdl3flags = popen("sdl3-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl3flags }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -890,9 +921,16 @@ function select_backend()
|
||||
add_sdl2()
|
||||
end
|
||||
|
||||
if backend_is("SDL3", "SDL3") then
|
||||
print("Selected SDL3")
|
||||
add_sdl3()
|
||||
end
|
||||
|
||||
-- If the selected backend is not present, try to find one present
|
||||
if not backend_selected then
|
||||
if os_findlib("SDL2", "SDL2") then
|
||||
if os_findlib("SDL3", "SDL3") then
|
||||
add_sdl3()
|
||||
elseif os_findlib("SDL2", "SDL2") then
|
||||
add_sdl2()
|
||||
else
|
||||
print("ERROR: Couldnt find any backend. Forced SDL2.")
|
||||
|
||||
61
premake5.lua
61
premake5.lua
@@ -24,6 +24,7 @@ newoption {
|
||||
description = "Select the backend to use for window and input handling.\n\t\t\tIf no backend is selected or if the selected is not installed the script will search for a backend present in the system, and will use it.",
|
||||
allowed = {
|
||||
{ "SDL2", "SDL2" },
|
||||
{ "SDL3", "SDL3" },
|
||||
}
|
||||
}
|
||||
newoption {
|
||||
@@ -642,17 +643,45 @@ function add_sdl2()
|
||||
table.insert( backends, "SDL2" )
|
||||
end
|
||||
|
||||
function add_sdl3()
|
||||
print("Using SDL3 backend");
|
||||
if not can_add_static_backend("SDL3") then
|
||||
table.insert( link_list, get_backend_link_name( "SDL3" ) )
|
||||
else
|
||||
print("Using static backend")
|
||||
insert_static_backend( "SDL3" )
|
||||
end
|
||||
|
||||
table.insert( backends, "SDL3" )
|
||||
end
|
||||
|
||||
function set_apple_config()
|
||||
if is_xcode() or _OPTIONS["use-frameworks"] then
|
||||
linkoptions { "-F /Library/Frameworks" }
|
||||
buildoptions { "-F /Library/Frameworks" }
|
||||
incdirs { "/Library/Frameworks/SDL2.framework/Headers" }
|
||||
if table.contains(backends, "SDL2") then
|
||||
incdirs { "/Library/Frameworks/SDL2.framework/Headers" }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
incdirs { "/Library/Frameworks/SDL3.framework/Headers" }
|
||||
end
|
||||
end
|
||||
if os.istarget("macosx") then
|
||||
defines { "EE_SDL2_FROM_ROOTPATH" }
|
||||
if table.contains(backends, "SDL2") then
|
||||
defines { "EE_SDL2_FROM_ROOTPATH" }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
defines { "EE_SDL3_FROM_ROOTPATH" }
|
||||
end
|
||||
if not is_xcode() and not _OPTIONS["use-frameworks"] then
|
||||
local sdl2flags = popen("sdl2-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl2flags }
|
||||
if table.contains(backends, "SDL2") then
|
||||
local sdl2flags = popen("sdl2-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl2flags }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
local sdl3flags = popen("sdl3-config --cflags"):gsub("\n", "")
|
||||
buildoptions { sdl3flags }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -718,9 +747,16 @@ function select_backend()
|
||||
add_sdl2()
|
||||
end
|
||||
|
||||
if backend_is("SDL3", "SDL3") then
|
||||
print("Selected SDL3")
|
||||
add_sdl3()
|
||||
end
|
||||
|
||||
-- If the selected backend is not present, try to find one present
|
||||
if not backend_selected then
|
||||
if os_findlib("SDL2", "SDL2") then
|
||||
if os_findlib("SDL3", "SDL3") then
|
||||
add_sdl3()
|
||||
elseif os_findlib("SDL2", "SDL2") then
|
||||
add_sdl2()
|
||||
else
|
||||
print("ERROR: Couldnt find any backend. Forced SDL2.")
|
||||
@@ -814,6 +850,11 @@ function build_eepp( build_name )
|
||||
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" }
|
||||
end
|
||||
|
||||
if table.contains( backends, "SDL3" ) then
|
||||
files { "src/eepp/window/backend/SDL3/*.cpp" }
|
||||
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_3" }
|
||||
end
|
||||
|
||||
multiple_insert( link_list, os_links )
|
||||
|
||||
links { link_list }
|
||||
@@ -1666,8 +1707,14 @@ workspace "eepp"
|
||||
links { "eterm-static", "languages-syntax-highlighting-static" }
|
||||
incdirs { "src/modules/eterm/include/" }
|
||||
language "C++"
|
||||
files { "src/tests/unit_tests/*.cpp" }
|
||||
build_link_configuration( "eepp-unit_tests", true )
|
||||
files { "src/tests/unit_tests/*.cpp" }
|
||||
build_link_configuration( "eepp-unit_tests", true )
|
||||
if table.contains(backends, "SDL2") then
|
||||
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_2" }
|
||||
end
|
||||
if table.contains(backends, "SDL3") then
|
||||
defines { "EE_BACKEND_SDL_ACTIVE", "EE_SDL_VERSION_3" }
|
||||
end
|
||||
|
||||
if os.isfile("external_projects.lua") then
|
||||
dofile("external_projects.lua")
|
||||
|
||||
34
src/eepp/window/backend/SDL3/backendsdl3.cpp
Normal file
34
src/eepp/window/backend/SDL3/backendsdl3.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <eepp/window/backend/SDL3/backendsdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#if ( EE_PLATFORM == EE_PLATFORM_ANDROID || EE_PLATFORM == EE_PLATFORM_IOS ) && defined( main )
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
#if EE_PLATFORM != EE_PLATFORM_ANDROID && EE_PLATFORM != EE_PLATFORM_IOS && \
|
||||
EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN && !defined( EE_COMPILER_MSVC ) && \
|
||||
!defined( EE_SDL3_FROM_ROOTPATH )
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
WindowBackendSDL3::WindowBackendSDL3() : WindowBackendLibrary() {
|
||||
SDL_SetHint( SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0" );
|
||||
// The following hints are not available in SDL3 (or renamed)
|
||||
// SDL_SetHint( SDL_HINT_IME_SHOW_UI, "1" );
|
||||
// SDL_SetHint( SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1" );
|
||||
}
|
||||
|
||||
WindowBackendSDL3::~WindowBackendSDL3() {
|
||||
#if EE_PLATFORM != EE_PLATFORM_MACOS
|
||||
SDL_Quit();
|
||||
#endif
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
25
src/eepp/window/backend/SDL3/backendsdl3.hpp
Normal file
25
src/eepp/window/backend/SDL3/backendsdl3.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef EE_WINDOWCBACKENDSDL3_HPP
|
||||
#define EE_WINDOWCBACKENDSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/window/backend/SDL3/displaymanagersdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/windowsdl3.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API WindowBackendSDL3 : public WindowBackendLibrary {
|
||||
public:
|
||||
WindowBackendSDL3();
|
||||
|
||||
~WindowBackendSDL3();
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
32
src/eepp/window/backend/SDL3/base.hpp
Normal file
32
src/eepp/window/backend/SDL3/base.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef EE_WINDOWBACKEND_BASE_SDL3_HPP
|
||||
#define EE_WINDOWBACKEND_BASE_SDL3_HPP
|
||||
|
||||
#include <eepp/core.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL_ACTIVE
|
||||
|
||||
#if defined( EE_SDL_VERSION_3 )
|
||||
#ifndef EE_BACKEND_SDL3
|
||||
#define EE_BACKEND_SDL3
|
||||
#endif
|
||||
|
||||
#if ( EE_PLATFORM == EE_PLATFORM_ANDROID || EE_PLATFORM == EE_PLATFORM_IOS ) && defined( main )
|
||||
#undef main
|
||||
#endif
|
||||
|
||||
#if EE_PLATFORM != EE_PLATFORM_ANDROID && EE_PLATFORM != EE_PLATFORM_IOS && \
|
||||
EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN && !defined( EE_COMPILER_MSVC ) && \
|
||||
!defined( EE_SDL3_FROM_ROOTPATH )
|
||||
#include <SDL3/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
#else
|
||||
#ifndef EE_BACKEND_SDL_1_2
|
||||
#define EE_BACKEND_SDL_1_2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
45
src/eepp/window/backend/SDL3/clipboardsdl3.cpp
Normal file
45
src/eepp/window/backend/SDL3/clipboardsdl3.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include <eepp/system/log.hpp>
|
||||
#include <eepp/window/backend/SDL3/clipboardsdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/windowsdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
ClipboardSDL::ClipboardSDL( EE::Window::Window* window ) : Clipboard( window ) {}
|
||||
|
||||
ClipboardSDL::~ClipboardSDL() {}
|
||||
|
||||
void ClipboardSDL::init() {}
|
||||
|
||||
void ClipboardSDL::setText( const std::string& text ) {
|
||||
SDL_SetClipboardText( text.c_str() );
|
||||
}
|
||||
|
||||
std::string ClipboardSDL::getText() {
|
||||
char* text = SDL_GetClipboardText();
|
||||
std::string str( text ? text : "" );
|
||||
SDL_free( text );
|
||||
return str;
|
||||
}
|
||||
|
||||
bool ClipboardSDL::hasPrimarySelection() const {
|
||||
// SDL3 may not have primary selection support
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string ClipboardSDL::getPrimarySelectionText() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
void ClipboardSDL::setPrimarySelectionText( const std::string& text ) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
String ClipboardSDL::getWideText() {
|
||||
return String::fromUtf8( getText() );
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
41
src/eepp/window/backend/SDL3/clipboardsdl3.hpp
Normal file
41
src/eepp/window/backend/SDL3/clipboardsdl3.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef EE_WINDOWCCLIPBOARDSDL3_HPP
|
||||
#define EE_WINDOWCCLIPBOARDSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/window/base.hpp>
|
||||
#include <eepp/window/clipboard.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API ClipboardSDL : public Clipboard {
|
||||
public:
|
||||
virtual ~ClipboardSDL();
|
||||
|
||||
std::string getText();
|
||||
|
||||
String getWideText();
|
||||
|
||||
void setText( const std::string& text );
|
||||
|
||||
bool hasPrimarySelection() const;
|
||||
|
||||
std::string getPrimarySelectionText();
|
||||
|
||||
void setPrimarySelectionText( const std::string& text );
|
||||
|
||||
protected:
|
||||
friend class WindowSDL;
|
||||
|
||||
ClipboardSDL( EE::Window::Window* window );
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
#endif
|
||||
85
src/eepp/window/backend/SDL3/cursormanagersdl3.cpp
Normal file
85
src/eepp/window/backend/SDL3/cursormanagersdl3.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include <eepp/window/backend/SDL3/cursormanagersdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/cursorsdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
static SDL_Cursor* SDL_SYS_CURSORS[Cursor::SysCursorCount] = { 0 };
|
||||
|
||||
static SDL_Cursor* getLoadCursor( const Cursor::SysType& cursor ) {
|
||||
if ( 0 == SDL_SYS_CURSORS[cursor] ) {
|
||||
SDL_SYS_CURSORS[cursor] = SDL_CreateSystemCursor( (SDL_SystemCursor)cursor );
|
||||
}
|
||||
return SDL_SYS_CURSORS[cursor];
|
||||
}
|
||||
|
||||
CursorManagerSDL::CursorManagerSDL( EE::Window::Window* window ) : CursorManager( window ) {}
|
||||
|
||||
Cursor* CursorManagerSDL::create( Texture* tex, const Vector2i& hotspot, const std::string& name ) {
|
||||
return eeNew( CursorSDL, ( tex, hotspot, name, mWindow ) );
|
||||
}
|
||||
|
||||
Cursor* CursorManagerSDL::create( Image* img, const Vector2i& hotspot, const std::string& name ) {
|
||||
return eeNew( CursorSDL, ( img, hotspot, name, mWindow ) );
|
||||
}
|
||||
|
||||
Cursor* CursorManagerSDL::create( const std::string& path, const Vector2i& hotspot,
|
||||
const std::string& name ) {
|
||||
return eeNew( CursorSDL, ( path, hotspot, name, mWindow ) );
|
||||
}
|
||||
|
||||
void CursorManagerSDL::set( Cursor* cursor ) {
|
||||
if ( NULL != cursor && cursor != mCurrent ) {
|
||||
SDL_SetCursor( reinterpret_cast<CursorSDL*>( cursor )->GetCursor() );
|
||||
mCurrent = cursor;
|
||||
mCurSysCursor = false;
|
||||
mSysCursor = Cursor::SysCursorNone;
|
||||
}
|
||||
}
|
||||
|
||||
void CursorManagerSDL::set( Cursor::SysType syscurid ) {
|
||||
if ( syscurid != mSysCursor ) {
|
||||
SDL_SetCursor( getLoadCursor( syscurid ) );
|
||||
mCurrent = NULL;
|
||||
mCurSysCursor = true;
|
||||
mSysCursor = syscurid;
|
||||
}
|
||||
}
|
||||
|
||||
void CursorManagerSDL::show() {
|
||||
setVisible( true );
|
||||
}
|
||||
|
||||
void CursorManagerSDL::hide() {
|
||||
setVisible( false );
|
||||
}
|
||||
|
||||
void CursorManagerSDL::setVisible( bool visible ) {
|
||||
if ( visible )
|
||||
SDL_ShowCursor();
|
||||
else
|
||||
SDL_HideCursor();
|
||||
mVisible = visible;
|
||||
}
|
||||
|
||||
void CursorManagerSDL::remove( Cursor* cursor, bool Delete ) {
|
||||
CursorManager::remove( cursor, Delete );
|
||||
}
|
||||
|
||||
void CursorManagerSDL::reload() {
|
||||
if ( mVisible ) {
|
||||
show();
|
||||
if ( mCurSysCursor ) {
|
||||
set( mSysCursor );
|
||||
} else {
|
||||
set( mCurrent );
|
||||
}
|
||||
} else {
|
||||
hide();
|
||||
}
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
41
src/eepp/window/backend/SDL3/cursormanagersdl3.hpp
Normal file
41
src/eepp/window/backend/SDL3/cursormanagersdl3.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef EE_WINDOWCCURSORMANAGERSDL3_HPP
|
||||
#define EE_WINDOWCCURSORMANAGERSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/cursormanager.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
using namespace EE::Window;
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API CursorManagerSDL : public CursorManager {
|
||||
public:
|
||||
CursorManagerSDL( EE::Window::Window* window );
|
||||
|
||||
Cursor* create( Texture* tex, const Vector2i& hotspot, const std::string& name );
|
||||
|
||||
Cursor* create( Image* img, const Vector2i& hotspot, const std::string& name );
|
||||
|
||||
Cursor* create( const std::string& path, const Vector2i& hotspot, const std::string& name );
|
||||
|
||||
void set( Cursor* cursor );
|
||||
|
||||
void set( Cursor::SysType syscurid );
|
||||
|
||||
void show();
|
||||
|
||||
void hide();
|
||||
|
||||
void setVisible( bool visible );
|
||||
|
||||
void remove( Cursor* cursor, bool Delete = false );
|
||||
|
||||
void reload();
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
#endif
|
||||
65
src/eepp/window/backend/SDL3/cursorsdl3.cpp
Normal file
65
src/eepp/window/backend/SDL3/cursorsdl3.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include <eepp/window/backend/SDL3/cursorsdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <cstring>
|
||||
#include <eepp/graphics/image.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
CursorSDL::CursorSDL( Texture* tex, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window ) :
|
||||
Cursor( tex, hotspot, name, window ), mCursor( nullptr ) {
|
||||
create();
|
||||
}
|
||||
|
||||
CursorSDL::CursorSDL( Graphics::Image* img, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window ) :
|
||||
Cursor( img, hotspot, name, window ), mCursor( nullptr ) {
|
||||
create();
|
||||
}
|
||||
|
||||
CursorSDL::CursorSDL( const std::string& path, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window ) :
|
||||
Cursor( path, hotspot, name, window ), mCursor( nullptr ) {
|
||||
create();
|
||||
}
|
||||
|
||||
CursorSDL::~CursorSDL() {
|
||||
if ( nullptr != mCursor )
|
||||
SDL_DestroyCursor( mCursor );
|
||||
}
|
||||
|
||||
void CursorSDL::create() {
|
||||
if ( nullptr == mImage )
|
||||
return;
|
||||
|
||||
int x = mImage->getWidth();
|
||||
int y = mImage->getHeight();
|
||||
int c = mImage->getChannels();
|
||||
|
||||
SDL_Surface* surface = SDL_CreateSurface( x, y, SDL_PIXELFORMAT_RGBA32 );
|
||||
if ( !surface )
|
||||
return;
|
||||
|
||||
Uint8* src = (Uint8*)mImage->getPixels();
|
||||
Uint8* dst = (Uint8*)surface->pixels;
|
||||
int srcPitch = x * c;
|
||||
int dstPitch = surface->pitch;
|
||||
|
||||
for ( int row = 0; row < y; ++row ) {
|
||||
memcpy( dst + row * dstPitch, src + row * srcPitch, srcPitch );
|
||||
}
|
||||
|
||||
mCursor = SDL_CreateColorCursor( surface, mHotSpot.x, mHotSpot.y );
|
||||
|
||||
SDL_DestroySurface( surface );
|
||||
}
|
||||
|
||||
SDL_Cursor* CursorSDL::GetCursor() const {
|
||||
return mCursor;
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
37
src/eepp/window/backend/SDL3/cursorsdl3.hpp
Normal file
37
src/eepp/window/backend/SDL3/cursorsdl3.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef EE_WINDOWCCURSORSDL3_HPP
|
||||
#define EE_WINDOWCCURSORSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/cursor.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API CursorSDL : public Cursor {
|
||||
public:
|
||||
SDL_Cursor* GetCursor() const;
|
||||
|
||||
protected:
|
||||
friend class CursorManagerSDL;
|
||||
|
||||
SDL_Cursor* mCursor;
|
||||
|
||||
CursorSDL( Texture* tex, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window );
|
||||
|
||||
CursorSDL( Graphics::Image* img, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window );
|
||||
|
||||
CursorSDL( const std::string& path, const Vector2i& hotspot, const std::string& name,
|
||||
EE::Window::Window* window );
|
||||
|
||||
virtual ~CursorSDL();
|
||||
|
||||
void create();
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
#endif
|
||||
159
src/eepp/window/backend/SDL3/displaymanagersdl3.cpp
Normal file
159
src/eepp/window/backend/SDL3/displaymanagersdl3.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/backend/SDL3/displaymanagersdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
DisplaySDL3::DisplaySDL3( int index, SDL_DisplayID displayId ) :
|
||||
Display( index ), mDisplayId( displayId ) {}
|
||||
|
||||
std::string DisplaySDL3::getName() const {
|
||||
return std::string( mDisplayId ? SDL_GetDisplayName( mDisplayId ) : "Unknown" );
|
||||
}
|
||||
|
||||
Rect DisplaySDL3::getBounds() const {
|
||||
SDL_Rect r{};
|
||||
if ( mDisplayId && SDL_GetDisplayBounds( mDisplayId, &r ) == 0 )
|
||||
return Rect( r.x, r.y, r.w, r.h );
|
||||
return Rect();
|
||||
}
|
||||
|
||||
Rect DisplaySDL3::getUsableBounds() const {
|
||||
SDL_Rect r{};
|
||||
if ( mDisplayId && SDL_GetDisplayUsableBounds( mDisplayId, &r ) == 0 )
|
||||
return Rect( r.x, r.y, r.w, r.h );
|
||||
return Rect();
|
||||
}
|
||||
|
||||
Float DisplaySDL3::getDPI() {
|
||||
float scale = 1.0f;
|
||||
if ( mDisplayId ) {
|
||||
scale = SDL_GetDisplayContentScale( mDisplayId );
|
||||
if ( scale <= 0 )
|
||||
scale = 1.0f;
|
||||
}
|
||||
return 96.0f * scale;
|
||||
}
|
||||
|
||||
const int& DisplaySDL3::getIndex() const {
|
||||
return index;
|
||||
}
|
||||
|
||||
DisplayMode DisplaySDL3::getCurrentMode() const {
|
||||
const SDL_DisplayMode* mode = mDisplayId ? SDL_GetCurrentDisplayMode( mDisplayId ) : nullptr;
|
||||
if ( mode )
|
||||
return DisplayMode( mode->w, mode->h, static_cast<int>( mode->refresh_rate ), index );
|
||||
return DisplayMode( 0, 0, 0, index );
|
||||
}
|
||||
|
||||
DisplayMode DisplaySDL3::getClosestDisplayMode( DisplayMode wantedMode ) const {
|
||||
if ( !mDisplayId )
|
||||
return DisplayMode( 0, 0, 0, index );
|
||||
|
||||
SDL_DisplayMode closest;
|
||||
if ( SDL_GetClosestFullscreenDisplayMode( mDisplayId, wantedMode.Width, wantedMode.Height,
|
||||
static_cast<float>( wantedMode.RefreshRate ), true,
|
||||
&closest ) ) {
|
||||
return DisplayMode( closest.w, closest.h, static_cast<int>( closest.refresh_rate ), index );
|
||||
}
|
||||
return DisplayMode( 0, 0, 0, index );
|
||||
}
|
||||
|
||||
const std::vector<DisplayMode>& DisplaySDL3::getModes() const {
|
||||
if ( displayModes.empty() && mDisplayId ) {
|
||||
int count = 0;
|
||||
SDL_DisplayMode** modesArray = SDL_GetFullscreenDisplayModes( mDisplayId, &count );
|
||||
if ( modesArray ) {
|
||||
for ( int i = 0; i < count; i++ ) {
|
||||
SDL_DisplayMode* mode = modesArray[i];
|
||||
displayModes.push_back( DisplayMode(
|
||||
mode->w, mode->h, static_cast<int>( mode->refresh_rate ), index ) );
|
||||
}
|
||||
SDL_free( modesArray );
|
||||
}
|
||||
}
|
||||
return displayModes;
|
||||
}
|
||||
|
||||
Uint32 DisplaySDL3::getRefreshRate() const {
|
||||
return getCurrentMode().RefreshRate;
|
||||
}
|
||||
|
||||
Sizeu DisplaySDL3::getSize() const {
|
||||
DisplayMode mode = getCurrentMode();
|
||||
return { static_cast<unsigned int>( mode.Width ), static_cast<unsigned int>( mode.Height ) };
|
||||
}
|
||||
|
||||
int DisplayManagerSDL3::getDisplayCount() {
|
||||
if ( mDisplayIds.empty() ) {
|
||||
// Initialize SDL video if not already done, similar to SDL2 backend
|
||||
if ( !SDL_WasInit( SDL_INIT_VIDEO ) && !SDL_Init( SDL_INIT_VIDEO ) ) {
|
||||
Log::error( "DisplayManagerSDL3: Failed to initialize SDL video: %s", SDL_GetError() );
|
||||
return 0;
|
||||
}
|
||||
int count = 0;
|
||||
SDL_DisplayID* ids = SDL_GetDisplays( &count );
|
||||
if ( ids ) {
|
||||
mDisplayIds.assign( ids, ids + count );
|
||||
SDL_free( ids );
|
||||
}
|
||||
}
|
||||
return static_cast<int>( mDisplayIds.size() );
|
||||
}
|
||||
|
||||
Display* DisplayManagerSDL3::getDisplayIndex( int index ) {
|
||||
if ( displays.empty() ) {
|
||||
int count = getDisplayCount();
|
||||
if ( count > 0 && !mDisplayIds.empty() ) {
|
||||
for ( int i = 0; i < count; i++ ) {
|
||||
displays.push_back( eeNew( DisplaySDL3, ( i, mDisplayIds[i] ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return ( index >= 0 && index < (int)displays.size() ) ? displays[index] : nullptr;
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::enableScreenSaver() {
|
||||
SDL_EnableScreenSaver();
|
||||
SDL_SetHint( SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "1" );
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::disableScreenSaver() {
|
||||
SDL_DisableScreenSaver();
|
||||
SDL_SetHint( SDL_HINT_VIDEO_ALLOW_SCREENSAVER, "0" );
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::enableMouseFocusClickThrough() {
|
||||
SDL_SetHint( SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1" );
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::disableMouseFocusClickThrough() {
|
||||
SDL_SetHint( SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "0" );
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::disableBypassCompositor() {
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
SDL_SetHint( SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0" );
|
||||
#endif
|
||||
}
|
||||
|
||||
void DisplayManagerSDL3::enableBypassCompositor() {
|
||||
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR
|
||||
SDL_SetHint( SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "1" );
|
||||
#endif
|
||||
}
|
||||
|
||||
int DisplayManagerSDL3::getDisplayIndexFromID( SDL_DisplayID id ) const {
|
||||
for ( size_t i = 0; i < mDisplayIds.size(); ++i ) {
|
||||
if ( mDisplayIds[i] == id )
|
||||
return static_cast<int>( i );
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
64
src/eepp/window/backend/SDL3/displaymanagersdl3.hpp
Normal file
64
src/eepp/window/backend/SDL3/displaymanagersdl3.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef EE_WINDOW_DISPLAYMANAGERSDL3_HPP
|
||||
#define EE_WINDOW_DISPLAYMANAGERSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/displaymanager.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API DisplaySDL3 : public Display {
|
||||
public:
|
||||
DisplaySDL3( int index, SDL_DisplayID displayId );
|
||||
|
||||
std::string getName() const;
|
||||
|
||||
Rect getBounds() const;
|
||||
|
||||
Rect getUsableBounds() const;
|
||||
|
||||
Float getDPI();
|
||||
|
||||
const int& getIndex() const;
|
||||
|
||||
DisplayMode getCurrentMode() const;
|
||||
|
||||
DisplayMode getClosestDisplayMode( DisplayMode wantedMode ) const;
|
||||
|
||||
const std::vector<DisplayMode>& getModes() const;
|
||||
|
||||
Uint32 getRefreshRate() const;
|
||||
|
||||
Sizeu getSize() const;
|
||||
|
||||
protected:
|
||||
mutable std::vector<DisplayMode> displayModes;
|
||||
SDL_DisplayID mDisplayId;
|
||||
};
|
||||
|
||||
class EE_API DisplayManagerSDL3 : public DisplayManager {
|
||||
public:
|
||||
int getDisplayCount();
|
||||
|
||||
Display* getDisplayIndex( int index );
|
||||
|
||||
void enableScreenSaver();
|
||||
|
||||
void disableScreenSaver();
|
||||
|
||||
void enableMouseFocusClickThrough();
|
||||
|
||||
void disableMouseFocusClickThrough();
|
||||
|
||||
void disableBypassCompositor();
|
||||
|
||||
void enableBypassCompositor();
|
||||
|
||||
int getDisplayIndexFromID( SDL_DisplayID id ) const;
|
||||
|
||||
protected:
|
||||
std::vector<SDL_DisplayID> mDisplayIds;
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
489
src/eepp/window/backend/SDL3/inputsdl3.cpp
Normal file
489
src/eepp/window/backend/SDL3/inputsdl3.cpp
Normal file
@@ -0,0 +1,489 @@
|
||||
#include <eepp/window/backend/SDL3/inputsdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/joystickmanagersdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/windowsdl3.hpp>
|
||||
#include <eepp/window/engine.hpp>
|
||||
#include <limits>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
InputSDL::InputSDL( Window* window ) :
|
||||
Input( window, eeNew( JoystickManagerSDL, () ) ), mDPIScale( 1.f ) {
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
mMouseSpeed = 1.75f;
|
||||
#endif
|
||||
}
|
||||
|
||||
InputSDL::~InputSDL() {}
|
||||
|
||||
void InputSDL::update() {
|
||||
SDL_Event SDLEvent;
|
||||
cleanStates();
|
||||
|
||||
++mEventsSentId;
|
||||
if ( mEventsSentId == std::numeric_limits<Uint64>::max() )
|
||||
mEventsSentId = 0;
|
||||
|
||||
if ( !mQueuedEvents.empty() ) {
|
||||
for ( const auto& prevEvent : mQueuedEvents )
|
||||
sendEvent( prevEvent );
|
||||
mQueuedEvents.clear();
|
||||
}
|
||||
while ( SDL_PollEvent( &SDLEvent ) )
|
||||
sendEvent( SDLEvent );
|
||||
InputEvent endProcessingEvent;
|
||||
endProcessingEvent.Type = InputEvent::EventsSent;
|
||||
processEvent( &endProcessingEvent );
|
||||
}
|
||||
|
||||
void InputSDL::waitEvent( const Time& timeout ) {
|
||||
SDL_Event SDLEvent;
|
||||
if ( timeout == Time::Zero ) {
|
||||
if ( SDL_WaitEvent( &SDLEvent ) )
|
||||
mQueuedEvents.emplace_back( SDLEvent );
|
||||
} else if ( SDL_WaitEventTimeout( &SDLEvent, (int)timeout.asMilliseconds() ) ) {
|
||||
if ( SDLEvent.type != SDL_EVENT_FIRST )
|
||||
mQueuedEvents.emplace_back( SDLEvent );
|
||||
}
|
||||
}
|
||||
|
||||
bool InputSDL::grabInput() {
|
||||
SDL_Window* win = static_cast<WindowSDL*>( mWindow )->getSDLWindow();
|
||||
return SDL_GetWindowMouseGrab( win );
|
||||
}
|
||||
|
||||
void InputSDL::grabInput( const bool& Grab ) {
|
||||
SDL_Window* win = static_cast<WindowSDL*>( mWindow )->getSDLWindow();
|
||||
SDL_SetWindowMouseGrab( win, Grab );
|
||||
}
|
||||
|
||||
void InputSDL::injectMousePos( const Uint16& x, const Uint16& y ) {
|
||||
SDL_Window* win = static_cast<WindowSDL*>( mWindow )->getSDLWindow();
|
||||
SDL_WarpMouseInWindow( win, static_cast<float>( x ), static_cast<float>( y ) );
|
||||
}
|
||||
|
||||
Vector2i InputSDL::queryMousePos() {
|
||||
Vector2i mousePos;
|
||||
float tempMouseX, tempMouseY;
|
||||
int tempWinPosX, tempWinPosY;
|
||||
SDL_Window* win = static_cast<WindowSDL*>( mWindow )->getSDLWindow();
|
||||
SDL_GetGlobalMouseState( &tempMouseX, &tempMouseY );
|
||||
SDL_GetWindowPosition( win, &tempWinPosX, &tempWinPosY );
|
||||
mousePos.x = static_cast<Int32>( tempMouseX ) - tempWinPosX;
|
||||
mousePos.y = static_cast<Int32>( tempMouseY ) - tempWinPosY;
|
||||
return mousePos;
|
||||
}
|
||||
|
||||
void InputSDL::captureMouse( const bool& capture ) {
|
||||
SDL_CaptureMouse( capture );
|
||||
}
|
||||
|
||||
bool InputSDL::isMouseCaptured() const {
|
||||
SDL_Window* win = static_cast<WindowSDL*>( mWindow )->getSDLWindow();
|
||||
return SDL_GetWindowFlags( win ) & SDL_WINDOW_MOUSE_CAPTURE;
|
||||
}
|
||||
|
||||
std::string InputSDL::getKeyName( const Keycode& keycode ) const {
|
||||
return std::string( SDL_GetKeyName( static_cast<SDL_Keycode>( keycode ) ) );
|
||||
}
|
||||
|
||||
Keycode InputSDL::getKeyFromName( const std::string& keycode ) const {
|
||||
return static_cast<Keycode>( SDL_GetKeyFromName( keycode.c_str() ) );
|
||||
}
|
||||
|
||||
std::string InputSDL::getScancodeName( const Scancode& scancode ) const {
|
||||
return SDL_GetScancodeName( static_cast<SDL_Scancode>( scancode ) );
|
||||
}
|
||||
|
||||
Scancode InputSDL::getScancodeFromName( const std::string& scancode ) const {
|
||||
return static_cast<Scancode>( SDL_GetScancodeFromName( scancode.c_str() ) );
|
||||
}
|
||||
|
||||
Keycode InputSDL::getKeyFromScancode( const Scancode& scancode ) const {
|
||||
return static_cast<Keycode>(
|
||||
SDL_GetKeyFromScancode( static_cast<SDL_Scancode>( scancode ), SDL_KMOD_NONE, 1 ) );
|
||||
}
|
||||
|
||||
Scancode InputSDL::getScancodeFromKey( const Keycode& keycode ) const {
|
||||
return static_cast<Scancode>(
|
||||
SDL_GetScancodeFromKey( static_cast<SDL_Keycode>( keycode ), nullptr ) );
|
||||
}
|
||||
|
||||
void InputSDL::init() {
|
||||
mDPIScale = mWindow->getScale();
|
||||
mMousePos = queryMousePos();
|
||||
}
|
||||
|
||||
void InputSDL::sendEvent( const SDL_Event& SDLEvent ) {
|
||||
InputEvent event;
|
||||
event.Type = InputEvent::NoEvent;
|
||||
event.WinID = 0;
|
||||
|
||||
switch ( SDLEvent.type ) {
|
||||
case SDL_EVENT_WINDOW_SHOWN: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowShown;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_HIDDEN: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 0;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowHidden;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_EXPOSED: {
|
||||
event.Type = InputEvent::VideoExpose;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.expose.type = event.Type;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MOVED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowMoved;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_RESIZED: {
|
||||
event.Type = InputEvent::VideoResize;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
mDPIScale = mWindow->getScale();
|
||||
event.resize.w = static_cast<int>( SDLEvent.window.data1 * mDPIScale );
|
||||
event.resize.h = static_cast<int>( SDLEvent.window.data2 * mDPIScale );
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowSizeChanged;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MINIMIZED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 0;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowMinimized;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowMaximized;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_RESTORED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowRestored;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowMouseEnter;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 0;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowMouseLeave;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowKeyboardFocusGain;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 0;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowKeyboardFocusLost;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 0;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowClose;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_HIT_TEST: {
|
||||
event.Type = InputEvent::Window;
|
||||
event.window.gain = 1;
|
||||
event.WinID = SDLEvent.window.windowID;
|
||||
event.window.type = InputEvent::WindowHitTest;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_TEXT_INPUT: {
|
||||
String txt = String::fromUtf8( std::string_view{ SDLEvent.text.text } );
|
||||
event.Type = InputEvent::TextInput;
|
||||
// Convert from nanoseconds (SDL3) to milliseconds (EE framework)
|
||||
event.text.timestamp = static_cast<Uint32>( SDLEvent.text.timestamp / 1000000ULL );
|
||||
event.WinID = SDLEvent.text.windowID;
|
||||
for ( size_t i = 0; i < txt.size() - 1; i++ ) {
|
||||
event.text.text = txt[i];
|
||||
processEvent( &event );
|
||||
}
|
||||
event.text.text = txt[txt.size() - 1];
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_TEXT_EDITING: {
|
||||
event.Type = InputEvent::TextEditing;
|
||||
event.textediting.text = SDLEvent.edit.text;
|
||||
event.textediting.start = SDLEvent.edit.start;
|
||||
event.textediting.length = SDLEvent.edit.length;
|
||||
event.WinID = SDLEvent.edit.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_KEY_DOWN: {
|
||||
event.Type = InputEvent::KeyDown;
|
||||
event.key.state = SDLEvent.key.down ? 1 : 0;
|
||||
event.key.which = SDLEvent.key.windowID;
|
||||
event.key.keysym.sym = static_cast<Keycode>( SDLEvent.key.key );
|
||||
event.key.keysym.scancode = static_cast<Scancode>( SDLEvent.key.scancode );
|
||||
event.key.keysym.mod = SDLEvent.key.mod;
|
||||
event.key.keysym.unicode = 0;
|
||||
event.WinID = SDLEvent.key.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_KEY_UP: {
|
||||
event.Type = InputEvent::KeyUp;
|
||||
event.key.state = SDLEvent.key.down ? 1 : 0;
|
||||
event.key.which = SDLEvent.key.windowID;
|
||||
event.key.keysym.sym = static_cast<Keycode>( SDLEvent.key.key );
|
||||
event.key.keysym.scancode = static_cast<Scancode>( SDLEvent.key.scancode );
|
||||
event.key.keysym.mod = SDLEvent.key.mod;
|
||||
event.key.keysym.unicode = 0;
|
||||
event.WinID = SDLEvent.key.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_MOTION: {
|
||||
event.Type = InputEvent::MouseMotion;
|
||||
event.motion.which = SDLEvent.motion.windowID;
|
||||
event.motion.state = SDLEvent.motion.state;
|
||||
event.motion.x = static_cast<Int16>( SDLEvent.motion.x * mDPIScale );
|
||||
event.motion.y = static_cast<Int16>( SDLEvent.motion.y * mDPIScale );
|
||||
event.motion.xrel = static_cast<Int16>( SDLEvent.motion.xrel * mDPIScale );
|
||||
event.motion.yrel = static_cast<Int16>( SDLEvent.motion.yrel * mDPIScale );
|
||||
event.WinID = SDLEvent.motion.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||
event.Type = InputEvent::MouseButtonDown;
|
||||
event.button.button = SDLEvent.button.button;
|
||||
event.button.which = SDLEvent.button.windowID;
|
||||
event.button.state = SDLEvent.button.down ? 1 : 0;
|
||||
event.button.x = static_cast<Int16>( SDLEvent.button.x * mDPIScale );
|
||||
event.button.y = static_cast<Int16>( SDLEvent.button.y * mDPIScale );
|
||||
event.WinID = SDLEvent.button.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||
event.Type = InputEvent::MouseButtonUp;
|
||||
event.button.button = SDLEvent.button.button;
|
||||
event.button.which = SDLEvent.button.windowID;
|
||||
event.button.state = SDLEvent.button.down ? 1 : 0;
|
||||
event.button.x = static_cast<Int16>( SDLEvent.button.x * mDPIScale );
|
||||
event.button.y = static_cast<Int16>( SDLEvent.button.y * mDPIScale );
|
||||
event.WinID = SDLEvent.button.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_WHEEL: {
|
||||
Uint8 button;
|
||||
float x = SDLEvent.wheel.x;
|
||||
float y = SDLEvent.wheel.y;
|
||||
|
||||
if ( y == 0 && x == 0 )
|
||||
break;
|
||||
|
||||
if ( y > 0 ) {
|
||||
button = EE_BUTTON_WHEELUP;
|
||||
} else if ( y < 0 ) {
|
||||
button = EE_BUTTON_WHEELDOWN;
|
||||
} else if ( x > 0 ) {
|
||||
button = EE_BUTTON_WHEELRIGHT;
|
||||
} else if ( x < 0 ) {
|
||||
button = EE_BUTTON_WHEELLEFT;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get mouse position from the event (mouse_x, mouse_y are in window coordinates)
|
||||
event.button.button = button;
|
||||
event.button.x = static_cast<Int16>( SDLEvent.wheel.mouse_x * mDPIScale );
|
||||
event.button.y = static_cast<Int16>( SDLEvent.wheel.mouse_y * mDPIScale );
|
||||
event.button.which = SDLEvent.wheel.windowID;
|
||||
event.WinID = SDLEvent.wheel.windowID;
|
||||
|
||||
event.Type = InputEvent::MouseButtonDown;
|
||||
event.button.state = 1;
|
||||
processEvent( &event );
|
||||
|
||||
event.Type = InputEvent::MouseButtonUp;
|
||||
event.button.state = 0;
|
||||
processEvent( &event );
|
||||
|
||||
event.Type = InputEvent::MouseWheel;
|
||||
event.wheel.which = SDLEvent.wheel.windowID;
|
||||
event.wheel.direction = SDLEvent.wheel.direction == SDL_MOUSEWHEEL_NORMAL
|
||||
? InputEvent::WheelEvent::Normal
|
||||
: InputEvent::WheelEvent::Flipped;
|
||||
event.wheel.x = SDLEvent.wheel.x;
|
||||
event.wheel.y = SDLEvent.wheel.y;
|
||||
processEvent( &event );
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_AXIS_MOTION: {
|
||||
event.Type = InputEvent::JoyAxisMotion;
|
||||
event.jaxis.which = SDLEvent.jaxis.which;
|
||||
event.jaxis.axis = SDLEvent.jaxis.axis;
|
||||
event.jaxis.value = SDLEvent.jaxis.value;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_BALL_MOTION: {
|
||||
event.Type = InputEvent::JoyBallMotion;
|
||||
event.jball.which = SDLEvent.jball.which;
|
||||
event.jball.ball = SDLEvent.jball.ball;
|
||||
event.jball.xrel = SDLEvent.jball.xrel;
|
||||
event.jball.yrel = SDLEvent.jball.yrel;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_HAT_MOTION: {
|
||||
event.Type = InputEvent::JoyHatMotion;
|
||||
event.jhat.which = SDLEvent.jhat.which;
|
||||
event.jhat.value = SDLEvent.jhat.value;
|
||||
event.jhat.hat = SDLEvent.jhat.hat;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_DOWN: {
|
||||
event.Type = InputEvent::JoyButtonDown;
|
||||
event.jbutton.which = SDLEvent.jbutton.which;
|
||||
event.jbutton.state = SDLEvent.jbutton.down ? 1 : 0;
|
||||
event.jbutton.button = SDLEvent.jbutton.button;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_UP: {
|
||||
event.Type = InputEvent::JoyButtonUp;
|
||||
event.jbutton.which = SDLEvent.jbutton.which;
|
||||
event.jbutton.state = SDLEvent.jbutton.down ? 1 : 0;
|
||||
event.jbutton.button = SDLEvent.jbutton.button;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_ADDED: {
|
||||
// Could be used to dynamically add joysticks, but JoystickManager handles it
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_REMOVED: {
|
||||
// Could be used to dynamically remove joysticks
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_QUIT: {
|
||||
event.Type = InputEvent::Quit;
|
||||
event.quit.type = event.Type;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_DROP_FILE: {
|
||||
event.Type = InputEvent::FileDropped;
|
||||
event.file.file = SDLEvent.drop.data;
|
||||
event.WinID = SDLEvent.drop.windowID;
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_DROP_TEXT: {
|
||||
event.Type = InputEvent::TextDropped;
|
||||
event.textdrop.text = SDLEvent.drop.data;
|
||||
event.WinID = SDLEvent.drop.windowID;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if ( SDLEvent.type >= SDL_EVENT_USER && SDLEvent.type < SDL_EVENT_LAST ) {
|
||||
event.Type = InputEvent::EventUser + SDLEvent.type - SDL_EVENT_USER;
|
||||
event.user.type = event.Type;
|
||||
event.user.code = SDLEvent.user.code;
|
||||
event.user.data1 = SDLEvent.user.data1;
|
||||
event.user.data2 = SDLEvent.user.data2;
|
||||
event.WinID = SDLEvent.user.windowID;
|
||||
} else {
|
||||
event.Type = InputEvent::NoEvent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert SDL3 joystick ID (which is a handle) to index for framework compatibility
|
||||
if ( event.Type == InputEvent::JoyAxisMotion || event.Type == InputEvent::JoyBallMotion ||
|
||||
event.Type == InputEvent::JoyHatMotion || event.Type == InputEvent::JoyButtonDown ||
|
||||
event.Type == InputEvent::JoyButtonUp ) {
|
||||
SDL_JoystickID joyId = 0;
|
||||
switch ( event.Type ) {
|
||||
case InputEvent::JoyAxisMotion:
|
||||
joyId = SDLEvent.jaxis.which;
|
||||
break;
|
||||
case InputEvent::JoyBallMotion:
|
||||
joyId = SDLEvent.jball.which;
|
||||
break;
|
||||
case InputEvent::JoyHatMotion:
|
||||
joyId = SDLEvent.jhat.which;
|
||||
break;
|
||||
case InputEvent::JoyButtonDown:
|
||||
case InputEvent::JoyButtonUp:
|
||||
joyId = SDLEvent.jbutton.which;
|
||||
break;
|
||||
default:
|
||||
joyId = 0;
|
||||
break;
|
||||
}
|
||||
auto* mgr = static_cast<JoystickManagerSDL*>( mJoystickManager );
|
||||
Uint32 idx = mgr->getIndexFromID( joyId );
|
||||
if ( UINT32_MAX == idx ) {
|
||||
// Unknown joystick ID, drop event
|
||||
return;
|
||||
}
|
||||
// Overwrite the 'which' field with the correct index
|
||||
switch ( event.Type ) {
|
||||
case InputEvent::JoyAxisMotion:
|
||||
event.jaxis.which = idx;
|
||||
break;
|
||||
case InputEvent::JoyBallMotion:
|
||||
event.jball.which = idx;
|
||||
break;
|
||||
case InputEvent::JoyHatMotion:
|
||||
event.jhat.which = idx;
|
||||
break;
|
||||
case InputEvent::JoyButtonDown:
|
||||
case InputEvent::JoyButtonUp:
|
||||
event.jbutton.which = idx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EE::Window::Window* win = nullptr;
|
||||
|
||||
if ( InputEvent::NoEvent != event.Type ) {
|
||||
if ( event.WinID == mWindow->getWindowID() || event.WinID == 0 ) {
|
||||
processEvent( &event );
|
||||
} else if ( ( win = EE::Window::Engine::instance()->getWindowID( event.WinID ) ) ) {
|
||||
win->getInput()->processEvent( &event );
|
||||
} else {
|
||||
processEvent( &event );
|
||||
}
|
||||
}
|
||||
|
||||
// In SDL3, drop event data is managed by SDL, do not free
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
61
src/eepp/window/backend/SDL3/inputsdl3.hpp
Normal file
61
src/eepp/window/backend/SDL3/inputsdl3.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef EE_WINDOWCINPUTSDL3_HPP
|
||||
#define EE_WINDOWCINPUTSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/window/input.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API InputSDL : public Input {
|
||||
public:
|
||||
~InputSDL();
|
||||
|
||||
void update();
|
||||
|
||||
void waitEvent( const Time& timeout = Time::Zero );
|
||||
|
||||
bool grabInput();
|
||||
|
||||
void grabInput( const bool& Grab );
|
||||
|
||||
void injectMousePos( const Uint16& x, const Uint16& y );
|
||||
|
||||
Vector2i queryMousePos();
|
||||
|
||||
void captureMouse( const bool& capture );
|
||||
|
||||
bool isMouseCaptured() const;
|
||||
|
||||
std::string getKeyName( const Keycode& keycode ) const;
|
||||
|
||||
Keycode getKeyFromName( const std::string& keycode ) const;
|
||||
|
||||
std::string getScancodeName( const Scancode& scancode ) const;
|
||||
|
||||
Scancode getScancodeFromName( const std::string& scancode ) const;
|
||||
|
||||
Keycode getKeyFromScancode( const Scancode& scancode ) const;
|
||||
|
||||
Scancode getScancodeFromKey( const Keycode& scancode ) const;
|
||||
|
||||
protected:
|
||||
friend class WindowSDL;
|
||||
Float mDPIScale;
|
||||
std::vector<SDL_Event> mQueuedEvents;
|
||||
|
||||
InputSDL( EE::Window::Window* window );
|
||||
|
||||
void init();
|
||||
|
||||
void sendEvent( const SDL_Event& SDLEvent );
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
92
src/eepp/window/backend/SDL3/joystickmanagersdl3.cpp
Normal file
92
src/eepp/window/backend/SDL3/joystickmanagersdl3.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <eepp/window/backend/SDL3/joystickmanagersdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/joysticksdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
namespace {
|
||||
void closeSubsystem() {
|
||||
#if EE_PLATFORM != EE_PLATFORM_MACOS && EE_PLATFORM != EE_PLATFORM_IOS
|
||||
if ( SDL_WasInit( SDL_INIT_JOYSTICK ) )
|
||||
SDL_QuitSubSystem( SDL_INIT_JOYSTICK );
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
JoystickManagerSDL::JoystickManagerSDL() :
|
||||
JoystickManager(), mAsyncInit( &JoystickManagerSDL::openAsync, this ) {}
|
||||
|
||||
JoystickManagerSDL::~JoystickManagerSDL() {
|
||||
for ( Uint32 i = 0; i < mCount; i++ )
|
||||
eeSAFE_DELETE( mJoysticks[i] );
|
||||
closeSubsystem();
|
||||
mInit = false;
|
||||
}
|
||||
|
||||
void JoystickManagerSDL::update() {
|
||||
if ( mInit ) {
|
||||
SDL_UpdateJoysticks();
|
||||
for ( Uint32 i = 0; i < mCount; i++ )
|
||||
if ( nullptr != mJoysticks[i] )
|
||||
mJoysticks[i]->update();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickManagerSDL::openAsync() {
|
||||
Sys::sleep( Milliseconds( 500 ) );
|
||||
|
||||
int error = SDL_InitSubSystem( SDL_INIT_JOYSTICK );
|
||||
|
||||
if ( !error ) {
|
||||
int count = 0;
|
||||
SDL_JoystickID* ids = SDL_GetJoysticks( &count );
|
||||
if ( ids ) {
|
||||
mIds.assign( ids, ids + count );
|
||||
mCount = static_cast<Uint32>( count );
|
||||
SDL_free( ids );
|
||||
} else {
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
// Build ID -> index mapping
|
||||
mIdToIndex.clear();
|
||||
for ( Uint32 i = 0; i < mCount; i++ ) {
|
||||
mIdToIndex[mIds[i]] = i;
|
||||
create( i );
|
||||
}
|
||||
|
||||
mInit = true;
|
||||
|
||||
if ( mOpenCb )
|
||||
mOpenCb();
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickManagerSDL::open( OpenCb openCb ) {
|
||||
mOpenCb = openCb;
|
||||
mAsyncInit.launch();
|
||||
}
|
||||
|
||||
void JoystickManagerSDL::close() {
|
||||
closeSubsystem();
|
||||
mInit = false;
|
||||
}
|
||||
|
||||
void JoystickManagerSDL::create( const Uint32& index ) {
|
||||
if ( nullptr != mJoysticks[index] )
|
||||
mJoysticks[index]->reOpen();
|
||||
else
|
||||
mJoysticks[index] = eeNew( JoystickSDL, ( index, mIds[index] ) );
|
||||
}
|
||||
|
||||
Uint32 JoystickManagerSDL::getIndexFromID( SDL_JoystickID id ) const {
|
||||
auto it = mIdToIndex.find( id );
|
||||
if ( it != mIdToIndex.end() )
|
||||
return it->second;
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
46
src/eepp/window/backend/SDL3/joystickmanagersdl3.hpp
Normal file
46
src/eepp/window/backend/SDL3/joystickmanagersdl3.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef EE_WINDOWCJOYSTICKMANAGERSDL3_HPP
|
||||
#define EE_WINDOWCJOYSTICKMANAGERSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/system/thread.hpp>
|
||||
#include <eepp/window/joystickmanager.hpp>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API JoystickManagerSDL : public JoystickManager {
|
||||
public:
|
||||
JoystickManagerSDL();
|
||||
|
||||
virtual ~JoystickManagerSDL();
|
||||
|
||||
void update();
|
||||
|
||||
void close();
|
||||
|
||||
void open( OpenCb openCb = nullptr );
|
||||
|
||||
protected:
|
||||
void create( const Uint32& index ) override;
|
||||
|
||||
void openAsync();
|
||||
|
||||
Thread mAsyncInit;
|
||||
bool mInit{ false };
|
||||
Uint32 mCount{ 0 };
|
||||
std::vector<SDL_JoystickID> mIds;
|
||||
std::unordered_map<SDL_JoystickID, Uint32> mIdToIndex;
|
||||
|
||||
public:
|
||||
Uint32 getIndexFromID( SDL_JoystickID id ) const;
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
#endif
|
||||
70
src/eepp/window/backend/SDL3/joysticksdl3.cpp
Normal file
70
src/eepp/window/backend/SDL3/joysticksdl3.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <eepp/window/backend/SDL3/joysticksdl3.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
JoystickSDL::JoystickSDL( const Uint32& index, SDL_JoystickID id ) : Joystick( index ), mJoystick( nullptr ), mId( id ) {
|
||||
open();
|
||||
}
|
||||
|
||||
JoystickSDL::~JoystickSDL() {
|
||||
close();
|
||||
}
|
||||
|
||||
void JoystickSDL::open() {
|
||||
mJoystick = SDL_OpenJoystick( mId );
|
||||
if ( nullptr != mJoystick ) {
|
||||
mName = SDL_GetJoystickName( mJoystick );
|
||||
mHats = SDL_GetNumJoystickHats( mJoystick );
|
||||
mButtons = eemin( SDL_GetNumJoystickButtons( mJoystick ), 32 );
|
||||
mAxes = SDL_GetNumJoystickAxes( mJoystick );
|
||||
mBalls = SDL_GetNumJoystickBalls( mJoystick );
|
||||
mButtonDown = mButtonDownLast = mButtonUp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void JoystickSDL::close() {
|
||||
if ( nullptr != mJoystick )
|
||||
SDL_CloseJoystick( mJoystick );
|
||||
mJoystick = nullptr;
|
||||
mName = "";
|
||||
mHats = mButtons = mAxes = mBalls = 0;
|
||||
}
|
||||
|
||||
void JoystickSDL::update() {
|
||||
if ( nullptr != mJoystick ) {
|
||||
clearStates();
|
||||
for ( Int32 i = 0; i < mButtons; i++ ) {
|
||||
updateButton( i, 0 != SDL_GetJoystickButton( mJoystick, i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Uint8 JoystickSDL::getHat( const Int32& index ) {
|
||||
if ( index >= 0 && index < mHats )
|
||||
return SDL_GetJoystickHat( mJoystick, index );
|
||||
return HAT_CENTERED;
|
||||
}
|
||||
|
||||
Float JoystickSDL::getAxis( const Int32& axis ) {
|
||||
if ( axis >= 0 && axis < mAxes ) {
|
||||
return static_cast<Float>( SDL_GetJoystickAxis( mJoystick, axis ) ) / 32768.0f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Vector2i JoystickSDL::getBallMotion( const Int32& ball ) {
|
||||
Vector2i v;
|
||||
if ( ball >= 0 && ball < mBalls )
|
||||
SDL_GetJoystickBall( mJoystick, ball, &v.x, &v.y );
|
||||
return v;
|
||||
}
|
||||
|
||||
bool JoystickSDL::isPlugged() const {
|
||||
return nullptr != mJoystick;
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
41
src/eepp/window/backend/SDL3/joysticksdl3.hpp
Normal file
41
src/eepp/window/backend/SDL3/joysticksdl3.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef EE_WINDOWCJOYSTICKSDL3_HPP
|
||||
#define EE_WINDOWCJOYSTICKSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/window/joystick.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API JoystickSDL : public Joystick {
|
||||
public:
|
||||
JoystickSDL( const Uint32& index, SDL_JoystickID id );
|
||||
|
||||
virtual ~JoystickSDL();
|
||||
|
||||
void close();
|
||||
|
||||
void open();
|
||||
|
||||
void update();
|
||||
|
||||
Uint8 getHat( const Int32& index );
|
||||
|
||||
Float getAxis( const Int32& axis );
|
||||
|
||||
Vector2i getBallMotion( const Int32& ball );
|
||||
|
||||
bool isPlugged() const;
|
||||
|
||||
protected:
|
||||
SDL_Joystick* mJoystick;
|
||||
SDL_JoystickID mId;
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
#endif
|
||||
78
src/eepp/window/backend/SDL3/platformhelpersdl3.cpp
Normal file
78
src/eepp/window/backend/SDL3/platformhelpersdl3.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/backend/SDL3/platformhelpersdl3.hpp>
|
||||
#include <eepp/system/log.hpp>
|
||||
|
||||
using namespace EE::System;
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
EM_JS( void, emscripten_open_url, ( const char* msg ),
|
||||
{ window.open( UTF8ToString( msg ), 'blank' ); } );
|
||||
#endif
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
PlatformHelperSDL3::PlatformHelperSDL3() {}
|
||||
|
||||
bool PlatformHelperSDL3::openURL( const std::string& url ) {
|
||||
#if EE_PLATFORM == EE_PLATFORM_EMSCRIPTEN
|
||||
emscripten_open_url( url.c_str() );
|
||||
return true;
|
||||
#else
|
||||
bool res = SDL_OpenURL( url.c_str() );
|
||||
if ( !res ) {
|
||||
Log::error( "PlatformHelperSDL3::openURL: Failed with error - %s", SDL_GetError() );
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
char* PlatformHelperSDL3::iconv( const char* tocode, const char* fromcode, const char* inbuf,
|
||||
size_t inbytesleft ) {
|
||||
return SDL_iconv_string( tocode, fromcode, inbuf, inbytesleft );
|
||||
}
|
||||
|
||||
void PlatformHelperSDL3::iconvFree( char* buf ) {
|
||||
SDL_free( buf );
|
||||
}
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_ANDROID
|
||||
void* PlatformHelperSDL3::getActivity() {
|
||||
return SDL_AndroidGetActivity();
|
||||
}
|
||||
|
||||
void* PlatformHelperSDL3::getJNIEnv() {
|
||||
return SDL_AndroidGetJNIEnv();
|
||||
}
|
||||
|
||||
std::string PlatformHelperSDL3::getExternalStoragePath() {
|
||||
return std::string( SDL_AndroidGetExternalStoragePath() );
|
||||
}
|
||||
|
||||
std::string PlatformHelperSDL3::getInternalStoragePath() {
|
||||
return std::string( SDL_AndroidGetInternalStoragePath() );
|
||||
}
|
||||
|
||||
std::string PlatformHelperSDL3::getApkPath() {
|
||||
static std::string apkPath = "";
|
||||
if ( "" == apkPath ) {
|
||||
// Simplified: use SDL_AndroidGetApkPath if available
|
||||
apkPath = std::string( SDL_AndroidGetApkPath() ? SDL_AndroidGetApkPath() : "" );
|
||||
}
|
||||
return apkPath;
|
||||
}
|
||||
|
||||
bool PlatformHelperSDL3::isExternalStorageReadable() {
|
||||
return 0 != ( SDL_AndroidGetExternalStorageState() & SDL_ANDROID_EXTERNAL_STORAGE_READ );
|
||||
}
|
||||
|
||||
bool PlatformHelperSDL3::isExternalStorageWritable() {
|
||||
return 0 != ( SDL_AndroidGetExternalStorageState() & SDL_ANDROID_EXTERNAL_STORAGE_WRITE );
|
||||
}
|
||||
#endif
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
38
src/eepp/window/backend/SDL3/platformhelpersdl3.hpp
Normal file
38
src/eepp/window/backend/SDL3/platformhelpersdl3.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef EE_PLATFORMHELPERSDL3_HPP
|
||||
#define EE_PLATFORMHELPERSDL3_HPP
|
||||
|
||||
#include <eepp/window/platformhelper.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API PlatformHelperSDL3 : public PlatformHelper {
|
||||
public:
|
||||
PlatformHelperSDL3();
|
||||
|
||||
bool openURL( const std::string& url );
|
||||
|
||||
char* iconv( const char* tocode, const char* fromcode, const char* inbuf, size_t inbytesleft );
|
||||
|
||||
void iconvFree( char* buf );
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_ANDROID
|
||||
void* getActivity();
|
||||
|
||||
void* getJNIEnv();
|
||||
|
||||
std::string getExternalStoragePath();
|
||||
|
||||
std::string getInternalStoragePath();
|
||||
|
||||
std::string getApkPath();
|
||||
|
||||
bool isExternalStorageReadable();
|
||||
|
||||
bool isExternalStorageWritable();
|
||||
#endif
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
941
src/eepp/window/backend/SDL3/windowsdl3.cpp
Normal file
941
src/eepp/window/backend/SDL3/windowsdl3.cpp
Normal file
@@ -0,0 +1,941 @@
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/graphics/framebuffermanager.hpp>
|
||||
#include <eepp/graphics/globalbatchrenderer.hpp>
|
||||
#include <eepp/graphics/renderer/renderer.hpp>
|
||||
#include <eepp/graphics/shaderprogrammanager.hpp>
|
||||
#include <eepp/graphics/texturefactory.hpp>
|
||||
#include <eepp/graphics/vertexbuffermanager.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/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
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
#include <cstdint>
|
||||
#include <initguid.h>
|
||||
#include <objbase.h>
|
||||
#include <shellapi.h>
|
||||
#include <tlhelp32.h>
|
||||
|
||||
bool WindowsIsProcessRunning( const char* processName, bool killProcess = false ) {
|
||||
bool exists = false;
|
||||
PROCESSENTRY32 entry = {};
|
||||
entry.dwSize = sizeof( PROCESSENTRY32 );
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
|
||||
if ( Process32First( snapshot, &entry ) ) {
|
||||
while ( Process32Next( snapshot, &entry ) ) {
|
||||
#ifdef UNICODE
|
||||
if ( EE::String( entry.szExeFile ).toUtf8() == std::string( processName ) ) {
|
||||
#else
|
||||
if ( !stricmp( entry.szExeFile, processName ) ) {
|
||||
#endif
|
||||
exists = true;
|
||||
if ( killProcess ) {
|
||||
HANDLE aProc = OpenProcess( PROCESS_TERMINATE, 0, entry.th32ProcessID );
|
||||
if ( aProc ) {
|
||||
TerminateProcess( aProc, 9 );
|
||||
CloseHandle( aProc );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle( snapshot );
|
||||
return exists;
|
||||
}
|
||||
|
||||
#ifndef ERROR_ELEVATION_REQUIRED
|
||||
#define ERROR_ELEVATION_REQUIRED ( 740 )
|
||||
#endif
|
||||
|
||||
bool WindowsProcessLaunch( std::string command, HWND windowHwnd ) {
|
||||
#ifdef UNICODE
|
||||
wchar_t expandedCmd[1024] = {};
|
||||
#else
|
||||
char expandedCmd[1024] = {};
|
||||
#endif
|
||||
static PROCESS_INFORMATION pi = {};
|
||||
static STARTUPINFO si = {};
|
||||
si.cb = sizeof( si );
|
||||
#if UNICODE
|
||||
ExpandEnvironmentStrings( EE::String::fromUtf8( command ).toWideString().c_str(), expandedCmd,
|
||||
1024 );
|
||||
#else
|
||||
ExpandEnvironmentStrings( command.c_str(), expandedCmd, 1024 );
|
||||
#endif
|
||||
if ( CreateProcess( NULL, expandedCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) ) {
|
||||
WaitForSingleObject( pi.hProcess, 10000 );
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
return true;
|
||||
} else {
|
||||
DWORD error = GetLastError();
|
||||
if ( error == ERROR_ELEVATION_REQUIRED && 0 != windowHwnd ) {
|
||||
#ifdef UNICODE
|
||||
std::intptr_t res = reinterpret_cast<std::intptr_t>(
|
||||
ShellExecute( windowHwnd, L"open", expandedCmd, L"", NULL, SW_SHOWDEFAULT ) );
|
||||
#else
|
||||
std::intptr_t res = reinterpret_cast<std::intptr_t>(
|
||||
ShellExecute( windowHwnd, "open", expandedCmd, "", NULL, SW_SHOWDEFAULT ) );
|
||||
#endif
|
||||
if ( res <= 32 ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_GUID( CLSID_UIHostNoLaunch, 0x4CE576FA, 0x83DC, 0x4f88, 0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4,
|
||||
0xE3, 0x76 );
|
||||
|
||||
DEFINE_GUID( IID_ITipInvocation, 0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b,
|
||||
0x83, 0x4b );
|
||||
|
||||
struct ITipInvocation : IUnknown {
|
||||
virtual HRESULT STDMETHODCALLTYPE Toggle( HWND wnd ) = 0;
|
||||
};
|
||||
|
||||
static bool WIN_OSK_VISIBLE = false;
|
||||
|
||||
int showOSK( HWND windowHwnd ) {
|
||||
if ( !WindowsIsProcessRunning( "TabTip.exe" ) ) {
|
||||
WindowsIsProcessRunning(
|
||||
"WindowsInternal.ComposableShell.Experiences.TextInput.InputApp.EXE", true );
|
||||
|
||||
std::string programFiles( Sys::getOSArchitecture() == "x64" ? "%ProgramW6432%"
|
||||
: "%ProgramFiles(x86)%" );
|
||||
WindowsProcessLaunch( programFiles + "\\Common Files\\microsoft shared\\ink\\TabTip.exe",
|
||||
windowHwnd );
|
||||
}
|
||||
|
||||
CoInitialize( 0 );
|
||||
|
||||
ITipInvocation* tip;
|
||||
CoCreateInstance( CLSID_UIHostNoLaunch, 0, CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER,
|
||||
IID_ITipInvocation, (void**)&tip );
|
||||
if ( tip != NULL ) {
|
||||
tip->Toggle( GetDesktopWindow() );
|
||||
tip->Release();
|
||||
WIN_OSK_VISIBLE = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hideOSK() {
|
||||
WIN_OSK_VISIBLE = false;
|
||||
return PostMessage( GetDesktopWindow(), WM_SYSCOMMAND, (int)SC_CLOSE, 0 );
|
||||
}
|
||||
|
||||
bool isDarkModeEnabled() {
|
||||
HKEY hKey;
|
||||
DWORD value = 1;
|
||||
DWORD valueSize = sizeof( value );
|
||||
|
||||
if ( RegOpenKeyExA( HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0,
|
||||
KEY_READ, &hKey ) == ERROR_SUCCESS ) {
|
||||
RegQueryValueExA( hKey, "AppsUseLightTheme", nullptr, nullptr,
|
||||
reinterpret_cast<LPBYTE>( &value ), &valueSize );
|
||||
RegCloseKey( hKey );
|
||||
}
|
||||
|
||||
return value == 0;
|
||||
}
|
||||
|
||||
typedef HRESULT( WINAPI* DwmSetWindowAttributeFunc )( HWND, DWORD, LPCVOID, DWORD );
|
||||
|
||||
constexpr DWORD DWMWA_USE_IMMERSIVE_DARK_MODE = 20;
|
||||
|
||||
void setUserTheme( HWND hwnd ) {
|
||||
HMODULE hDwmapi = LoadLibraryA( "dwmapi.dll" );
|
||||
if ( !hDwmapi ) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto DwmSetWindowAttribute = reinterpret_cast<DwmSetWindowAttributeFunc>(
|
||||
GetProcAddress( hDwmapi, "DwmSetWindowAttribute" ) );
|
||||
if ( !DwmSetWindowAttribute ) {
|
||||
FreeLibrary( hDwmapi );
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL darkMode = isDarkModeEnabled() ? TRUE : FALSE;
|
||||
DwmSetWindowAttribute( hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &darkMode, sizeof( darkMode ) );
|
||||
|
||||
FreeLibrary( hDwmapi );
|
||||
}
|
||||
#elif defined( EE_X11_PLATFORM )
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static pid_t ONBOARD_PID = 0;
|
||||
|
||||
void showOSK() {
|
||||
if ( ONBOARD_PID == 0 ) {
|
||||
if ( FileSystem::fileExists( "/usr/bin/onboard" ) ) {
|
||||
pid_t pid = fork();
|
||||
|
||||
if ( pid == 0 ) {
|
||||
execl( "/usr/bin/onboard", "onboard", NULL );
|
||||
} else if ( pid != -1 ) {
|
||||
ONBOARD_PID = pid;
|
||||
}
|
||||
} else {
|
||||
EE::System::Log::error(
|
||||
"\"onboard\" must be installed to be able to use the On Screen Keyboard" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hideOSK() {
|
||||
if ( ONBOARD_PID != 0 ) {
|
||||
kill( ONBOARD_PID, SIGTERM );
|
||||
ONBOARD_PID = 0;
|
||||
}
|
||||
}
|
||||
#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 ) ) ),
|
||||
mSDLWindow( NULL ),
|
||||
mGLContext( NULL ),
|
||||
mGLContextThread( NULL ),
|
||||
mWMinfo( NULL ) {
|
||||
create( Settings, Context );
|
||||
}
|
||||
|
||||
WindowSDL::~WindowSDL() {
|
||||
if ( NULL != mGLContext ) {
|
||||
SDL_GL_DestroyContext( mGLContext );
|
||||
}
|
||||
|
||||
if ( NULL != mGLContextThread ) {
|
||||
SDL_GL_DestroyContext( mGLContextThread );
|
||||
}
|
||||
|
||||
eeSAFE_DELETE( mWMinfo );
|
||||
|
||||
if ( NULL != mSDLWindow ) {
|
||||
SDL_DestroyWindow( mSDLWindow );
|
||||
}
|
||||
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
hideOSK();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WindowSDL::create( WindowSettings Settings, ContextSettings Context ) {
|
||||
if ( mWindow.Created )
|
||||
return false;
|
||||
|
||||
mWindow.WindowConfig = Settings;
|
||||
mWindow.ContextConfig = Context;
|
||||
|
||||
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.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 ( NULL == 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 ( NULL == mGLContext
|
||||
#ifdef SDL3_THREADED_GLCONTEXT
|
||||
|| ( mWindow.ContextConfig.SharedGLContext && NULL == 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 ( NULL != 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 ( NULL == 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 );
|
||||
|
||||
logSuccessfulInit( getVersion() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Uint32 WindowSDL::getWindowID() const {
|
||||
return mID;
|
||||
}
|
||||
|
||||
void WindowSDL::makeCurrent() {
|
||||
SDL_GL_MakeCurrent( mSDLWindow, mGLContext );
|
||||
}
|
||||
|
||||
void WindowSDL::close() {
|
||||
SDL_DestroyWindow( mSDLWindow );
|
||||
mSDLWindow = NULL;
|
||||
mGLContext = NULL;
|
||||
mGLContextThread = NULL;
|
||||
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, NULL );
|
||||
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 major = SDL_MAJOR_VERSION;
|
||||
int minor = SDL_MINOR_VERSION;
|
||||
int patch = SDL_MICRO_VERSION;
|
||||
|
||||
return String::format( "SDL %d.%d.%d", major, minor, patch );
|
||||
}
|
||||
|
||||
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 ( NULL != 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 ( NULL != 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 ) {
|
||||
Uint32 ssize = iconSurface->w * iconSurface->h * c;
|
||||
for ( Uint32 i = 0; i < ssize; i++ ) {
|
||||
( static_cast<Uint8*>( iconSurface->pixels ) )[i + 0] = ( Ptr )[i];
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
showOSK( getWindowHandler() );
|
||||
#elif defined( EE_X11_PLATFORM )
|
||||
showOSK();
|
||||
#endif
|
||||
}
|
||||
|
||||
void WindowSDL::stopOnScreenKeyboard() {
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
hideOSK();
|
||||
#elif defined( EE_X11_PLATFORM )
|
||||
hideOSK();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool WindowSDL::isOnScreenKeyboardActive() const {
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
return WIN_OSK_VISIBLE;
|
||||
#elif defined( EE_X11_PLATFORM )
|
||||
return ONBOARD_PID != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
145
src/eepp/window/backend/SDL3/windowsdl3.hpp
Normal file
145
src/eepp/window/backend/SDL3/windowsdl3.hpp
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef EE_WINDOWCWINDOWSDL3_HPP
|
||||
#define EE_WINDOWCWINDOWSDL3_HPP
|
||||
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <eepp/window/backend/SDL3/wminfo.hpp>
|
||||
#include <eepp/window/window.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API WindowSDL : public Window {
|
||||
public:
|
||||
WindowSDL( WindowSettings Settings, ContextSettings Context );
|
||||
|
||||
virtual ~WindowSDL();
|
||||
|
||||
bool create( WindowSettings Settings, ContextSettings Context );
|
||||
|
||||
Uint32 getWindowID() const;
|
||||
|
||||
void makeCurrent();
|
||||
|
||||
void close();
|
||||
|
||||
void setCurrent();
|
||||
|
||||
void toggleFullscreen();
|
||||
|
||||
void setTitle( const std::string& title );
|
||||
|
||||
bool setIcon( const std::string& Path );
|
||||
|
||||
bool isActive() const;
|
||||
|
||||
bool isVisible() const;
|
||||
|
||||
bool hasFocus() const;
|
||||
|
||||
bool hasInputFocus() const;
|
||||
|
||||
bool hasMouseFocus() const;
|
||||
|
||||
void setSize( Uint32 width, Uint32 height, bool windowed );
|
||||
|
||||
std::vector<DisplayMode> getDisplayModes() const;
|
||||
|
||||
void setGamma( Float Red, Float Green, Float Blue );
|
||||
|
||||
eeWindowHandle getWindowHandler() const;
|
||||
|
||||
virtual void minimize();
|
||||
|
||||
virtual void maximize();
|
||||
|
||||
virtual bool isMaximized() const;
|
||||
|
||||
virtual bool isMinimized() const;
|
||||
|
||||
virtual void hide();
|
||||
|
||||
virtual void raise();
|
||||
|
||||
virtual void restore();
|
||||
|
||||
virtual void flash( WindowFlashOperation op );
|
||||
|
||||
virtual void show();
|
||||
|
||||
virtual void setPosition( int Left, int Top );
|
||||
|
||||
virtual Vector2i getPosition() const;
|
||||
|
||||
const Sizei& getDesktopResolution() const;
|
||||
|
||||
virtual Rect getBorderSize() const;
|
||||
|
||||
virtual Float getScale() const;
|
||||
|
||||
virtual bool hasNativeMessageBox() const;
|
||||
|
||||
virtual bool showMessageBox( const MessageBoxType& type, const std::string& title,
|
||||
const std::string& message );
|
||||
|
||||
SDL_Window* getSDLWindow() const;
|
||||
|
||||
void startOnScreenKeyboard();
|
||||
|
||||
void stopOnScreenKeyboard();
|
||||
|
||||
bool isOnScreenKeyboardActive() const;
|
||||
|
||||
void startTextInput();
|
||||
|
||||
bool isTextInputActive() const;
|
||||
|
||||
void stopTextInput();
|
||||
|
||||
void setTextInputRect( const Rect& rect );
|
||||
|
||||
void clearComposition();
|
||||
|
||||
bool hasScreenKeyboardSupport() const;
|
||||
|
||||
bool isScreenKeyboardShown() const;
|
||||
|
||||
bool isThreadedGLContext() const;
|
||||
|
||||
void setGLContextThread();
|
||||
|
||||
void unsetGLContextThread();
|
||||
|
||||
int getCurrentDisplayIndex() const;
|
||||
|
||||
protected:
|
||||
friend class ClipboardSDL;
|
||||
|
||||
SDL_Window* mSDLWindow{ nullptr };
|
||||
SDL_GLContext mGLContext;
|
||||
SDL_GLContext mGLContextThread;
|
||||
Mutex mGLContextMutex;
|
||||
Uint32 mID{ 0 };
|
||||
|
||||
WMInfo* mWMinfo;
|
||||
|
||||
Vector2i mWinPos;
|
||||
|
||||
void swapBuffers();
|
||||
|
||||
void setGLConfig();
|
||||
|
||||
std::string getVersion();
|
||||
|
||||
void updateDesktopResolution() const;
|
||||
|
||||
void onWindowResize( Uint32 width, Uint32 height );
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
34
src/eepp/window/backend/SDL3/wminfo.cpp
Normal file
34
src/eepp/window/backend/SDL3/wminfo.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#include <eepp/window/backend/SDL3/wminfo.hpp>
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
WMInfo::WMInfo( SDL_Window* win ) : mProps( SDL_GetWindowProperties( win ) ) {}
|
||||
|
||||
WMInfo::~WMInfo() {}
|
||||
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
X11Window WMInfo::getWindow() const {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
eeWindowHandle WMInfo::getWindowHandler() const {
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
return (eeWindowHandle)SDL_GetPointerProperty( mProps, SDL_PROP_WINDOW_WIN32_HWND_POINTER, 0 );
|
||||
#elif defined( EE_X11_PLATFORM )
|
||||
return (eeWindowHandle)SDL_GetNumberProperty( mProps, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0 );
|
||||
#elif EE_PLATFORM == EE_PLATFORM_MACOS
|
||||
return (eeWindowHandle)SDL_GetPointerProperty( mProps, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER,
|
||||
0 );
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
27
src/eepp/window/backend/SDL3/wminfo.hpp
Normal file
27
src/eepp/window/backend/SDL3/wminfo.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef EE_BACKEND_SDL3_WMINFO_HPP
|
||||
#define EE_BACKEND_SDL3_WMINFO_HPP
|
||||
|
||||
#include <eepp/window/backend/SDL3/base.hpp>
|
||||
#include <eepp/window/windowhandle.hpp>
|
||||
|
||||
namespace EE { namespace Window { namespace Backend { namespace SDL3 {
|
||||
|
||||
class EE_API WMInfo {
|
||||
public:
|
||||
WMInfo( SDL_Window* win );
|
||||
|
||||
~WMInfo();
|
||||
|
||||
#if defined( EE_X11_PLATFORM )
|
||||
X11Window getWindow() const;
|
||||
#endif
|
||||
|
||||
eeWindowHandle getWindowHandler() const;
|
||||
|
||||
protected:
|
||||
SDL_PropertiesID mProps;
|
||||
};
|
||||
|
||||
}}}} // namespace EE::Window::Backend::SDL3
|
||||
|
||||
#endif
|
||||
@@ -24,6 +24,10 @@
|
||||
#include <eepp/window/backend.hpp>
|
||||
#include <eepp/window/backend/SDL2/backendsdl2.hpp>
|
||||
#include <eepp/window/backend/SDL2/platformhelpersdl2.hpp>
|
||||
#if defined(EE_SDL_VERSION_3)
|
||||
#include <eepp/window/backend/SDL3/backendsdl3.hpp>
|
||||
#include <eepp/window/backend/SDL3/platformhelpersdl3.hpp>
|
||||
#endif
|
||||
#include <eepp/window/engine.hpp>
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_ANDROID
|
||||
@@ -31,10 +35,13 @@
|
||||
#endif
|
||||
|
||||
#define BACKEND_SDL2 1
|
||||
#define BACKEND_SDL3 2
|
||||
|
||||
#ifndef DEFAULT_BACKEND
|
||||
|
||||
#if defined( EE_BACKEND_SDL2 )
|
||||
#if defined( EE_BACKEND_SDL3 )
|
||||
#define DEFAULT_BACKEND BACKEND_SDL3
|
||||
#elif defined( EE_BACKEND_SDL2 )
|
||||
#define DEFAULT_BACKEND BACKEND_SDL2
|
||||
#endif
|
||||
|
||||
@@ -150,10 +157,35 @@ EE::Window::Window* Engine::createSDL2Window( const WindowSettings& Settings,
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef EE_BACKEND_SDL3
|
||||
Backend::WindowBackendLibrary* Engine::createSDL3Backend( const WindowSettings& ) {
|
||||
#if defined( EE_SDL_VERSION_3 )
|
||||
return eeNew( Backend::SDL3::WindowBackendSDL3, () );
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
EE::Window::Window* Engine::createSDL3Window( const WindowSettings& Settings,
|
||||
const ContextSettings& Context ) {
|
||||
#if defined( EE_SDL_VERSION_3 )
|
||||
if ( NULL == mBackend ) {
|
||||
mBackend = createSDL3Backend( Settings );
|
||||
}
|
||||
|
||||
return eeNew( Backend::SDL3::WindowSDL, ( Settings, Context ) );
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
EE::Window::Window* Engine::createDefaultWindow( const WindowSettings& Settings,
|
||||
const ContextSettings& Context ) {
|
||||
#if DEFAULT_BACKEND == BACKEND_SDL2
|
||||
return createSDL2Window( Settings, Context );
|
||||
#elif DEFAULT_BACKEND == BACKEND_SDL3
|
||||
return createSDL3Window( Settings, Context );
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -251,6 +283,8 @@ bool Engine::isRunning() const {
|
||||
WindowBackend Engine::getDefaultBackend() const {
|
||||
#if DEFAULT_BACKEND == BACKEND_SDL2
|
||||
return WindowBackend::SDL2;
|
||||
#elif DEFAULT_BACKEND == BACKEND_SDL3
|
||||
return WindowBackend::SDL3;
|
||||
#else
|
||||
return WindowBackend::Default;
|
||||
#endif
|
||||
@@ -293,6 +327,8 @@ WindowSettings Engine::createWindowSettings( IniFile* ini, std::string iniKeyNam
|
||||
|
||||
if ( "sdl2" == backend )
|
||||
winBackend = WindowBackend::SDL2;
|
||||
else if ( "sdl3" == backend )
|
||||
winBackend = WindowBackend::SDL3;
|
||||
|
||||
Uint32 Style = WindowStyle::Titlebar;
|
||||
|
||||
@@ -382,6 +418,8 @@ PlatformHelper* Engine::getPlatformHelper() {
|
||||
if ( NULL == mPlatformHelper ) {
|
||||
#if DEFAULT_BACKEND == BACKEND_SDL2
|
||||
mPlatformHelper = eeNew( Backend::SDL2::PlatformHelperSDL2, () );
|
||||
#elif DEFAULT_BACKEND == BACKEND_SDL3
|
||||
mPlatformHelper = eeNew( Backend::SDL3::PlatformHelperSDL3, () );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -392,6 +430,8 @@ DisplayManager* Engine::getDisplayManager() {
|
||||
if ( NULL == mDisplayManager ) {
|
||||
#if DEFAULT_BACKEND == BACKEND_SDL2
|
||||
mDisplayManager = eeNew( Backend::SDL2::DisplayManagerSDL2, () );
|
||||
#elif DEFAULT_BACKEND == BACKEND_SDL3
|
||||
mDisplayManager = eeNew( Backend::SDL3::DisplayManagerSDL3, () );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -348,9 +348,17 @@ void Window::close() {
|
||||
|
||||
void Window::setFrameRateLimit( Uint32 FrameRateLimit ) {
|
||||
if ( FrameRateLimit == ContextSettings::FrameRateLimitScreenRefreshRate ) {
|
||||
Display* currentDisplay = Engine::instance()->getDisplayManager()->getDisplayIndex(
|
||||
isOpen() ? getCurrentDisplayIndex() : 0 );
|
||||
FrameRateLimit = currentDisplay->getRefreshRate();
|
||||
Display* currentDisplay = nullptr;
|
||||
if ( Engine::existsSingleton() && Engine::instance()->getDisplayManager() ) {
|
||||
currentDisplay = Engine::instance()->getDisplayManager()->getDisplayIndex(
|
||||
getCurrentDisplayIndex() );
|
||||
}
|
||||
if ( currentDisplay ) {
|
||||
FrameRateLimit = currentDisplay->getRefreshRate();
|
||||
} else {
|
||||
// Fallback to 60 FPS if display info not available
|
||||
FrameRateLimit = 60;
|
||||
}
|
||||
}
|
||||
mFrameData.FPS.Limit = (Float)FrameRateLimit;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user