@ -59,10 +59,11 @@
# include "TargetConditionals.h"
# include "TargetConditionals.h"
# endif
# endif
# define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE SDL_VERSION_ATLEAST(2,0,4)
# define SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE ( SDL_VERSION_ATLEAST(2,0,4) && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS) )
# define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
# define SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH SDL_VERSION_ATLEAST(2,0,5)
# define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
# define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6)
// SDL Data
struct ImGui_ImplSDL2_Data
struct ImGui_ImplSDL2_Data
{
{
SDL_Window * Window ;
SDL_Window * Window ;
@ -156,6 +157,17 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
ImGuiIO & io = ImGui : : GetIO ( ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
IM_ASSERT ( io . BackendPlatformUserData = = NULL & & " Already initialized a platform backend! " ) ;
IM_ASSERT ( io . BackendPlatformUserData = = NULL & & " Already initialized a platform backend! " ) ;
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
const char * sdl_backend = SDL_GetCurrentVideoDriver ( ) ;
const char * global_mouse_whitelist [ ] = { " windows " , " cocoa " , " x11 " , " DIVE " , " VMAN " } ;
bool mouse_can_use_global_state = false ;
# if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
for ( int n = 0 ; n < IM_ARRAYSIZE ( global_mouse_whitelist ) ; n + + )
if ( strncmp ( sdl_backend , global_mouse_whitelist [ n ] , strlen ( global_mouse_whitelist [ n ] ) ) = = 0 )
mouse_can_use_global_state = true ;
# endif
// Setup backend capabilities flags
// Setup backend capabilities flags
ImGui_ImplSDL2_Data * bd = IM_NEW ( ImGui_ImplSDL2_Data ) ( ) ;
ImGui_ImplSDL2_Data * bd = IM_NEW ( ImGui_ImplSDL2_Data ) ( ) ;
io . BackendPlatformUserData = ( void * ) bd ;
io . BackendPlatformUserData = ( void * ) bd ;
@ -164,6 +176,7 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
io . BackendFlags | = ImGuiBackendFlags_HasSetMousePos ; // We can honor io.WantSetMousePos requests (optional, rarely used)
io . BackendFlags | = ImGuiBackendFlags_HasSetMousePos ; // We can honor io.WantSetMousePos requests (optional, rarely used)
bd - > Window = window ;
bd - > Window = window ;
bd - > MouseCanUseGlobalState = mouse_can_use_global_state ;
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
io . KeyMap [ ImGuiKey_Tab ] = SDL_SCANCODE_TAB ;
io . KeyMap [ ImGuiKey_Tab ] = SDL_SCANCODE_TAB ;
@ -204,20 +217,11 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
bd - > MouseCursors [ ImGuiMouseCursor_Hand ] = SDL_CreateSystemCursor ( SDL_SYSTEM_CURSOR_HAND ) ;
bd - > MouseCursors [ ImGuiMouseCursor_Hand ] = SDL_CreateSystemCursor ( SDL_SYSTEM_CURSOR_HAND ) ;
bd - > MouseCursors [ ImGuiMouseCursor_NotAllowed ] = SDL_CreateSystemCursor ( SDL_SYSTEM_CURSOR_NO ) ;
bd - > MouseCursors [ ImGuiMouseCursor_NotAllowed ] = SDL_CreateSystemCursor ( SDL_SYSTEM_CURSOR_NO ) ;
// Check and store if we are on a SDL backend that supports global mouse position
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
const char * sdl_backend = SDL_GetCurrentVideoDriver ( ) ;
const char * global_mouse_whitelist [ ] = { " windows " , " cocoa " , " x11 " , " DIVE " , " VMAN " } ;
bd - > MouseCanUseGlobalState = false ;
for ( int n = 0 ; n < IM_ARRAYSIZE ( global_mouse_whitelist ) ; n + + )
if ( strncmp ( sdl_backend , global_mouse_whitelist [ n ] , strlen ( global_mouse_whitelist [ n ] ) ) = = 0 )
bd - > MouseCanUseGlobalState = true ;
# ifdef _WIN32
# ifdef _WIN32
SDL_SysWMinfo wmI nfo;
SDL_SysWMinfo info ;
SDL_VERSION ( & wmI nfo. version ) ;
SDL_VERSION ( & info . version ) ;
SDL_GetWindowWMInfo ( window , & wmInfo) ;
if ( SDL_GetWindowWMInfo ( window , & info ) )
io . ImeWindowHandle = wmI nfo. info . win . window ;
io . ImeWindowHandle = info . info . win . window ;
# else
# else
( void ) window ;
( void ) window ;
# endif
# endif
@ -278,55 +282,59 @@ void ImGui_ImplSDL2_Shutdown()
static void ImGui_ImplSDL2_UpdateMousePosAndButtons ( )
static void ImGui_ImplSDL2_UpdateMousePosAndButtons ( )
{
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
ImGui_ImplSDL2_Data * bd = ImGui_ImplSDL2_GetBackendData ( ) ;
ImGui_ImplSDL2_Data * bd = ImGui_ImplSDL2_GetBackendData ( ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
ImVec2 mouse_pos_prev = io . MousePos ;
if ( io . WantSetMousePos )
io . MousePos = ImVec2 ( - FLT_MAX , - FLT_MAX ) ;
SDL_WarpMouseInWindow ( bd - > Window , ( int ) io . MousePos . x , ( int ) io . MousePos . y ) ;
else
io . MousePos = ImVec2 ( - FLT_MAX , - FLT_MAX ) ;
int mx , my ;
// Update mouse buttons
Uint32 mouse_buttons = SDL_GetMouseState ( & mx , & my ) ;
int mouse_x_local , mouse_y_local ;
Uint32 mouse_buttons = SDL_GetMouseState ( & mouse_x_local , & mouse_y_local ) ;
io . MouseDown [ 0 ] = bd - > MousePressed [ 0 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_LEFT ) ) ! = 0 ; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io . MouseDown [ 0 ] = bd - > MousePressed [ 0 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_LEFT ) ) ! = 0 ; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
io . MouseDown [ 1 ] = bd - > MousePressed [ 1 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_RIGHT ) ) ! = 0 ;
io . MouseDown [ 1 ] = bd - > MousePressed [ 1 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_RIGHT ) ) ! = 0 ;
io . MouseDown [ 2 ] = bd - > MousePressed [ 2 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_MIDDLE ) ) ! = 0 ;
io . MouseDown [ 2 ] = bd - > MousePressed [ 2 ] | | ( mouse_buttons & SDL_BUTTON ( SDL_BUTTON_MIDDLE ) ) ! = 0 ;
bd - > MousePressed [ 0 ] = bd - > MousePressed [ 1 ] = bd - > MousePressed [ 2 ] = false ;
bd - > MousePressed [ 0 ] = bd - > MousePressed [ 1 ] = bd - > MousePressed [ 2 ] = false ;
# if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE && !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) && !(defined(__APPLE__) && TARGET_OS_IOS)
// Obtain focused and hovered window. We forward mouse input when focused or when hovered (and no other window is capturing)
SDL_Window * focused_window = SDL_GetKeyboardFocus ( ) ; // Mouse position won't be reported unless window is focused.
# if SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE
# if SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH
SDL_Window * focused_window = SDL_GetKeyboardFocus ( ) ;
SDL_Window * hovered_window = SDL_GetMouseFocus ( ) ; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH enabled.
SDL_Window * hovered_window = SDL_HAS_MOUSE_FOCUS_CLICKTHROUGH ? SDL_GetMouseFocus ( ) : NULL ; // This is better but is only reliably useful with SDL 2.0.5+ and SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH.
SDL_Window * mouse_window = ( bd - > Window = = focused_window | | bd - > Window = = hovered_window ) ? bd - > Window : NULL ;
SDL_Window * mouse_window = NULL ;
if ( hovered_window & & bd - > Window = = hovered_window )
mouse_window = hovered_window ;
else if ( focused_window & & bd - > Window = = focused_window )
mouse_window = focused_window ;
// 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 ( ImGui : : IsAnyMouseDown ( ) ? SDL_TRUE : SDL_FALSE ) ;
# else
# else
SDL_Window * mouse_window = ( bd - > Window = = focused_window ) ? bd - > Window : NULL ;
// SDL 2.0.3 and non-windowed systems: single-viewport only
SDL_Window * mouse_window = ( SDL_GetWindowFlags ( bd - > Window ) & SDL_WINDOW_INPUT_FOCUS ) ? bd - > Window : NULL ;
# endif
# endif
if ( mouse_window ! = NULL )
if ( mouse_window = = NULL )
return ;
// 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 , ( int ) mouse_pos_prev . x , ( int ) mouse_pos_prev . y ) ;
// Set Dear ImGui mouse position from OS position + get buttons. (this is the common behavior)
if ( bd - > MouseCanUseGlobalState )
{
{
if ( bd - > MouseCanUseGlobalState )
// 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)
{
// Unlike local position obtained earlier this will be valid when straying out of bounds.
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
int mouse_x_global , mouse_y_global ;
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
SDL_GetGlobalMouseState ( & mouse_x_global , & mouse_y_global ) ;
// Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI
int window_x , window_y ;
int wx , wy ;
SDL_GetWindowPosition ( mouse_window , & window_x , & window_y ) ;
SDL_GetWindowPosition ( mouse_window , & wx , & wy ) ;
io . MousePos = ImVec2 ( ( float ) ( mouse_x_global - window_x ) , ( float ) ( mouse_y_global - window_y ) ) ;
SDL_GetGlobalMouseState ( & mx , & my ) ;
}
mx - = wx ;
else
my - = wy ;
{
}
io . MousePos = ImVec2 ( ( float ) mouse_x_local , ( float ) mouse_y_local ) ;
io . MousePos = ImVec2 ( ( float ) mx , ( float ) my ) ;
}
}
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries shouldn't e.g. trigger the OS window resize cursor.
// The function is only supported from SDL 2.0.4 (released Jan 2016)
bool any_mouse_button_down = ImGui : : IsAnyMouseDown ( ) ;
SDL_CaptureMouse ( any_mouse_button_down ? SDL_TRUE : SDL_FALSE ) ;
# else
// SDL 2.0.3 and non-windowed systems
if ( SDL_GetWindowFlags ( bd - > Window ) & SDL_WINDOW_INPUT_FOCUS )
io . MousePos = ImVec2 ( ( float ) mx , ( float ) my ) ;
# endif
}
}
static void ImGui_ImplSDL2_UpdateMouseCursor ( )
static void ImGui_ImplSDL2_UpdateMouseCursor ( )
@ -393,9 +401,9 @@ static void ImGui_ImplSDL2_UpdateGamepads()
void ImGui_ImplSDL2_NewFrame ( )
void ImGui_ImplSDL2_NewFrame ( )
{
{
ImGuiIO & io = ImGui : : GetIO ( ) ;
ImGui_ImplSDL2_Data * bd = ImGui_ImplSDL2_GetBackendData ( ) ;
ImGui_ImplSDL2_Data * bd = ImGui_ImplSDL2_GetBackendData ( ) ;
IM_ASSERT ( bd ! = NULL & & " Did you call ImGui_ImplSDL2_Init()? " ) ;
IM_ASSERT ( bd ! = NULL & & " Did you call ImGui_ImplSDL2_Init()? " ) ;
ImGuiIO & io = ImGui : : GetIO ( ) ;
// Setup display size (every frame to accommodate for window resizing)
// Setup display size (every frame to accommodate for window resizing)
int w , h ;
int w , h ;