Browse Source

Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_dx12.cpp
ocornut 2 days ago
parent
commit
3dcd17f402

+ 5 - 5
backends/imgui_impl_dx10.cpp

@@ -75,7 +75,7 @@ struct ImGui_ImplDX10_Data
     ID3D10InputLayout*          pInputLayout;
     ID3D10InputLayout*          pInputLayout;
     ID3D10Buffer*               pVertexConstantBuffer;
     ID3D10Buffer*               pVertexConstantBuffer;
     ID3D10PixelShader*          pPixelShader;
     ID3D10PixelShader*          pPixelShader;
-    ID3D10SamplerState*         pFontSampler;
+    ID3D10SamplerState*         pTexSamplerLinear;
     ID3D10RasterizerState*      pRasterizerState;
     ID3D10RasterizerState*      pRasterizerState;
     ID3D10BlendState*           pBlendState;
     ID3D10BlendState*           pBlendState;
     ID3D10DepthStencilState*    pDepthStencilState;
     ID3D10DepthStencilState*    pDepthStencilState;
@@ -146,7 +146,7 @@ static void ImGui_ImplDX10_SetupRenderState(ImDrawData* draw_data, ID3D10Device*
     device->VSSetShader(bd->pVertexShader);
     device->VSSetShader(bd->pVertexShader);
     device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
     device->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
     device->PSSetShader(bd->pPixelShader);
     device->PSSetShader(bd->pPixelShader);
-    device->PSSetSamplers(0, 1, &bd->pFontSampler);
+    device->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
     device->GSSetShader(nullptr);
     device->GSSetShader(nullptr);
 
 
     // Setup render state
     // Setup render state
@@ -263,7 +263,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
     ImGui_ImplDX10_RenderState render_state;
     ImGui_ImplDX10_RenderState render_state;
     render_state.Device = bd->pd3dDevice;
     render_state.Device = bd->pd3dDevice;
-    render_state.SamplerDefault = bd->pFontSampler;
+    render_state.SamplerDefault = bd->pTexSamplerLinear;
     render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
     render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
     platform_io.Renderer_RenderState = &render_state;
     platform_io.Renderer_RenderState = &render_state;
 
 
@@ -569,7 +569,7 @@ bool    ImGui_ImplDX10_CreateDeviceObjects()
         desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
         desc.ComparisonFunc = D3D10_COMPARISON_ALWAYS;
         desc.MinLOD = 0.f;
         desc.MinLOD = 0.f;
         desc.MaxLOD = 0.f;
         desc.MaxLOD = 0.f;
-        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
     }
     }
 
 
     return true;
     return true;
@@ -585,7 +585,7 @@ void    ImGui_ImplDX10_InvalidateDeviceObjects()
     for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
     for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)
         if (tex->RefCount == 1)
         if (tex->RefCount == 1)
             ImGui_ImplDX10_DestroyTexture(tex);
             ImGui_ImplDX10_DestroyTexture(tex);
-    if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
+    if (bd->pTexSamplerLinear)      { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }

+ 6 - 6
backends/imgui_impl_dx11.cpp

@@ -79,7 +79,7 @@ struct ImGui_ImplDX11_Data
     ID3D11InputLayout*          pInputLayout;
     ID3D11InputLayout*          pInputLayout;
     ID3D11Buffer*               pVertexConstantBuffer;
     ID3D11Buffer*               pVertexConstantBuffer;
     ID3D11PixelShader*          pPixelShader;
     ID3D11PixelShader*          pPixelShader;
-    ID3D11SamplerState*         pFontSampler;
+    ID3D11SamplerState*         pTexSamplerLinear;
     ID3D11RasterizerState*      pRasterizerState;
     ID3D11RasterizerState*      pRasterizerState;
     ID3D11BlendState*           pBlendState;
     ID3D11BlendState*           pBlendState;
     ID3D11DepthStencilState*    pDepthStencilState;
     ID3D11DepthStencilState*    pDepthStencilState;
@@ -107,7 +107,7 @@ static void ImGui_ImplDX11_InitMultiViewportSupport();
 static void ImGui_ImplDX11_ShutdownMultiViewportSupport();
 static void ImGui_ImplDX11_ShutdownMultiViewportSupport();
 
 
 // Functions
 // Functions
-static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
+static void ImGui_ImplDX11_SetupRenderState(const ImDrawData* draw_data, ID3D11DeviceContext* device_ctx)
 {
 {
     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
     ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
 
 
@@ -151,7 +151,7 @@ static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceC
     device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
     device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0);
     device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
     device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer);
     device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
     device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0);
-    device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler);
+    device_ctx->PSSetSamplers(0, 1, &bd->pTexSamplerLinear);
     device_ctx->GSSetShader(nullptr, nullptr, 0);
     device_ctx->GSSetShader(nullptr, nullptr, 0);
     device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
     device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
     device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
     device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used..
@@ -279,7 +279,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
     ImGui_ImplDX11_RenderState render_state;
     ImGui_ImplDX11_RenderState render_state;
     render_state.Device = bd->pd3dDevice;
     render_state.Device = bd->pd3dDevice;
     render_state.DeviceContext = bd->pd3dDeviceContext;
     render_state.DeviceContext = bd->pd3dDeviceContext;
-    render_state.SamplerDefault = bd->pFontSampler;
+    render_state.SamplerDefault = bd->pTexSamplerLinear;
     render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
     render_state.VertexConstantBuffer = bd->pVertexConstantBuffer;
     platform_io.Renderer_RenderState = &render_state;
     platform_io.Renderer_RenderState = &render_state;
 
 
@@ -586,7 +586,7 @@ bool    ImGui_ImplDX11_CreateDeviceObjects()
         desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
         desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
         desc.MinLOD = 0.f;
         desc.MinLOD = 0.f;
         desc.MaxLOD = 0.f;
         desc.MaxLOD = 0.f;
-        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler);
+        bd->pd3dDevice->CreateSamplerState(&desc, &bd->pTexSamplerLinear);
     }
     }
 
 
     return true;
     return true;
@@ -603,7 +603,7 @@ void    ImGui_ImplDX11_InvalidateDeviceObjects()
         if (tex->RefCount == 1)
         if (tex->RefCount == 1)
             ImGui_ImplDX11_DestroyTexture(tex);
             ImGui_ImplDX11_DestroyTexture(tex);
 
 
-    if (bd->pFontSampler)           { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
+    if (bd->pTexSamplerLinear)    { bd->pTexSamplerLinear->Release(); bd->pTexSamplerLinear = nullptr; }
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pIB)                    { bd->pIB->Release(); bd->pIB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pVB)                    { bd->pVB->Release(); bd->pVB = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
     if (bd->pBlendState)            { bd->pBlendState->Release(); bd->pBlendState = nullptr; }

+ 19 - 16
backends/imgui_impl_dx12.cpp

@@ -98,7 +98,10 @@ struct ImGui_ImplDX12_Data
     DXGI_FORMAT                 DSVFormat;
     DXGI_FORMAT                 DSVFormat;
     ID3D12DescriptorHeap*       pd3dSrvDescHeap;
     ID3D12DescriptorHeap*       pd3dSrvDescHeap;
     UINT                        numFramesInFlight;
     UINT                        numFramesInFlight;
-    ImGui_ImplDX12_Texture      FontTexture;
+
+    ImGui_ImplDX12_RenderBuffers* pFrameResources;
+    UINT                        frameIndex;
+
     bool                        LegacySingleDescriptorUsed;
     bool                        LegacySingleDescriptorUsed;
 
 
     ImGui_ImplDX12_Data()       { memset((void*)this, 0, sizeof(*this)); }
     ImGui_ImplDX12_Data()       { memset((void*)this, 0, sizeof(*this)); }
@@ -655,26 +658,26 @@ bool    ImGui_ImplDX12_CreateDeviceObjects()
         param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
         param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
 
 
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
-        D3D12_STATIC_SAMPLER_DESC staticSampler = {};
-        staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
-        staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
-        staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
-        staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
-        staticSampler.MipLODBias = 0.f;
-        staticSampler.MaxAnisotropy = 0;
-        staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
-        staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
-        staticSampler.MinLOD = 0.f;
-        staticSampler.MaxLOD = D3D12_FLOAT32_MAX;
-        staticSampler.ShaderRegister = 0;
-        staticSampler.RegisterSpace = 0;
-        staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
+        D3D12_STATIC_SAMPLER_DESC staticSampler[1] = {};
+        staticSampler[0].Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
+        staticSampler[0].AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+        staticSampler[0].AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+        staticSampler[0].AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
+        staticSampler[0].MipLODBias = 0.f;
+        staticSampler[0].MaxAnisotropy = 0;
+        staticSampler[0].ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS;
+        staticSampler[0].BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK;
+        staticSampler[0].MinLOD = 0.f;
+        staticSampler[0].MaxLOD = D3D12_FLOAT32_MAX;
+        staticSampler[0].ShaderRegister = 0;
+        staticSampler[0].RegisterSpace = 0;
+        staticSampler[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
 
 
         D3D12_ROOT_SIGNATURE_DESC desc = {};
         D3D12_ROOT_SIGNATURE_DESC desc = {};
         desc.NumParameters = _countof(param);
         desc.NumParameters = _countof(param);
         desc.pParameters = param;
         desc.pParameters = param;
         desc.NumStaticSamplers = 1;
         desc.NumStaticSamplers = 1;
-        desc.pStaticSamplers = &staticSampler;
+        desc.pStaticSamplers = &staticSampler[0];
         desc.Flags =
         desc.Flags =
             D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
             D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
             D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
             D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |

+ 7 - 3
backends/imgui_impl_opengl3.cpp

@@ -248,6 +248,7 @@ struct ImGui_ImplOpenGL3_Data
     GLsizeiptr      VertexBufferSize;
     GLsizeiptr      VertexBufferSize;
     GLsizeiptr      IndexBufferSize;
     GLsizeiptr      IndexBufferSize;
     bool            HasPolygonMode;
     bool            HasPolygonMode;
+    bool            HasBindSampler;
     bool            HasClipOrigin;
     bool            HasClipOrigin;
     bool            UseBufferSubData;
     bool            UseBufferSubData;
     ImVector<char>  TempBuffer;
     ImVector<char>  TempBuffer;
@@ -403,6 +404,9 @@ bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
     // Detect extensions we support
     // Detect extensions we support
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE
     bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
     bd->HasPolygonMode = (!bd->GlProfileIsES2 && !bd->GlProfileIsES3);
+#endif
+#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
+    bd->HasBindSampler = (bd->GlVersion >= 330 || bd->GlProfileIsES3);
 #endif
 #endif
     bd->HasClipOrigin = (bd->GlVersion >= 450);
     bd->HasClipOrigin = (bd->GlVersion >= 450);
 #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
 #ifdef IMGUI_IMPL_OPENGL_HAS_EXTENSIONS
@@ -505,7 +509,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
     glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
     glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
 
 
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
-    if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
+    if (bd->HasBindSampler)
         glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
         glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 and GL ES 3.0 may set that otherwise.
 #endif
 #endif
 
 
@@ -553,7 +557,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
     GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
     GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
     GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
     GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
-    GLuint last_sampler; if (bd->GlVersion >= 330 || bd->GlProfileIsES3) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
+    GLuint last_sampler; if (bd->HasBindSampler) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
 #endif
 #endif
     GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
     GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
 #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
 #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
@@ -678,7 +682,7 @@ void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
     if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program);
     if (last_program == 0 || glIsProgram(last_program)) glUseProgram(last_program);
     glBindTexture(GL_TEXTURE_2D, last_texture);
     glBindTexture(GL_TEXTURE_2D, last_texture);
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
 #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
-    if (bd->GlVersion >= 330 || bd->GlProfileIsES3)
+    if (bd->HasBindSampler)
         glBindSampler(0, last_sampler);
         glBindSampler(0, last_sampler);
 #endif
 #endif
     glActiveTexture(last_active_texture);
     glActiveTexture(last_active_texture);

+ 17 - 1
backends/imgui_impl_opengl3_loader.h

@@ -180,6 +180,7 @@ typedef khronos_uint8_t GLubyte;
 #define GL_RENDERER                       0x1F01
 #define GL_RENDERER                       0x1F01
 #define GL_VERSION                        0x1F02
 #define GL_VERSION                        0x1F02
 #define GL_EXTENSIONS                     0x1F03
 #define GL_EXTENSIONS                     0x1F03
+#define GL_NEAREST                        0x2600
 #define GL_LINEAR                         0x2601
 #define GL_LINEAR                         0x2601
 #define GL_TEXTURE_MAG_FILTER             0x2800
 #define GL_TEXTURE_MAG_FILTER             0x2800
 #define GL_TEXTURE_MIN_FILTER             0x2801
 #define GL_TEXTURE_MIN_FILTER             0x2801
@@ -400,9 +401,15 @@ GLAPI void APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum
 #ifndef GL_VERSION_3_3
 #ifndef GL_VERSION_3_3
 #define GL_VERSION_3_3 1
 #define GL_VERSION_3_3 1
 #define GL_SAMPLER_BINDING                0x8919
 #define GL_SAMPLER_BINDING                0x8919
+typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
 typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
 typedef void (APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
 #ifdef GL_GLEXT_PROTOTYPES
 #ifdef GL_GLEXT_PROTOTYPES
+GLAPI void APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GLAPI void APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
 GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
 GLAPI void APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GLAPI void APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
 #endif
 #endif
 #endif /* GL_VERSION_3_3 */
 #endif /* GL_VERSION_3_3 */
 #ifndef GL_VERSION_4_1
 #ifndef GL_VERSION_4_1
@@ -483,7 +490,7 @@ GL3W_API GL3WglProc imgl3wGetProcAddress(const char *proc);
 
 
 /* gl3w internal state */
 /* gl3w internal state */
 union ImGL3WProcs {
 union ImGL3WProcs {
-    GL3WglProc ptr[60];
+    GL3WglProc ptr[63];
     struct {
     struct {
         PFNGLACTIVETEXTUREPROC            ActiveTexture;
         PFNGLACTIVETEXTUREPROC            ActiveTexture;
         PFNGLATTACHSHADERPROC             AttachShader;
         PFNGLATTACHSHADERPROC             AttachShader;
@@ -503,6 +510,7 @@ union ImGL3WProcs {
         PFNGLCREATESHADERPROC             CreateShader;
         PFNGLCREATESHADERPROC             CreateShader;
         PFNGLDELETEBUFFERSPROC            DeleteBuffers;
         PFNGLDELETEBUFFERSPROC            DeleteBuffers;
         PFNGLDELETEPROGRAMPROC            DeleteProgram;
         PFNGLDELETEPROGRAMPROC            DeleteProgram;
+        PFNGLDELETESAMPLERSPROC           DeleteSamplers;
         PFNGLDELETESHADERPROC             DeleteShader;
         PFNGLDELETESHADERPROC             DeleteShader;
         PFNGLDELETETEXTURESPROC           DeleteTextures;
         PFNGLDELETETEXTURESPROC           DeleteTextures;
         PFNGLDELETEVERTEXARRAYSPROC       DeleteVertexArrays;
         PFNGLDELETEVERTEXARRAYSPROC       DeleteVertexArrays;
@@ -515,6 +523,7 @@ union ImGL3WProcs {
         PFNGLENABLEVERTEXATTRIBARRAYPROC  EnableVertexAttribArray;
         PFNGLENABLEVERTEXATTRIBARRAYPROC  EnableVertexAttribArray;
         PFNGLFLUSHPROC                    Flush;
         PFNGLFLUSHPROC                    Flush;
         PFNGLGENBUFFERSPROC               GenBuffers;
         PFNGLGENBUFFERSPROC               GenBuffers;
+        PFNGLGENSAMPLERSPROC              GenSamplers;
         PFNGLGENTEXTURESPROC              GenTextures;
         PFNGLGENTEXTURESPROC              GenTextures;
         PFNGLGENVERTEXARRAYSPROC          GenVertexArrays;
         PFNGLGENVERTEXARRAYSPROC          GenVertexArrays;
         PFNGLGETATTRIBLOCATIONPROC        GetAttribLocation;
         PFNGLGETATTRIBLOCATIONPROC        GetAttribLocation;
@@ -535,6 +544,7 @@ union ImGL3WProcs {
         PFNGLPIXELSTOREIPROC              PixelStorei;
         PFNGLPIXELSTOREIPROC              PixelStorei;
         PFNGLPOLYGONMODEPROC              PolygonMode;
         PFNGLPOLYGONMODEPROC              PolygonMode;
         PFNGLREADPIXELSPROC               ReadPixels;
         PFNGLREADPIXELSPROC               ReadPixels;
+        PFNGLSAMPLERPARAMETERIPROC        SamplerParameteri;
         PFNGLSCISSORPROC                  Scissor;
         PFNGLSCISSORPROC                  Scissor;
         PFNGLSHADERSOURCEPROC             ShaderSource;
         PFNGLSHADERSOURCEPROC             ShaderSource;
         PFNGLTEXIMAGE2DPROC               TexImage2D;
         PFNGLTEXIMAGE2DPROC               TexImage2D;
@@ -569,6 +579,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
 #define glCreateShader                    imgl3wProcs.gl.CreateShader
 #define glCreateShader                    imgl3wProcs.gl.CreateShader
 #define glDeleteBuffers                   imgl3wProcs.gl.DeleteBuffers
 #define glDeleteBuffers                   imgl3wProcs.gl.DeleteBuffers
 #define glDeleteProgram                   imgl3wProcs.gl.DeleteProgram
 #define glDeleteProgram                   imgl3wProcs.gl.DeleteProgram
+#define glDeleteSamplers                  imgl3wProcs.gl.DeleteSamplers
 #define glDeleteShader                    imgl3wProcs.gl.DeleteShader
 #define glDeleteShader                    imgl3wProcs.gl.DeleteShader
 #define glDeleteTextures                  imgl3wProcs.gl.DeleteTextures
 #define glDeleteTextures                  imgl3wProcs.gl.DeleteTextures
 #define glDeleteVertexArrays              imgl3wProcs.gl.DeleteVertexArrays
 #define glDeleteVertexArrays              imgl3wProcs.gl.DeleteVertexArrays
@@ -581,6 +592,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
 #define glEnableVertexAttribArray         imgl3wProcs.gl.EnableVertexAttribArray
 #define glEnableVertexAttribArray         imgl3wProcs.gl.EnableVertexAttribArray
 #define glFlush                           imgl3wProcs.gl.Flush
 #define glFlush                           imgl3wProcs.gl.Flush
 #define glGenBuffers                      imgl3wProcs.gl.GenBuffers
 #define glGenBuffers                      imgl3wProcs.gl.GenBuffers
+#define glGenSamplers                     imgl3wProcs.gl.GenSamplers
 #define glGenTextures                     imgl3wProcs.gl.GenTextures
 #define glGenTextures                     imgl3wProcs.gl.GenTextures
 #define glGenVertexArrays                 imgl3wProcs.gl.GenVertexArrays
 #define glGenVertexArrays                 imgl3wProcs.gl.GenVertexArrays
 #define glGetAttribLocation               imgl3wProcs.gl.GetAttribLocation
 #define glGetAttribLocation               imgl3wProcs.gl.GetAttribLocation
@@ -601,6 +613,7 @@ GL3W_API extern union ImGL3WProcs imgl3wProcs;
 #define glPixelStorei                     imgl3wProcs.gl.PixelStorei
 #define glPixelStorei                     imgl3wProcs.gl.PixelStorei
 #define glPolygonMode                     imgl3wProcs.gl.PolygonMode
 #define glPolygonMode                     imgl3wProcs.gl.PolygonMode
 #define glReadPixels                      imgl3wProcs.gl.ReadPixels
 #define glReadPixels                      imgl3wProcs.gl.ReadPixels
+#define glSamplerParameteri               imgl3wProcs.gl.SamplerParameteri
 #define glScissor                         imgl3wProcs.gl.Scissor
 #define glScissor                         imgl3wProcs.gl.Scissor
 #define glShaderSource                    imgl3wProcs.gl.ShaderSource
 #define glShaderSource                    imgl3wProcs.gl.ShaderSource
 #define glTexImage2D                      imgl3wProcs.gl.TexImage2D
 #define glTexImage2D                      imgl3wProcs.gl.TexImage2D
@@ -870,6 +883,7 @@ static const char *proc_names[] = {
     "glCreateShader",
     "glCreateShader",
     "glDeleteBuffers",
     "glDeleteBuffers",
     "glDeleteProgram",
     "glDeleteProgram",
+    "glDeleteSamplers",
     "glDeleteShader",
     "glDeleteShader",
     "glDeleteTextures",
     "glDeleteTextures",
     "glDeleteVertexArrays",
     "glDeleteVertexArrays",
@@ -882,6 +896,7 @@ static const char *proc_names[] = {
     "glEnableVertexAttribArray",
     "glEnableVertexAttribArray",
     "glFlush",
     "glFlush",
     "glGenBuffers",
     "glGenBuffers",
+    "glGenSamplers",
     "glGenTextures",
     "glGenTextures",
     "glGenVertexArrays",
     "glGenVertexArrays",
     "glGetAttribLocation",
     "glGetAttribLocation",
@@ -902,6 +917,7 @@ static const char *proc_names[] = {
     "glPixelStorei",
     "glPixelStorei",
     "glPolygonMode",
     "glPolygonMode",
     "glReadPixels",
     "glReadPixels",
+    "glSamplerParameteri",
     "glScissor",
     "glScissor",
     "glShaderSource",
     "glShaderSource",
     "glTexImage2D",
     "glTexImage2D",

+ 10 - 10
backends/imgui_impl_sdlgpu3.cpp

@@ -61,7 +61,7 @@ struct ImGui_ImplSDLGPU3_Data
     SDL_GPUShader*               VertexShader           = nullptr;
     SDL_GPUShader*               VertexShader           = nullptr;
     SDL_GPUShader*               FragmentShader         = nullptr;
     SDL_GPUShader*               FragmentShader         = nullptr;
     SDL_GPUGraphicsPipeline*     Pipeline               = nullptr;
     SDL_GPUGraphicsPipeline*     Pipeline               = nullptr;
-    SDL_GPUSampler*              TexSampler             = nullptr;
+    SDL_GPUSampler*              TexSamplerLinear       = nullptr;
     SDL_GPUTransferBuffer*       TexTransferBuffer      = nullptr;
     SDL_GPUTransferBuffer*       TexTransferBuffer      = nullptr;
     uint32_t                     TexTransferBufferSize  = 0;
     uint32_t                     TexTransferBufferSize  = 0;
 
 
@@ -87,7 +87,7 @@ static ImGui_ImplSDLGPU3_Data* ImGui_ImplSDLGPU3_GetBackendData()
 static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
 static void ImGui_ImplSDLGPU3_SetupRenderState(ImDrawData* draw_data, ImGui_ImplSDLGPU3_RenderState* render_state, SDL_GPUGraphicsPipeline* pipeline, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, ImGui_ImplSDLGPU3_FrameData* fd, uint32_t fb_width, uint32_t fb_height)
 {
 {
     ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
     ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
-    render_state->SamplerCurrent = bd->TexSampler;
+    render_state->SamplerCurrent = bd->TexSamplerLinear;
 
 
     // Bind graphics pipeline
     // Bind graphics pipeline
     SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
     SDL_BindGPUGraphicsPipeline(render_pass, pipeline);
@@ -236,7 +236,7 @@ void ImGui_ImplSDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffe
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
     ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
     ImGui_ImplSDLGPU3_RenderState render_state;
     ImGui_ImplSDLGPU3_RenderState render_state;
     render_state.Device = bd->InitInfo.Device;
     render_state.Device = bd->InitInfo.Device;
-    render_state.SamplerDefault = render_state.SamplerCurrent = bd->TexSampler;
+    render_state.SamplerDefault = render_state.SamplerCurrent = bd->TexSamplerLinear;
     platform_io.Renderer_RenderState = &render_state;
     platform_io.Renderer_RenderState = &render_state;
 
 
     ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
     ImGui_ImplSDLGPU3_SetupRenderState(draw_data, &render_state, pipeline, command_buffer, render_pass, fd, fb_width, fb_height);
@@ -341,7 +341,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
         texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1;
         texture_info.sample_count = SDL_GPU_SAMPLECOUNT_1;
 
 
         SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info);
         SDL_GPUTexture* raw_tex = SDL_CreateGPUTexture(v->Device, &texture_info);
-        IM_ASSERT(raw_tex != nullptr && "Failed to create font texture, call SDL_GetError() for more info");
+        IM_ASSERT(raw_tex != nullptr && "Failed to create texture, call SDL_GetError() for more info");
 
 
         // Store identifiers
         // Store identifiers
         tex->SetTexID((ImTextureID)(intptr_t)raw_tex);
         tex->SetTexID((ImTextureID)(intptr_t)raw_tex);
@@ -371,7 +371,7 @@ void ImGui_ImplSDLGPU3_UpdateTexture(ImTextureData* tex)
             transferbuffer_info.size = upload_size + 1024;
             transferbuffer_info.size = upload_size + 1024;
             bd->TexTransferBufferSize = upload_size + 1024;
             bd->TexTransferBufferSize = upload_size + 1024;
             bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
             bd->TexTransferBuffer = SDL_CreateGPUTransferBuffer(v->Device, &transferbuffer_info);
-            IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create font transfer buffer, call SDL_GetError() for more information");
+            IM_ASSERT(bd->TexTransferBuffer != nullptr && "Failed to create transfer buffer, call SDL_GetError() for more information");
         }
         }
 
 
         // Copy to transfer buffer
         // Copy to transfer buffer
@@ -560,7 +560,7 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
 
 
     ImGui_ImplSDLGPU3_DestroyDeviceObjects();
     ImGui_ImplSDLGPU3_DestroyDeviceObjects();
 
 
-    if (bd->TexSampler == nullptr)
+    if (bd->TexSamplerLinear == nullptr)
     {
     {
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         SDL_GPUSamplerCreateInfo sampler_info = {};
         SDL_GPUSamplerCreateInfo sampler_info = {};
@@ -577,8 +577,8 @@ void ImGui_ImplSDLGPU3_CreateDeviceObjects()
         sampler_info.max_anisotropy = 1.0f;
         sampler_info.max_anisotropy = 1.0f;
         sampler_info.enable_compare = false;
         sampler_info.enable_compare = false;
 
 
-        bd->TexSampler = SDL_CreateGPUSampler(v->Device, &sampler_info);
-        IM_ASSERT(bd->TexSampler != nullptr && "Failed to create font sampler, call SDL_GetError() for more information");
+        bd->TexSamplerLinear = SDL_CreateGPUSampler(v->Device, &sampler_info);
+        IM_ASSERT(bd->TexSamplerLinear != nullptr && "Failed to create sampler, call SDL_GetError() for more information");
     }
     }
 
 
     ImGui_ImplSDLGPU3_CreateGraphicsPipeline();
     ImGui_ImplSDLGPU3_CreateGraphicsPipeline();
@@ -613,7 +613,7 @@ void ImGui_ImplSDLGPU3_DestroyDeviceObjects()
     if (bd->TexTransferBuffer)  { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; }
     if (bd->TexTransferBuffer)  { SDL_ReleaseGPUTransferBuffer(v->Device, bd->TexTransferBuffer); bd->TexTransferBuffer = nullptr; }
     if (bd->VertexShader)       { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; }
     if (bd->VertexShader)       { SDL_ReleaseGPUShader(v->Device, bd->VertexShader); bd->VertexShader = nullptr; }
     if (bd->FragmentShader)     { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; }
     if (bd->FragmentShader)     { SDL_ReleaseGPUShader(v->Device, bd->FragmentShader); bd->FragmentShader = nullptr; }
-    if (bd->TexSampler)         { SDL_ReleaseGPUSampler(v->Device, bd->TexSampler); bd->TexSampler = nullptr; }
+    if (bd->TexSamplerLinear)   { SDL_ReleaseGPUSampler(v->Device, bd->TexSamplerLinear); bd->TexSamplerLinear = nullptr; }
     if (bd->Pipeline)           { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; }
     if (bd->Pipeline)           { SDL_ReleaseGPUGraphicsPipeline(v->Device, bd->Pipeline); bd->Pipeline = nullptr; }
 }
 }
 
 
@@ -663,7 +663,7 @@ void ImGui_ImplSDLGPU3_NewFrame()
     ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
     ImGui_ImplSDLGPU3_Data* bd = ImGui_ImplSDLGPU3_GetBackendData();
     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?");
     IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDLGPU3_Init()?");
 
 
-    if (!bd->TexSampler)
+    if (!bd->TexSamplerLinear)
         ImGui_ImplSDLGPU3_CreateDeviceObjects();
         ImGui_ImplSDLGPU3_CreateDeviceObjects();
 }
 }
 
 

+ 5 - 5
backends/imgui_impl_vulkan.cpp

@@ -283,7 +283,7 @@ struct ImGui_ImplVulkan_Data
     ImVector<VkFormat>          PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array
     ImVector<VkFormat>          PipelineRenderingCreateInfoColorAttachmentFormats; // Deep copy of format array
 
 
     // Texture management
     // Texture management
-    VkSampler                   TexSampler;
+    VkSampler                   TexSamplerLinear;
     VkCommandPool               TexCommandPool;
     VkCommandPool               TexCommandPool;
     VkCommandBuffer             TexCommandBuffer;
     VkCommandBuffer             TexCommandBuffer;
 
 
@@ -766,7 +766,7 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex)
         }
         }
 
 
         // Create the Descriptor Set
         // Create the Descriptor Set
-        backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSampler, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+        backend_tex->DescriptorSet = ImGui_ImplVulkan_AddTexture(bd->TexSamplerLinear, backend_tex->ImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
 
 
         // Store identifiers
         // Store identifiers
         tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
         tex->SetTexID((ImTextureID)backend_tex->DescriptorSet);
@@ -1066,7 +1066,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
     ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
     VkResult err;
     VkResult err;
 
 
-    if (!bd->TexSampler)
+    if (!bd->TexSamplerLinear)
     {
     {
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         // Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling.
         VkSamplerCreateInfo info = {};
         VkSamplerCreateInfo info = {};
@@ -1080,7 +1080,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
         info.minLod = -1000;
         info.minLod = -1000;
         info.maxLod = 1000;
         info.maxLod = 1000;
         info.maxAnisotropy = 1.0f;
         info.maxAnisotropy = 1.0f;
-        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSampler);
+        err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->TexSamplerLinear);
         check_vk_result(err);
         check_vk_result(err);
     }
     }
 
 
@@ -1217,7 +1217,7 @@ void    ImGui_ImplVulkan_DestroyDeviceObjects()
 
 
     if (bd->TexCommandBuffer)     { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
     if (bd->TexCommandBuffer)     { vkFreeCommandBuffers(v->Device, bd->TexCommandPool, 1, &bd->TexCommandBuffer); bd->TexCommandBuffer = VK_NULL_HANDLE; }
     if (bd->TexCommandPool)       { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
     if (bd->TexCommandPool)       { vkDestroyCommandPool(v->Device, bd->TexCommandPool, v->Allocator); bd->TexCommandPool = VK_NULL_HANDLE; }
-    if (bd->TexSampler)           { vkDestroySampler(v->Device, bd->TexSampler, v->Allocator); bd->TexSampler = VK_NULL_HANDLE; }
+    if (bd->TexSamplerLinear)     { vkDestroySampler(v->Device, bd->TexSamplerLinear, v->Allocator); bd->TexSamplerLinear = VK_NULL_HANDLE; }
     if (bd->ShaderModuleVert)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
     if (bd->ShaderModuleVert)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
     if (bd->ShaderModuleFrag)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
     if (bd->ShaderModuleFrag)     { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
     if (bd->DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
     if (bd->DescriptorSetLayout)  { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }

+ 10 - 0
docs/CHANGELOG.txt

@@ -69,14 +69,24 @@ Other Changes:
 - InputText: revert a change in 1.79 where pressing Down or PageDown on the last line
 - InputText: revert a change in 1.79 where pressing Down or PageDown on the last line
   of a multi-line buffer without a trailing carriage return would keep the cursor
   of a multi-line buffer without a trailing carriage return would keep the cursor
   unmoved. We revert back to move to the end of line in this situation.
   unmoved. We revert back to move to the end of line in this situation.
+- Focus, InputText: fixed an issue where SetKeyboardFocusHere() did not work
+  on InputTextMultiline() fields with ImGuiInputTextFlags_AllowTabInput, since
+  they normally inhibit activation to allow tabbing through multiple items. (#8928)
+- Selectable: added ImGuiSelectableFlags_SelectOnNav to auto-select an item when
+  moved into (automatic when in a BeginMultiSelect() block).
+- TabBar: fixed an issue were forcefully selecting a tab using internal API would
+  be ignored on first/appearing frame before tabs are submitted (#8929, #6681)
 - DrawList: fixed CloneOutput() unnecessarily taking a copy of the ImDrawListSharedData
 - DrawList: fixed CloneOutput() unnecessarily taking a copy of the ImDrawListSharedData
   pointer, which could to issue when deleting the cloned list. (#8894, #1860)
   pointer, which could to issue when deleting the cloned list. (#8894, #1860)
+- DrawList: made AddCallback() assert when passing a null callback.
 - Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers
 - Debug Tools: ID Stack Tool: fixed using fixed-size buffers preventing long identifiers
   from being displayed in the tool. (#8905, #4631)
   from being displayed in the tool. (#8905, #4631)
 - Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ###
 - Debug Tools: ID Stack Tool: when ### is used, uncontributing prefix before the ###
   is now skipped. (#8904, #4631)
   is now skipped. (#8904, #4631)
 - Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in
 - Debug Tools: ID Stack Tool: added option to hex-encode non-ASCII characters in
   output path. (#8904, #4631)
   output path. (#8904, #4631)
+- Demo: tweaked ShowFontSelector() and ShowStyleSelector() to update selection
+  while navigating and to not close popup automatically.
 - Examples: Android: Android+OpenGL3: update Gradle project (#8888, #8878) [@scribam]
 - Examples: Android: Android+OpenGL3: update Gradle project (#8888, #8878) [@scribam]
 - Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and
 - Backends: SDL_GPU: Added ImGui_ImplSDLGPU3_InitInfo::SwapchainComposition and
   PresentMode to configure how secondary viewports are created. Currently only used
   PresentMode to configure how secondary viewports are created. Currently only used

+ 4 - 1
imgui.cpp

@@ -14638,6 +14638,8 @@ void ImGui::NavMoveRequestApplyResult()
     {
     {
         g.NavNextActivateId = result->ID;
         g.NavNextActivateId = result->ID;
         g.NavNextActivateFlags = ImGuiActivateFlags_None;
         g.NavNextActivateFlags = ImGuiActivateFlags_None;
+        if (g.NavMoveFlags & ImGuiNavMoveFlags_FocusApi)
+            g.NavNextActivateFlags |= ImGuiActivateFlags_FromFocusApi;
         if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
         if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing)
             g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
             g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing;
     }
     }
@@ -21403,6 +21405,7 @@ static void Platform_SetImeDataFn_DefaultImpl(ImGuiContext*, ImGuiViewport*, ImG
 // - DebugNodeWindowSettings() [Internal]
 // - DebugNodeWindowSettings() [Internal]
 // - DebugNodeWindowsList() [Internal]
 // - DebugNodeWindowsList() [Internal]
 // - DebugNodeWindowsListByBeginStackParent() [Internal]
 // - DebugNodeWindowsListByBeginStackParent() [Internal]
+// - ShowFontSelector()
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS)
 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS)
@@ -23749,7 +23752,7 @@ void ImGui::ShowFontSelector(const char* label)
         for (ImFont* font : io.Fonts->Fonts)
         for (ImFont* font : io.Fonts->Fonts)
         {
         {
             PushID((void*)font);
             PushID((void*)font);
-            if (Selectable(font->GetDebugName(), font == font_current))
+            if (Selectable(font->GetDebugName(), font == font_current, ImGuiSelectableFlags_SelectOnNav | ImGuiSelectableFlags_NoAutoClosePopups))
                 io.FontDefault = font;
                 io.FontDefault = font;
             if (font == font_current)
             if (font == font_current)
                 SetItemDefaultFocus();
                 SetItemDefaultFocus();

+ 2 - 1
imgui.h

@@ -29,7 +29,7 @@
 // Library Version
 // Library Version
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
 #define IMGUI_VERSION       "1.92.3 WIP"
 #define IMGUI_VERSION       "1.92.3 WIP"
-#define IMGUI_VERSION_NUM   19226
+#define IMGUI_VERSION_NUM   19227
 #define IMGUI_HAS_TABLE             // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
 #define IMGUI_HAS_TABLE             // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
 #define IMGUI_HAS_TEXTURES          // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
 #define IMGUI_HAS_TEXTURES          // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
 #define IMGUI_HAS_VIEWPORT          // In 'docking' WIP branch.
 #define IMGUI_HAS_VIEWPORT          // In 'docking' WIP branch.
@@ -1380,6 +1380,7 @@ enum ImGuiSelectableFlags_
     ImGuiSelectableFlags_Disabled           = 1 << 3,   // Cannot be selected, display grayed out text
     ImGuiSelectableFlags_Disabled           = 1 << 3,   // Cannot be selected, display grayed out text
     ImGuiSelectableFlags_AllowOverlap       = 1 << 4,   // (WIP) Hit testing to allow subsequent widgets to overlap this one
     ImGuiSelectableFlags_AllowOverlap       = 1 << 4,   // (WIP) Hit testing to allow subsequent widgets to overlap this one
     ImGuiSelectableFlags_Highlight          = 1 << 5,   // Make the item be displayed as if it is hovered
     ImGuiSelectableFlags_Highlight          = 1 << 5,   // Make the item be displayed as if it is hovered
+    ImGuiSelectableFlags_SelectOnNav        = 1 << 6,   // Auto-select when moved into. Automatic when in a BeginMultiSelect() block.
 
 
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
 #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     ImGuiSelectableFlags_DontClosePopups    = ImGuiSelectableFlags_NoAutoClosePopups,   // Renamed in 1.91.0
     ImGuiSelectableFlags_DontClosePopups    = ImGuiSelectableFlags_NoAutoClosePopups,   // Renamed in 1.91.0

+ 18 - 11
imgui_demo.cpp

@@ -8333,17 +8333,25 @@ void ImGui::ShowAboutWindow(bool* p_open)
 bool ImGui::ShowStyleSelector(const char* label)
 bool ImGui::ShowStyleSelector(const char* label)
 {
 {
     static int style_idx = -1;
     static int style_idx = -1;
-    if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
+    const char* style_names[] = { "Dark", "Light", "Classic" };
+    bool ret = false;
+    if (ImGui::BeginCombo(label, (style_idx >= 0 && style_idx < IM_ARRAYSIZE(style_names)) ? style_names[style_idx] : ""))
     {
     {
-        switch (style_idx)
-        {
-        case 0: ImGui::StyleColorsDark(); break;
-        case 1: ImGui::StyleColorsLight(); break;
-        case 2: ImGui::StyleColorsClassic(); break;
-        }
-        return true;
+        for (int n = 0; n < IM_ARRAYSIZE(style_names); n++)
+            if (ImGui::Selectable(style_names[n], style_idx == n, ImGuiSelectableFlags_SelectOnNav | ImGuiSelectableFlags_NoAutoClosePopups))
+            {
+                style_idx = n;
+                ret = true;
+                switch (style_idx)
+                {
+                case 0: ImGui::StyleColorsDark(); break;
+                case 1: ImGui::StyleColorsLight(); break;
+                case 2: ImGui::StyleColorsClassic(); break;
+                }
+            }
+        ImGui::EndCombo();
     }
     }
-    return false;
+    return ret;
 }
 }
 
 
 static const char* GetTreeLinesFlagsName(ImGuiTreeNodeFlags flags)
 static const char* GetTreeLinesFlagsName(ImGuiTreeNodeFlags flags)
@@ -9395,10 +9403,9 @@ static void ShowExampleAppLayout(bool* p_open)
             ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX);
             ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX);
             for (int i = 0; i < 100; i++)
             for (int i = 0; i < 100; i++)
             {
             {
-                // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
                 char label[128];
                 char label[128];
                 sprintf(label, "MyObject %d", i);
                 sprintf(label, "MyObject %d", i);
-                if (ImGui::Selectable(label, selected == i))
+                if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SelectOnNav))
                     selected = i;
                     selected = i;
             }
             }
             ImGui::EndChild();
             ImGui::EndChild();

+ 1 - 0
imgui_draw.cpp

@@ -524,6 +524,7 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t use
 {
 {
     IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
     IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
     ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
     ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
+    IM_ASSERT(callback != NULL);
     IM_ASSERT(curr_cmd->UserCallback == NULL);
     IM_ASSERT(curr_cmd->UserCallback == NULL);
     if (curr_cmd->ElemCount != 0)
     if (curr_cmd->ElemCount != 0)
     {
     {

+ 4 - 2
imgui_internal.h

@@ -1086,7 +1086,6 @@ enum ImGuiSelectableFlagsPrivate_
 {
 {
     // NB: need to be in sync with last value of ImGuiSelectableFlags_
     // NB: need to be in sync with last value of ImGuiSelectableFlags_
     ImGuiSelectableFlags_NoHoldingActiveID      = 1 << 20,
     ImGuiSelectableFlags_NoHoldingActiveID      = 1 << 20,
-    ImGuiSelectableFlags_SelectOnNav            = 1 << 21,  // (WIP) Auto-select when moved into. This is not exposed in public API as to handle multi-select and modifiers we will need user to explicitly control focus scope. May be replaced with a BeginSelection() API.
     ImGuiSelectableFlags_SelectOnClick          = 1 << 22,  // Override button behavior to react on Click (default is Click+Release)
     ImGuiSelectableFlags_SelectOnClick          = 1 << 22,  // Override button behavior to react on Click (default is Click+Release)
     ImGuiSelectableFlags_SelectOnRelease        = 1 << 23,  // Override button behavior to react on Release (default is Click+Release)
     ImGuiSelectableFlags_SelectOnRelease        = 1 << 23,  // Override button behavior to react on Release (default is Click+Release)
     ImGuiSelectableFlags_SpanAvailWidth         = 1 << 24,  // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)
     ImGuiSelectableFlags_SpanAvailWidth         = 1 << 24,  // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus)
@@ -1702,8 +1701,9 @@ enum ImGuiActivateFlags_
     ImGuiActivateFlags_PreferInput          = 1 << 0,       // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key.
     ImGuiActivateFlags_PreferInput          = 1 << 0,       // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key.
     ImGuiActivateFlags_PreferTweak          = 1 << 1,       // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used.
     ImGuiActivateFlags_PreferTweak          = 1 << 1,       // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used.
     ImGuiActivateFlags_TryToPreserveState   = 1 << 2,       // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
     ImGuiActivateFlags_TryToPreserveState   = 1 << 2,       // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
-    ImGuiActivateFlags_FromTabbing          = 1 << 3,       // Activation requested by a tabbing request
+    ImGuiActivateFlags_FromTabbing          = 1 << 3,       // Activation requested by a tabbing request (ImGuiNavMoveFlags_IsTabbing)
     ImGuiActivateFlags_FromShortcut         = 1 << 4,       // Activation requested by an item shortcut via SetNextItemShortcut() function.
     ImGuiActivateFlags_FromShortcut         = 1 << 4,       // Activation requested by an item shortcut via SetNextItemShortcut() function.
+    ImGuiActivateFlags_FromFocusApi         = 1 << 5,       // Activation requested by an api request (ImGuiNavMoveFlags_FocusApi)
 };
 };
 
 
 // Early work-in-progress API for ScrollToItem()
 // Early work-in-progress API for ScrollToItem()
@@ -3815,6 +3815,8 @@ namespace ImGui
 
 
     // Tab Bars
     // Tab Bars
     inline    ImGuiTabBar*  GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
     inline    ImGuiTabBar*  GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
+    IMGUI_API ImGuiTabBar*  TabBarFindByID(ImGuiID id);
+    IMGUI_API void          TabBarRemove(ImGuiTabBar* tab_bar);
     IMGUI_API bool          BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
     IMGUI_API bool          BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
     IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order);
     IMGUI_API ImGuiTabItem* TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order);

+ 1 - 1
imgui_tables.cpp

@@ -3943,7 +3943,7 @@ void ImGui::TableSettingsAddSettingsHandler()
 // - TableGcCompactSettings() [Internal]
 // - TableGcCompactSettings() [Internal]
 //-------------------------------------------------------------------------
 //-------------------------------------------------------------------------
 
 
-// Remove Table (currently only used by TestEngine)
+// Remove Table data (currently only used by TestEngine)
 void ImGui::TableRemove(ImGuiTable* table)
 void ImGui::TableRemove(ImGuiTable* table)
 {
 {
     //IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID);
     //IMGUI_DEBUG_PRINT("TableRemove() id=0x%08X\n", table->ID);

+ 23 - 7
imgui_widgets.cpp

@@ -3998,7 +3998,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
 namespace ImStb
 namespace ImStb
 {
 {
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->TextLen; }
 static int     STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj)                             { return obj->TextLen; }
-static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx <= obj->TextLen); return obj->TextSrc[idx]; }
+static char    STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx)                      { IM_ASSERT(idx >= 0 && idx <= obj->TextLen); return obj->TextSrc[idx]; }
 static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontBakedScale; }
 static float   STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx)  { unsigned int c; ImTextCharFromUtf8(&c, obj->TextSrc + line_start_idx + char_idx, obj->TextSrc + obj->TextLen); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.FontBaked->GetCharAdvance((ImWchar)c) * g.FontBakedScale; }
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static char    STB_TEXTEDIT_NEWLINE = '\n';
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
 static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
@@ -4613,8 +4613,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         item_data_backup = g.LastItemData;
         item_data_backup = g.LastItemData;
         window->DC.CursorPos = backup_pos;
         window->DC.CursorPos = backup_pos;
 
 
-        // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping.
-        if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput))
+        // Prevent NavActivation from explicit Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping.
+        if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && !(g.NavActivateFlags & ImGuiActivateFlags_FromFocusApi) && (flags & ImGuiInputTextFlags_AllowTabInput))
             g.NavActivateId = 0;
             g.NavActivateId = 0;
 
 
         // Prevent NavActivate reactivating in BeginChild() when we are already active.
         // Prevent NavActivate reactivating in BeginChild() when we are already active.
@@ -7354,6 +7354,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
 
 
     bool hovered, held;
     bool hovered, held;
     bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
     bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
+    bool auto_selected = false;
 
 
     // Multi-selection support (footer)
     // Multi-selection support (footer)
     if (is_multi_select)
     if (is_multi_select)
@@ -7371,7 +7372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         //   The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
         //   The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
         if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId)
         if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId)
             if (g.NavJustMovedToId == id)
             if (g.NavJustMovedToId == id)
-                selected = pressed = true;
+                selected = pressed = auto_selected = true;
     }
     }
 
 
     // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with keyboard/gamepad
     // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with keyboard/gamepad
@@ -7422,8 +7423,9 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
         RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb);
         RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb);
 
 
     // Automatically close popups
     // Automatically close popups
-    if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
-        CloseCurrentPopup();
+    if (pressed && !auto_selected && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
+        if (!(flags & ImGuiSelectableFlags_SelectOnNav) || g.NavJustMovedToId != id)
+            CloseCurrentPopup();
 
 
     if (disabled_item && !disabled_global)
     if (disabled_item && !disabled_global)
         EndDisabled();
         EndDisabled();
@@ -9568,6 +9570,19 @@ static ImGuiPtrOrIndex GetTabBarRefFromTabBar(ImGuiTabBar* tab_bar)
     return ImGuiPtrOrIndex(tab_bar);
     return ImGuiPtrOrIndex(tab_bar);
 }
 }
 
 
+ImGuiTabBar* ImGui::TabBarFindByID(ImGuiID id)
+{
+    ImGuiContext& g = *GImGui;
+    return g.TabBars.GetByKey(id);
+}
+
+// Remove TabBar data (currently only used by TestEngine)
+void    ImGui::TabBarRemove(ImGuiTabBar* tab_bar)
+{
+    ImGuiContext& g = *GImGui;
+    g.TabBars.Remove(tab_bar->ID, tab_bar);
+}
+
 bool    ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
 bool    ImGui::BeginTabBar(const char* str_id, ImGuiTabBarFlags flags)
 {
 {
     ImGuiContext& g = *GImGui;
     ImGuiContext& g = *GImGui;
@@ -9907,7 +9922,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
     tab_bar->TabsNames.Buf.resize(0);
     tab_bar->TabsNames.Buf.resize(0);
 
 
     // If we have lost the selected tab, select the next most recently active one
     // If we have lost the selected tab, select the next most recently active one
-    if (found_selected_tab_id == false)
+    const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
+    if (found_selected_tab_id == false && !tab_bar_appearing)
         tab_bar->SelectedTabId = 0;
         tab_bar->SelectedTabId = 0;
     if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
     if (tab_bar->SelectedTabId == 0 && tab_bar->NextSelectedTabId == 0 && most_recently_selected_tab != NULL)
         scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;
         scroll_to_tab_id = tab_bar->SelectedTabId = most_recently_selected_tab->ID;

+ 1 - 1
imstb_textedit.h

@@ -582,7 +582,7 @@ static void stb_textedit_find_charpos(StbFindState *find, IMSTB_TEXTEDIT_STRING
       STB_TEXTEDIT_LAYOUTROW(&r, str, i);
       STB_TEXTEDIT_LAYOUTROW(&r, str, i);
       if (n < i + r.num_chars)
       if (n < i + r.num_chars)
          break;
          break;
-      if (str->LastMoveDirectionLR == ImGuiDir_Right && str->Stb->cursor == i + r.num_chars && STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] Wrapping point handling
+      if (str->LastMoveDirectionLR == ImGuiDir_Right && str->Stb->cursor > 0 && str->Stb->cursor == i + r.num_chars && STB_TEXTEDIT_GETCHAR(str, i + r.num_chars - 1) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI] Wrapping point handling
          break;
          break;
       if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE)  // [DEAR IMGUI] special handling for last line
       if (i + r.num_chars == z && z > 0 && STB_TEXTEDIT_GETCHAR(str, z - 1) != STB_TEXTEDIT_NEWLINE)  // [DEAR IMGUI] special handling for last line
          break;   // [DEAR IMGUI]
          break;   // [DEAR IMGUI]