@ -8,6 +8,9 @@
// [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy SDL_SCANCODE_* values will also be supported unless IMGUI_DISABLE_OBSOLETE_KEYIO is set]
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
// [x] Platform: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable' -> the OS animation effect when window gets created/destroyed is problematic. SDL2 backend doesn't have issue.
// Missing features:
// [ ] Platform: Multi-viewport + Minimized windows seems to break mouse wheel events (at least under Windows).
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
@ -16,6 +19,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2023-02-07: Forked "imgui_impl_sdl2" into "imgui_impl_sdl3". Removed version checks for old feature. Refer to imgui_impl_sdl2.cpp for older changelog.
# include "imgui.h"
@ -47,6 +51,8 @@ struct ImGui_ImplSDL3_Data
int PendingMouseLeaveFrame ;
char * ClipboardTextData ;
bool MouseCanUseGlobalState ;
bool MouseCanReportHoveredViewport ; // This is hard to use/unreliable on SDL so we'll set ImGuiBackendFlags_HasMouseHoveredViewport dynamically based on state.
bool UseVulkan ;
ImGui_ImplSDL3_Data ( ) { memset ( ( void * ) this , 0 , sizeof ( * this ) ) ; }
} ;
@ -60,6 +66,11 @@ static ImGui_ImplSDL3_Data* ImGui_ImplSDL3_GetBackendData()
return ImGui : : GetCurrentContext ( ) ? ( ImGui_ImplSDL3_Data * ) ImGui : : GetIO ( ) . BackendPlatformUserData : nullptr ;
}
// Forward Declarations
static void ImGui_ImplSDL3_UpdateMonitors ( ) ;
static void ImGui_ImplSDL3_InitPlatformInterface ( SDL_Window * window , void * sdl_gl_context ) ;
static void ImGui_ImplSDL3_ShutdownPlatformInterface ( ) ;
// Functions
static const char * ImGui_ImplSDL3_GetClipboardText ( void * )
{
@ -212,6 +223,13 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_MOUSE_MOTION :
{
ImVec2 mouse_pos ( ( float ) event - > motion . x , ( float ) event - > motion . y ) ;
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
{
int window_x , window_y ;
SDL_GetWindowPosition ( SDL_GetWindowFromID ( event - > motion . windowID ) , & window_x , & window_y ) ;
mouse_pos . x + = window_x ;
mouse_pos . y + = window_y ;
}
io . AddMousePosEvent ( mouse_pos . x , mouse_pos . y ) ;
return true ;
}
@ -276,11 +294,25 @@ bool ImGui_ImplSDL3_ProcessEvent(const SDL_Event* event)
case SDL_EVENT_WINDOW_FOCUS_LOST :
io . AddFocusEvent ( false ) ;
return true ;
case SDL_EVENT_WINDOW_CLOSE_REQUESTED :
case SDL_EVENT_WINDOW_MOVED :
case SDL_EVENT_WINDOW_RESIZED :
if ( ImGuiViewport * viewport = ImGui : : FindViewportByPlatformHandle ( ( void * ) SDL_GetWindowFromID ( event - > window . windowID ) ) )
{
if ( event - > type = = SDL_EVENT_WINDOW_CLOSE_REQUESTED )
viewport - > PlatformRequestClose = true ;
if ( event - > type = = SDL_EVENT_WINDOW_MOVED )
viewport - > PlatformRequestMove = true ;
if ( event - > type = = SDL_EVENT_WINDOW_RESIZED )
viewport - > PlatformRequestResize = true ;
return true ;
}
return true ;
}
return false ;
}
static bool ImGui_ImplSDL3_Init ( SDL_Window * window , SDL_Renderer * renderer )
static bool ImGui_ImplSDL3_Init ( SDL_Window * window , SDL_Renderer * renderer , void * sdl_gl_context )
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
IM_ASSERT ( io . BackendPlatformUserData = = nullptr & & " Already initialized a platform backend! " ) ;
@ -302,10 +334,20 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer)
io . BackendPlatformName = " imgui_impl_sdl3 " ;
io . BackendFlags | = ImGuiBackendFlags_HasMouseCursors ; // We can honor GetMouseCursor() values (optional)
io . BackendFlags | = ImGuiBackendFlags_HasSetMousePos ; // We can honor io.WantSetMousePos requests (optional, rarely used)
if ( mouse_can_use_global_state )
io . BackendFlags | = ImGuiBackendFlags_PlatformHasViewports ; // We can create multi-viewports on the Platform side (optional)
bd - > Window = window ;
bd - > Renderer = renderer ;
// SDL on Linux/OSX doesn't report events for unfocused windows (see https://github.com/ocornut/imgui/issues/4960)
// We will use 'MouseCanReportHoveredViewport' to set 'ImGuiBackendFlags_HasMouseHoveredViewport' dynamically each frame.
bd - > MouseCanUseGlobalState = mouse_can_use_global_state ;
# ifndef __APPLE__
bd - > MouseCanReportHoveredViewport = bd - > MouseCanUseGlobalState ;
# else
bd - > MouseCanReportHoveredViewport = false ;
# endif
io . SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText ;
io . GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText ;
@ -325,6 +367,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer)
// Set platform dependent data in viewport
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
main_viewport - > PlatformHandle = ( void * ) window ;
main_viewport - > PlatformHandleRaw = nullptr ;
SDL_SysWMinfo info ;
if ( SDL_GetWindowWMInfo ( window , & info , SDL_SYSWM_CURRENT_VERSION ) )
@ -350,18 +393,29 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer)
SDL_SetHint ( SDL_HINT_MOUSE_AUTO_CAPTURE , " 0 " ) ;
# endif
// Update monitors
ImGui_ImplSDL3_UpdateMonitors ( ) ;
// We need SDL_CaptureMouse(), SDL_GetGlobalMouseState() from SDL 2.0.4+ to support multiple viewports.
// We left the call to ImGui_ImplSDL3_InitPlatformInterface() outside of #ifdef to avoid unused-function warnings.
if ( ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable ) & & ( io . BackendFlags & ImGuiBackendFlags_PlatformHasViewports ) )
ImGui_ImplSDL3_InitPlatformInterface ( window , sdl_gl_context ) ;
return true ;
}
bool ImGui_ImplSDL3_InitForOpenGL ( SDL_Window * window , void * sdl_gl_context )
{
IM_UNUSED ( sdl_gl_context ) ; // Viewport branch will need this.
return ImGui_ImplSDL3_Init ( window , nullptr ) ;
return ImGui_ImplSDL3_Init ( window , nullptr , sdl_gl_context ) ;
}
bool ImGui_ImplSDL3_InitForVulkan ( SDL_Window * window )
{
return ImGui_ImplSDL3_Init ( window , nullptr ) ;
if ( ! ImGui_ImplSDL3_Init ( window , nullptr , nullptr ) )
return false ;
ImGui_ImplSDL3_Data * bd = ImGui_ImplSDL3_GetBackendData ( ) ;
bd - > UseVulkan = true ;
return true ;
}
bool ImGui_ImplSDL3_InitForD3D ( SDL_Window * window )
@ -369,17 +423,17 @@ bool ImGui_ImplSDL3_InitForD3D(SDL_Window* window)
# if !defined(_WIN32)
IM_ASSERT ( 0 & & " Unsupported " ) ;
# endif
return ImGui_ImplSDL3_Init ( window , nullptr ) ;
return ImGui_ImplSDL3_Init ( window , nullptr , nullptr ) ;
}
bool ImGui_ImplSDL3_InitForMetal ( SDL_Window * window )
{
return ImGui_ImplSDL3_Init ( window , nullptr ) ;
return ImGui_ImplSDL3_Init ( window , nullptr , nullptr ) ;
}
bool ImGui_ImplSDL3_InitForSDLRenderer ( SDL_Window * window , SDL_Renderer * renderer )
{
return ImGui_ImplSDL3_Init ( window , renderer ) ;
return ImGui_ImplSDL3_Init ( window , renderer , nullptr ) ;
}
void ImGui_ImplSDL3_Shutdown ( )
@ -388,6 +442,8 @@ void ImGui_ImplSDL3_Shutdown()
IM_ASSERT ( bd ! = nullptr & & " No platform backend to shutdown, or already shutdown? " ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
ImGui_ImplSDL3_ShutdownPlatformInterface ( ) ;
if ( bd - > ClipboardTextData )
SDL_free ( bd - > ClipboardTextData ) ;
for ( ImGuiMouseCursor cursor_n = 0 ; cursor_n < ImGuiMouseCursor_COUNT ; cursor_n + + )
@ -399,6 +455,7 @@ void ImGui_ImplSDL3_Shutdown()
IM_DELETE ( bd ) ;
}
// This code is incredibly messy because some of the functions we need for full viewport support are not available in SDL < 2.0.4.
static void ImGui_ImplSDL3_UpdateMouseData ( )
{
ImGui_ImplSDL3_Data * bd = ImGui_ImplSDL3_GetBackendData ( ) ;
@ -409,27 +466,57 @@ static void ImGui_ImplSDL3_UpdateMouseData()
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger other operations outside
SDL_CaptureMouse ( ( bd - > MouseButtonsDown ! = 0 ) ? SDL_TRUE : SDL_FALSE ) ;
SDL_Window * focused_window = SDL_GetKeyboardFocus ( ) ;
const bool is_app_focused = ( bd - > Window = = focused_window ) ;
const bool is_app_focused = ( focused_window & & ( bd - > Window = = focused_window | | ImGui : : FindViewportByPlatformHandle ( ( void * ) focused_window ) ) ) ;
# else
SDL_Window * focused_window = bd - > Window ;
const bool is_app_focused = ( SDL_GetWindowFlags ( bd - > Window ) & SDL_WINDOW_INPUT_FOCUS ) ! = 0 ; // SDL 2.0.3 and non-windowed systems: single-viewport only
# endif
if ( is_app_focused )
{
// (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
if ( io . WantSetMousePos )
SDL_WarpMouseInWindow ( bd - > Window , io . MousePos . x , io . MousePos . y ) ;
{
# if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
if ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable )
SDL_WarpMouseGlobal ( io . MousePos . x , io . MousePos . y ) ;
else
# endif
SDL_WarpMouseInWindow ( bd - > Window , io . MousePos . x , io . MousePos . y ) ;
}
// (Optional) Fallback to provide mouse position when focused (SDL_MOUSEMOTION already provides this when hovered or captured)
if ( bd - > MouseCanUseGlobalState & & bd - > MouseButtonsDown = = 0 )
{
// Single-viewport mode: mouse position in client window coordinates (io.MousePos is (0,0) when the mouse is on the upper-left corner of the app window)
float mouse_x_global , mouse_y_global ;
// Multi-viewport mode: mouse position in OS absolute coordinates (io.MousePos is (0,0) when the mouse is on the upper-left of the primary monitor)
float mouse_x , mouse_y ;
int window_x , window_y ;
SDL_GetGlobalMouseState ( & mouse_x_global , & mouse_y_global ) ;
SDL_GetWindowPosition ( focused_window , & window_x , & window_y ) ;
io . AddMousePosEvent ( mouse_x_global - window_x , mouse_y_global - window_y ) ;
SDL_GetGlobalMouseState ( & mouse_x , & mouse_y ) ;
if ( ! ( io . ConfigFlags & ImGuiConfigFlags_ViewportsEnable ) )
{
SDL_GetWindowPosition ( focused_window , & window_x , & window_y ) ;
mouse_x - = window_x ;
mouse_y - = window_y ;
}
io . AddMousePosEvent ( ( float ) mouse_x , ( float ) mouse_y ) ;
}
}
// (Optional) When using multiple viewports: call io.AddMouseViewportEvent() with the viewport the OS mouse cursor is hovering.
// If ImGuiBackendFlags_HasMouseHoveredViewport is not set by the backend, Dear imGui will ignore this field and infer the information using its flawed heuristic.
// - [!] SDL backend does NOT correctly ignore viewports with the _NoInputs flag.
// Some backend are not able to handle that correctly. If a backend report an hovered viewport that has the _NoInputs flag (e.g. when dragging a window
// for docking, the viewport has the _NoInputs flag in order to allow us to find the viewport under), then Dear ImGui is forced to ignore the value reported
// by the backend, and use its flawed heuristic to guess the viewport behind.
// - [X] SDL backend correctly reports this regardless of another viewport behind focused and dragged from (we need this to find a useful drag and drop target).
if ( io . BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport )
{
ImGuiID mouse_viewport_id = 0 ;
if ( SDL_Window * sdl_mouse_window = SDL_GetWindowFromID ( bd - > MouseWindowID ) )
if ( ImGuiViewport * mouse_viewport = ImGui : : FindViewportByPlatformHandle ( ( void * ) sdl_mouse_window ) )
mouse_viewport_id = mouse_viewport - > ID ;
io . AddMouseViewportEvent ( mouse_viewport_id ) ;
}
}
static void ImGui_ImplSDL3_UpdateMouseCursor ( )
@ -504,6 +591,35 @@ static void ImGui_ImplSDL3_UpdateGamepads()
# undef MAP_ANALOG
}
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
static void ImGui_ImplSDL3_UpdateMonitors ( )
{
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
platform_io . Monitors . resize ( 0 ) ;
int display_count ;
SDL_DisplayID * displays = SDL_GetDisplays ( & display_count ) ;
for ( int n = 0 ; n < display_count ; n + + )
{
// Warning: the validity of monitor DPI information on Windows depends on the application DPI awareness settings, which generally needs to be set in the manifest or at runtime.
SDL_DisplayID display_id = displays [ n ] ;
ImGuiPlatformMonitor monitor ;
SDL_Rect r ;
SDL_GetDisplayBounds ( display_id , & r ) ;
monitor . MainPos = monitor . WorkPos = ImVec2 ( ( float ) r . x , ( float ) r . y ) ;
monitor . MainSize = monitor . WorkSize = ImVec2 ( ( float ) r . w , ( float ) r . h ) ;
SDL_GetDisplayUsableBounds ( display_id , & r ) ;
monitor . WorkPos = ImVec2 ( ( float ) r . x , ( float ) r . y ) ;
monitor . WorkSize = ImVec2 ( ( float ) r . w , ( float ) r . h ) ;
// FIXME-VIEWPORT: On MacOS SDL reports actual monitor DPI scale, ignoring OS configuration. We may want to set
// DpiScale to cocoa_window.backingScaleFactor here.
float dpi = 0.0f ;
if ( ! SDL_GetDisplayPhysicalDPI ( display_id , & dpi , nullptr , nullptr ) )
monitor . DpiScale = dpi / 96.0f ;
platform_io . Monitors . push_back ( monitor ) ;
}
}
void ImGui_ImplSDL3_NewFrame ( )
{
ImGui_ImplSDL3_Data * bd = ImGui_ImplSDL3_GetBackendData ( ) ;
@ -534,9 +650,251 @@ void ImGui_ImplSDL3_NewFrame()
io . AddMousePosEvent ( - FLT_MAX , - FLT_MAX ) ;
}
// Our io.AddMouseViewportEvent() calls will only be valid when not capturing.
// Technically speaking testing for 'bd->MouseButtonsDown == 0' would be more rygorous, but testing for payload reduces noise and potential side-effects.
if ( bd - > MouseCanReportHoveredViewport & & ImGui : : GetDragDropPayload ( ) = = nullptr )
io . BackendFlags | = ImGuiBackendFlags_HasMouseHoveredViewport ;
else
io . BackendFlags & = ~ ImGuiBackendFlags_HasMouseHoveredViewport ;
ImGui_ImplSDL3_UpdateMouseData ( ) ;
ImGui_ImplSDL3_UpdateMouseCursor ( ) ;
// Update game controllers (if enabled and available)
ImGui_ImplSDL3_UpdateGamepads ( ) ;
}
//--------------------------------------------------------------------------------------------------------
// MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
// This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
// If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
//--------------------------------------------------------------------------------------------------------
// Helper structure we store in the void* RenderUserData field of each ImGuiViewport to easily retrieve our backend data.
struct ImGui_ImplSDL3_ViewportData
{
SDL_Window * Window ;
Uint32 WindowID ;
bool WindowOwned ;
SDL_GLContext GLContext ;
ImGui_ImplSDL3_ViewportData ( ) { Window = nullptr ; WindowID = 0 ; WindowOwned = false ; GLContext = nullptr ; }
~ ImGui_ImplSDL3_ViewportData ( ) { IM_ASSERT ( Window = = nullptr & & GLContext = = nullptr ) ; }
} ;
static void ImGui_ImplSDL3_CreateWindow ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_Data * bd = ImGui_ImplSDL3_GetBackendData ( ) ;
ImGui_ImplSDL3_ViewportData * vd = IM_NEW ( ImGui_ImplSDL3_ViewportData ) ( ) ;
viewport - > PlatformUserData = vd ;
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
ImGui_ImplSDL3_ViewportData * main_viewport_data = ( ImGui_ImplSDL3_ViewportData * ) main_viewport - > PlatformUserData ;
// Share GL resources with main context
bool use_opengl = ( main_viewport_data - > GLContext ! = nullptr ) ;
SDL_GLContext backup_context = nullptr ;
if ( use_opengl )
{
backup_context = SDL_GL_GetCurrentContext ( ) ;
SDL_GL_SetAttribute ( SDL_GL_SHARE_WITH_CURRENT_CONTEXT , 1 ) ;
SDL_GL_MakeCurrent ( main_viewport_data - > Window , main_viewport_data - > GLContext ) ;
}
Uint32 sdl_flags = 0 ;
sdl_flags | = use_opengl ? SDL_WINDOW_OPENGL : ( bd - > UseVulkan ? SDL_WINDOW_VULKAN : 0 ) ;
sdl_flags | = SDL_GetWindowFlags ( bd - > Window ) ;
sdl_flags | = ( viewport - > Flags & ImGuiViewportFlags_NoDecoration ) ? SDL_WINDOW_BORDERLESS : 0 ;
sdl_flags | = ( viewport - > Flags & ImGuiViewportFlags_NoDecoration ) ? 0 : SDL_WINDOW_RESIZABLE ;
# if !defined(_WIN32)
// See SDL hack in ImGui_ImplSDL3_ShowWindow().
sdl_flags | = ( viewport - > Flags & ImGuiViewportFlags_NoTaskBarIcon ) ? SDL_WINDOW_SKIP_TASKBAR : 0 ;
# endif
sdl_flags | = ( viewport - > Flags & ImGuiViewportFlags_TopMost ) ? SDL_WINDOW_ALWAYS_ON_TOP : 0 ;
vd - > Window = SDL_CreateWindow ( " No Title Yet " , ( int ) viewport - > Pos . x , ( int ) viewport - > Pos . y , ( int ) viewport - > Size . x , ( int ) viewport - > Size . y , sdl_flags ) ;
vd - > WindowOwned = true ;
if ( use_opengl )
{
vd - > GLContext = SDL_GL_CreateContext ( vd - > Window ) ;
SDL_GL_SetSwapInterval ( 0 ) ;
}
if ( use_opengl & & backup_context )
SDL_GL_MakeCurrent ( vd - > Window , backup_context ) ;
viewport - > PlatformHandle = ( void * ) vd - > Window ;
viewport - > PlatformHandleRaw = nullptr ;
SDL_SysWMinfo info ;
if ( SDL_GetWindowWMInfo ( vd - > Window , & info , SDL_SYSWM_CURRENT_VERSION ) )
{
# if defined(SDL_VIDEO_DRIVER_WINDOWS)
viewport - > PlatformHandleRaw = info . info . win . window ;
# elif defined(__APPLE__) && defined(SDL_VIDEO_DRIVER_COCOA)
viewport - > PlatformHandleRaw = ( void * ) info . info . cocoa . window ;
# endif
}
}
static void ImGui_ImplSDL3_DestroyWindow ( ImGuiViewport * viewport )
{
if ( ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData )
{
if ( vd - > GLContext & & vd - > WindowOwned )
SDL_GL_DeleteContext ( vd - > GLContext ) ;
if ( vd - > Window & & vd - > WindowOwned )
SDL_DestroyWindow ( vd - > Window ) ;
vd - > GLContext = nullptr ;
vd - > Window = nullptr ;
IM_DELETE ( vd ) ;
}
viewport - > PlatformUserData = viewport - > PlatformHandle = nullptr ;
}
static void ImGui_ImplSDL3_ShowWindow ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
# if defined(_WIN32)
HWND hwnd = ( HWND ) viewport - > PlatformHandleRaw ;
// SDL hack: Hide icon from task bar
// Note: SDL 2.0.6+ has a SDL_WINDOW_SKIP_TASKBAR flag which is supported under Windows but the way it create the window breaks our seamless transition.
if ( viewport - > Flags & ImGuiViewportFlags_NoTaskBarIcon )
{
LONG ex_style = : : GetWindowLong ( hwnd , GWL_EXSTYLE ) ;
ex_style & = ~ WS_EX_APPWINDOW ;
ex_style | = WS_EX_TOOLWINDOW ;
: : SetWindowLong ( hwnd , GWL_EXSTYLE , ex_style ) ;
}
// SDL hack: SDL always activate/focus windows :/
if ( viewport - > Flags & ImGuiViewportFlags_NoFocusOnAppearing )
{
: : ShowWindow ( hwnd , SW_SHOWNA ) ;
return ;
}
# endif
SDL_ShowWindow ( vd - > Window ) ;
}
static ImVec2 ImGui_ImplSDL3_GetWindowPos ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
int x = 0 , y = 0 ;
SDL_GetWindowPosition ( vd - > Window , & x , & y ) ;
return ImVec2 ( ( float ) x , ( float ) y ) ;
}
static void ImGui_ImplSDL3_SetWindowPos ( ImGuiViewport * viewport , ImVec2 pos )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
SDL_SetWindowPosition ( vd - > Window , ( int ) pos . x , ( int ) pos . y ) ;
}
static ImVec2 ImGui_ImplSDL3_GetWindowSize ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
int w = 0 , h = 0 ;
SDL_GetWindowSize ( vd - > Window , & w , & h ) ;
return ImVec2 ( ( float ) w , ( float ) h ) ;
}
static void ImGui_ImplSDL3_SetWindowSize ( ImGuiViewport * viewport , ImVec2 size )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
SDL_SetWindowSize ( vd - > Window , ( int ) size . x , ( int ) size . y ) ;
}
static void ImGui_ImplSDL3_SetWindowTitle ( ImGuiViewport * viewport , const char * title )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
SDL_SetWindowTitle ( vd - > Window , title ) ;
}
static void ImGui_ImplSDL3_SetWindowAlpha ( ImGuiViewport * viewport , float alpha )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
SDL_SetWindowOpacity ( vd - > Window , alpha ) ;
}
static void ImGui_ImplSDL3_SetWindowFocus ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
SDL_RaiseWindow ( vd - > Window ) ;
}
static bool ImGui_ImplSDL3_GetWindowFocus ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
return ( SDL_GetWindowFlags ( vd - > Window ) & SDL_WINDOW_INPUT_FOCUS ) ! = 0 ;
}
static bool ImGui_ImplSDL3_GetWindowMinimized ( ImGuiViewport * viewport )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
return ( SDL_GetWindowFlags ( vd - > Window ) & SDL_WINDOW_MINIMIZED ) ! = 0 ;
}
static void ImGui_ImplSDL3_RenderWindow ( ImGuiViewport * viewport , void * )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
if ( vd - > GLContext )
SDL_GL_MakeCurrent ( vd - > Window , vd - > GLContext ) ;
}
static void ImGui_ImplSDL3_SwapBuffers ( ImGuiViewport * viewport , void * )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
if ( vd - > GLContext )
{
SDL_GL_MakeCurrent ( vd - > Window , vd - > GLContext ) ;
SDL_GL_SwapWindow ( vd - > Window ) ;
}
}
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
// SDL is graceful enough to _not_ need <vulkan/vulkan.h> so we can safely include this.
# include <SDL3/SDL_vulkan.h>
static int ImGui_ImplSDL3_CreateVkSurface ( ImGuiViewport * viewport , ImU64 vk_instance , const void * vk_allocator , ImU64 * out_vk_surface )
{
ImGui_ImplSDL3_ViewportData * vd = ( ImGui_ImplSDL3_ViewportData * ) viewport - > PlatformUserData ;
( void ) vk_allocator ;
SDL_bool ret = SDL_Vulkan_CreateSurface ( vd - > Window , ( VkInstance ) vk_instance , ( VkSurfaceKHR * ) out_vk_surface ) ;
return ret ? 0 : 1 ; // ret ? VK_SUCCESS : VK_NOT_READY
}
static void ImGui_ImplSDL3_InitPlatformInterface ( SDL_Window * window , void * sdl_gl_context )
{
// Register platform interface (will be coupled with a renderer interface)
ImGuiPlatformIO & platform_io = ImGui : : GetPlatformIO ( ) ;
platform_io . Platform_CreateWindow = ImGui_ImplSDL3_CreateWindow ;
platform_io . Platform_DestroyWindow = ImGui_ImplSDL3_DestroyWindow ;
platform_io . Platform_ShowWindow = ImGui_ImplSDL3_ShowWindow ;
platform_io . Platform_SetWindowPos = ImGui_ImplSDL3_SetWindowPos ;
platform_io . Platform_GetWindowPos = ImGui_ImplSDL3_GetWindowPos ;
platform_io . Platform_SetWindowSize = ImGui_ImplSDL3_SetWindowSize ;
platform_io . Platform_GetWindowSize = ImGui_ImplSDL3_GetWindowSize ;
platform_io . Platform_SetWindowFocus = ImGui_ImplSDL3_SetWindowFocus ;
platform_io . Platform_GetWindowFocus = ImGui_ImplSDL3_GetWindowFocus ;
platform_io . Platform_GetWindowMinimized = ImGui_ImplSDL3_GetWindowMinimized ;
platform_io . Platform_SetWindowTitle = ImGui_ImplSDL3_SetWindowTitle ;
platform_io . Platform_RenderWindow = ImGui_ImplSDL3_RenderWindow ;
platform_io . Platform_SwapBuffers = ImGui_ImplSDL3_SwapBuffers ;
platform_io . Platform_SetWindowAlpha = ImGui_ImplSDL3_SetWindowAlpha ;
platform_io . Platform_CreateVkSurface = ImGui_ImplSDL3_CreateVkSurface ;
// Register main window handle (which is owned by the main application, not by us)
// This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports.
ImGuiViewport * main_viewport = ImGui : : GetMainViewport ( ) ;
ImGui_ImplSDL3_ViewportData * vd = IM_NEW ( ImGui_ImplSDL3_ViewportData ) ( ) ;
vd - > Window = window ;
vd - > WindowID = SDL_GetWindowID ( window ) ;
vd - > WindowOwned = false ;
vd - > GLContext = sdl_gl_context ;
main_viewport - > PlatformUserData = vd ;
main_viewport - > PlatformHandle = vd - > Window ;
}
static void ImGui_ImplSDL3_ShutdownPlatformInterface ( )
{
ImGui : : DestroyPlatformWindows ( ) ;
}