Merge branch 'master' into docking

+ fix warning fix for mingw+dx9
# Conflicts:
#	backends/imgui_impl_dx9.cpp
#	imgui.cpp
This commit is contained in:
ocornut 2021-04-30 22:48:16 +02:00
commit 31290807dc
14 changed files with 302 additions and 187 deletions

View File

@ -254,10 +254,11 @@ jobs:
EOF EOF
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
- name: Build example_null (with large ImDrawIdx) - name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
run: | run: |
cat > example_single_file.cpp <<'EOF' cat > example_single_file.cpp <<'EOF'
#define ImTextureID void*
#define ImDrawIdx unsigned int #define ImDrawIdx unsigned int
#define IMGUI_IMPLEMENTATION #define IMGUI_IMPLEMENTATION
#include "misc/single_file/imgui_single_file.h" #include "misc/single_file/imgui_single_file.h"

View File

@ -299,6 +299,7 @@ static void ImGui_ImplDX10_CreateFontsTexture()
subResource.SysMemPitch = desc.Width * 4; subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0; subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != NULL);
// Create texture view // Create texture view
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc; D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;

View File

@ -311,6 +311,7 @@ static void ImGui_ImplDX11_CreateFontsTexture()
subResource.SysMemPitch = desc.Width * 4; subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0; subResource.SysMemSlicePitch = 0;
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != NULL);
// Create texture view // Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;

View File

@ -13,6 +13,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2021-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857). // 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file. // 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer. // 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
@ -74,11 +75,13 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient) // Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
g_pd3dDevice->SetPixelShader(NULL); g_pd3dDevice->SetPixelShader(NULL);
g_pd3dDevice->SetVertexShader(NULL); g_pd3dDevice->SetVertexShader(NULL);
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
@ -86,8 +89,12 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE); g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE); g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
@ -437,7 +444,7 @@ static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*) static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
{ {
ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData; ImGuiViewportDataDx9* data = (ImGuiViewportDataDx9*)viewport->RendererUserData;
HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, NULL); HRESULT hr = data->SwapChain->Present(NULL, NULL, data->d3dpp.hDeviceWindow, NULL, 0);
// Let main application handle D3DERR_DEVICELOST by resetting the device. // Let main application handle D3DERR_DEVICELOST by resetting the device.
IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST); IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST);
} }

View File

@ -26,7 +26,7 @@
// Using XInput for gamepad (will load DLL dynamically) // Using XInput for gamepad (will load DLL dynamically)
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
#include <XInput.h> #include <xinput.h>
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*); typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*); typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
#endif #endif
@ -340,7 +340,7 @@ static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, H
static void ImGui_ImplWin32_UpdateMonitors() static void ImGui_ImplWin32_UpdateMonitors()
{ {
ImGui::GetPlatformIO().Monitors.resize(0); ImGui::GetPlatformIO().Monitors.resize(0);
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL); ::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, 0);
g_WantUpdateMonitors = false; g_WantUpdateMonitors = false;
} }

View File

@ -111,6 +111,11 @@ Other Changes:
- Scrolling: Fix scroll snapping on edge of scroll region when both scrollbars are enabled. - Scrolling: Fix scroll snapping on edge of scroll region when both scrollbars are enabled.
- Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010) - Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010)
- Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061) - Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061)
- Nav: Fixed toggling menu layer while an InputText() is active not stealing active id. (#787)
- Nav: Fixed pressing Escape to leave menu layer while in a popup or child window. (#787)
- Nav, InputText: Fixed accidental menu toggling while typing non-ascii characters using AltGR. [@rokups] (#370)
- Nav: Fixed using SetItemDefaultFocus() on windows with _NavFlattened flag. (#787)
- Nav: Fixed Tabbing initial activation from skipping the first item if it is tabbable through. (#787)
- Tables: Expose TableSetColumnEnabled() in public api. (#3935) - Tables: Expose TableSetColumnEnabled() in public api. (#3935)
- Tables: Better preserve widths when columns count changes. (#4046) - Tables: Better preserve widths when columns count changes. (#4046)
- TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single - TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single
@ -120,6 +125,7 @@ Other Changes:
- DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler] - DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler]
- ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack] - ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack]
- InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks] - InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks]
- InputText: Align caret/cursor to pixel coordinates. (#4080) [@elvissteinjr]
- LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004) - LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004)
- LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004) - LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004)
- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash]
@ -135,6 +141,8 @@ Other Changes:
- Backends: OSX: Fix keys remaining stuck when CMD-tabbing to a different application. (#3832) [@rokups] - Backends: OSX: Fix keys remaining stuck when CMD-tabbing to a different application. (#3832) [@rokups]
- Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to - Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to
workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857) workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857)
- Backends: DirectX9: explicitly setting up more graphics states to increase compatibility with unusual
non-default states. (#4063)
- Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when - Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when
entering the rendering function. (#4045) [@Nemirtingas] entering the rendering function. (#4045) [@Nemirtingas]
- Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of - Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of

View File

@ -380,7 +380,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied - nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied
- focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622)
- focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame)
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787, #343)
- viewport: make it possible to have no main/hosting viewport - viewport: make it possible to have no main/hosting viewport
- viewport: We set ImGuiViewportFlags_NoFocusOnAppearing in a way that is required for GLFW/SDL binding, but could be handled better without - viewport: We set ImGuiViewportFlags_NoFocusOnAppearing in a way that is required for GLFW/SDL binding, but could be handled better without

187
imgui.cpp
View File

@ -826,6 +826,9 @@ CODE
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
#endif #endif
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -910,8 +913,8 @@ static void NavUpdateInitResult();
static float NavUpdatePageUpPageDown(); static float NavUpdatePageUpPageDown();
static inline void NavUpdateAnyRequestFlag(); static inline void NavUpdateAnyRequestFlag();
static void NavEndFrame(); static void NavEndFrame();
static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand); static bool NavScoreItem(ImGuiNavItemData* result, ImRect cand);
static void NavApplyItemToResult(ImGuiNavMoveResult* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel); static void NavApplyItemToResult(ImGuiNavItemData* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel);
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, ImGuiID id);
static ImVec2 NavCalcPreferredRefPos(); static ImVec2 NavCalcPreferredRefPos();
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window); static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
@ -3223,7 +3226,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
return false; return false;
// Test if the item is disabled // Test if the item is disabled
if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled)) if ((g.CurrentItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
return false; return false;
// Special handling for calling after Begin() which represent the title bar or tab. // Special handling for calling after Begin() which represent the title bar or tab.
@ -3249,7 +3252,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
return false; return false;
if (g.NavDisableMouseHover) if (g.NavDisableMouseHover)
return false; return false;
if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (window->DC.ItemFlags & ImGuiItemFlags_Disabled)) if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled))
{ {
g.HoveredIdDisabled = true; g.HoveredIdDisabled = true;
return false; return false;
@ -3296,15 +3299,21 @@ void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatu
} }
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out. // Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id) void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0 && id == window->DC.LastItemId);
// Increment counters // Increment counters
const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0; // FIXME: ImGuiItemFlags_Disabled should disable more.
const bool is_tab_stop = (g.CurrentItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->DC.FocusCounterRegular++; window->DC.FocusCounterRegular++;
if (is_tab_stop) if (is_tab_stop)
{
window->DC.FocusCounterTabStop++; window->DC.FocusCounterTabStop++;
if (g.NavId == id)
g.NavIdTabCounter = window->DC.FocusCounterTabStop;
}
// Process TAB/Shift-TAB to tab *OUT* of the currently focused item. // Process TAB/Shift-TAB to tab *OUT* of the currently focused item.
// (Note that we can always TAB out of a widget that doesn't allow tabbing in) // (Note that we can always TAB out of a widget that doesn't allow tabbing in)
@ -3318,25 +3327,21 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
if (g.TabFocusRequestCurrWindow == window) if (g.TabFocusRequestCurrWindow == window)
{ {
if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular) if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
return true; {
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByCode;
return;
}
if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop) if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{ {
g.NavJustTabbedId = id; g.NavJustTabbedId = id;
return true; window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing;
return;
} }
// If another item is about to be focused, we clear our own active id // If another item is about to be focused, we clear our own active id
if (g.ActiveId == id) if (g.ActiveId == id)
ClearActiveID(); ClearActiveID();
} }
return false;
}
void ImGui::FocusableItemUnregister(ImGuiWindow* window)
{
window->DC.FocusCounterRegular--;
window->DC.FocusCounterTabStop--;
} }
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
@ -3909,12 +3914,14 @@ void ImGui::UpdateTabFocus()
g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)); g.TabFocusPressed = (g.NavWindow && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab));
if (g.ActiveId == 0 && g.TabFocusPressed) if (g.ActiveId == 0 && g.TabFocusPressed)
{ {
// Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also // - This path is only taken when no widget are active/tabbed-into yet.
// manipulate the Next fields even, even though they will be turned into Curr fields by the code below. // Subsequent tabbing will be processed by FocusableItemRegister()
// - Note that SetKeyboardFocusHere() sets the Next fields mid-frame. To be consistent we also
// manipulate the Next fields here even though they will be turned into Curr fields below.
g.TabFocusRequestNextWindow = g.NavWindow; g.TabFocusRequestNextWindow = g.NavWindow;
g.TabFocusRequestNextCounterRegular = INT_MAX; g.TabFocusRequestNextCounterRegular = INT_MAX;
if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX)
g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); g.TabFocusRequestNextCounterTabStop = g.NavIdTabCounter + (g.IO.KeyShift ? -1 : 0);
else else
g.TabFocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0; g.TabFocusRequestNextCounterTabStop = g.IO.KeyShift ? -1 : 0;
} }
@ -4201,7 +4208,7 @@ void ImGui::NewFrame()
g.CurrentWindowStack.resize(0); g.CurrentWindowStack.resize(0);
g.BeginPopupStack.resize(0); g.BeginPopupStack.resize(0);
g.ItemFlagsStack.resize(0); g.ItemFlagsStack.resize(0);
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_); g.ItemFlagsStack.push_back(ImGuiItemFlags_None);
g.GroupStack.resize(0); g.GroupStack.resize(0);
ClosePopupsOverWindow(g.NavWindow, false); ClosePopupsOverWindow(g.NavWindow, false);
@ -4710,6 +4717,7 @@ void ImGui::Render()
for (int n = 0; n != g.Windows.Size; n++) for (int n = 0; n != g.Windows.Size; n++)
{ {
ImGuiWindow* window = g.Windows[n]; ImGuiWindow* window = g.Windows[n];
IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1]) if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_top_most[0] && window != windows_to_render_top_most[1])
AddRootWindowToDrawData(window); AddRootWindowToDrawData(window);
} }
@ -4801,6 +4809,7 @@ static void FindHoveredWindow()
for (int i = g.Windows.Size - 1; i >= 0; i--) for (int i = g.Windows.Size - 1; i >= 0; i--)
{ {
ImGuiWindow* window = g.Windows[i]; ImGuiWindow* window = g.Windows[i];
IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
if (!window->Active || window->Hidden) if (!window->Active || window->Hidden)
continue; continue;
if (window->Flags & ImGuiWindowFlags_NoMouseInputs) if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
@ -4830,6 +4839,7 @@ static void FindHoveredWindow()
if (hovered_window == NULL) if (hovered_window == NULL)
hovered_window = window; hovered_window = window;
IM_MSVC_WARNING_SUPPRESS(28182); // [Static Analyzer] Dereferencing NULL pointer.
if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree)) if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindowDockTree != g.MovingWindow->RootWindowDockTree))
hovered_window_ignoring_moving_window = window; hovered_window_ignoring_moving_window = window;
if (hovered_window && hovered_window_ignoring_moving_window) if (hovered_window && hovered_window_ignoring_moving_window)
@ -5254,7 +5264,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
parent_window->DC.CursorPos = child_window->Pos; parent_window->DC.CursorPos = child_window->Pos;
// Process navigation-in immediately so NavInit can run on first frame // Process navigation-in immediately so NavInit can run on first frame
if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll)) if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayersActiveMask != 0 || child_window->DC.NavHasScroll))
{ {
FocusWindow(child_window); FocusWindow(child_window);
NavInitWindow(child_window, false); NavInitWindow(child_window, false);
@ -5301,13 +5311,13 @@ void ImGui::EndChild()
ImGuiWindow* parent_window = g.CurrentWindow; ImGuiWindow* parent_window = g.CurrentWindow;
ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz);
ItemSize(sz); ItemSize(sz);
if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) if ((window->DC.NavLayersActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
{ {
ItemAdd(bb, window->ChildId); ItemAdd(bb, window->ChildId);
RenderNavHighlight(bb, window->ChildId); RenderNavHighlight(bb, window->ChildId);
// When browsing a window that has no activable items (scroll only) we keep a highlight on the child // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow) if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow)
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
} }
else else
@ -5952,8 +5962,8 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None); const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse) && (style.WindowMenuButtonPosition != ImGuiDir_None);
// Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer) // Close & Collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
window->DC.NavLayerCurrent = ImGuiNavLayer_Menu; window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
// Layout buttons // Layout buttons
@ -5990,7 +6000,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
*p_open = false; *p_open = false;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.ItemFlags = item_flags_backup; g.CurrentItemFlags = item_flags_backup;
// Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker) // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
// FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code.. // FIXME: Refactor text alignment facilities along with RenderText helpers, this is WAY too much messy code..
@ -6743,8 +6753,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
window->DC.NavLayerCurrent = ImGuiNavLayer_Main; window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayersActiveMask = window->DC.NavLayersActiveMaskNext;
window->DC.NavLayerActiveMaskNext = 0x00; window->DC.NavLayersActiveMaskNext = 0x00;
window->DC.NavHideHighlightOneFrame = false; window->DC.NavHideHighlightOneFrame = false;
window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f); window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
@ -6840,7 +6850,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
// Pull/inherit current state // Pull/inherit current state
window->DC.ItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack g.CurrentItemFlags = g.ItemFlagsStack.back(); // Inherit from shared stack
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595 window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : 0; // Inherit from parent only // -V595
if (!(flags & ImGuiWindowFlags_DockNodeHost)) if (!(flags & ImGuiWindowFlags_DockNodeHost))
@ -7115,24 +7125,22 @@ void ImGui::PopFont()
void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiItemFlags item_flags = g.CurrentItemFlags;
ImGuiItemFlags item_flags = window->DC.ItemFlags;
IM_ASSERT(item_flags == g.ItemFlagsStack.back()); IM_ASSERT(item_flags == g.ItemFlagsStack.back());
if (enabled) if (enabled)
item_flags |= option; item_flags |= option;
else else
item_flags &= ~option; item_flags &= ~option;
window->DC.ItemFlags = item_flags; g.CurrentItemFlags = item_flags;
g.ItemFlagsStack.push_back(item_flags); g.ItemFlagsStack.push_back(item_flags);
} }
void ImGui::PopItemFlag() void ImGui::PopItemFlag()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack. IM_ASSERT(g.ItemFlagsStack.Size > 1); // Too many calls to PopItemFlag() - we always leave a 0 at the bottom of the stack.
g.ItemFlagsStack.pop_back(); g.ItemFlagsStack.pop_back();
window->DC.ItemFlags = g.ItemFlagsStack.back(); g.CurrentItemFlags = g.ItemFlagsStack.back();
} }
// FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system. // FIXME: Look into renaming this once we have settled the new Focus/Activation/TabStop system.
@ -7608,11 +7616,11 @@ void ImGui::SetItemDefaultFocus()
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (!window->Appearing) if (!window->Appearing)
return; return;
if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == window->DC.NavLayerCurrent)
{ {
g.NavInitRequest = false; g.NavInitRequest = false;
g.NavInitResultId = g.NavWindow->DC.LastItemId; g.NavInitResultId = window->DC.LastItemId;
g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); g.NavInitResultRectRel = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
NavUpdateAnyRequestFlag(); NavUpdateAnyRequestFlag();
if (!IsItemVisible()) if (!IsItemVisible())
SetScrollHereY(); SetScrollHereY();
@ -8045,7 +8053,7 @@ void ImGui::ItemSize(const ImRect& bb, float text_baseline_y)
// Declare item bounding box for clipping and interaction. // Declare item bounding box for clipping and interaction.
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction. // declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemAddFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
@ -8061,7 +8069,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick). // to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
// We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null. // We intentionally don't check if g.NavWindow != NULL because g.NavAnyRequest should only be set when it is non null.
// If we crash on a NULL g.NavWindow we need to fix the bug elsewhere. // If we crash on a NULL g.NavWindow we need to fix the bug elsewhere.
window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); window->DC.NavLayersActiveMaskNext |= (1 << window->DC.NavLayerCurrent);
if (g.NavId == id || g.NavAnyRequest) if (g.NavId == id || g.NavAnyRequest)
if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
@ -8094,6 +8102,11 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
return false; return false;
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
// Tab stop handling (previously was using internal ItemFocusable() api)
// FIXME-NAV: We would now want to move this above the clipping test, but this would require being able to scroll and currently this would mean an extra frame. (#4079, #343)
if (flags & ImGuiItemAddFlags_Focusable)
ItemFocusable(window, id);
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
if (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsMouseHoveringRect(bb.Min, bb.Max))
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
@ -9240,13 +9253,13 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked. // FIXME-NAV: The existence of SetNavID vs SetFocusID properly needs to be clarified/reworked.
void ImGui::SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel) void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.NavWindow != NULL); IM_ASSERT(g.NavWindow != NULL);
IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu); IM_ASSERT(nav_layer == ImGuiNavLayer_Main || nav_layer == ImGuiNavLayer_Menu);
g.NavId = id; g.NavId = id;
g.NavLayer = (ImGuiNavLayer)nav_layer; g.NavLayer = nav_layer;
g.NavFocusScopeId = focus_scope_id; g.NavFocusScopeId = focus_scope_id;
g.NavWindow->NavLastIds[nav_layer] = id; g.NavWindow->NavLastIds[nav_layer] = id;
g.NavWindow->NavRectRel[nav_layer] = rect_rel; g.NavWindow->NavRectRel[nav_layer] = rect_rel;
@ -9309,7 +9322,7 @@ static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect
} }
// Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057
static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) static bool ImGui::NavScoreItem(ImGuiNavItemData* result, ImRect cand)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
@ -9440,7 +9453,7 @@ static bool ImGui::NavScoreItem(ImGuiNavMoveResult* result, ImRect cand)
return new_best; return new_best;
} }
static void ImGui::NavApplyItemToResult(ImGuiNavMoveResult* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel) static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result, ImGuiWindow* window, ImGuiID id, const ImRect& nav_bb_rel)
{ {
result->Window = window; result->Window = window;
result->ID = id; result->ID = id;
@ -9455,7 +9468,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
//if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag.
// return; // return;
const ImGuiItemFlags item_flags = window->DC.ItemFlags; const ImGuiItemFlags item_flags = g.CurrentItemFlags;
const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
// Process Init Request // Process Init Request
@ -9478,7 +9491,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
// FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy) // FIXME-NAV: Consider policy for double scoring (scoring from NavScoringRectScreen + scoring from a rect wrapped according to current wrapping policy)
if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav))) if ((g.NavId != id || (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AllowCurrentNavId)) && !(item_flags & (ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNav)))
{ {
ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; ImGuiNavItemData* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
#if IMGUI_DEBUG_NAV_SCORING #if IMGUI_DEBUG_NAV_SCORING
// [DEBUG] Score all items in NavWindow at all times // [DEBUG] Score all items in NavWindow at all times
if (!g.NavMoveRequest) if (!g.NavMoveRequest)
@ -9505,7 +9518,6 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con
g.NavLayer = window->DC.NavLayerCurrent; g.NavLayer = window->DC.NavLayerCurrent;
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
g.NavIdIsAlive = true; g.NavIdIsAlive = true;
g.NavIdTabCounter = window->DC.FocusCounterTabStop;
window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
} }
} }
@ -9601,10 +9613,16 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
// FIXME: ChildWindow test here is wrong for docking // FIXME: ChildWindow test here is wrong for docking
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(window == g.NavWindow); IM_ASSERT(window == g.NavWindow);
if (window->Flags & ImGuiWindowFlags_NoNavInputs)
{
g.NavId = g.NavFocusScopeId = 0;
return;
}
bool init_for_nav = false; bool init_for_nav = false;
if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
if (window == window->RootWindow || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) init_for_nav = true;
init_for_nav = true;
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer); IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
if (init_for_nav) if (init_for_nav)
{ {
@ -9718,8 +9736,16 @@ static void ImGui::NavUpdate()
io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f;
if (io.KeyShift) if (io.KeyShift)
io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f; io.NavInputs[ImGuiNavInput_TweakFast] = 1.0f;
if (io.KeyAlt && !io.KeyCtrl) // AltGR is Alt+Ctrl, also even on keyboards without AltGR we don't want Alt+Ctrl to open menu.
// AltGR is normally Alt+Ctrl but we can't reliably detect it (not all backends/systems/layout emit it as Alt+Ctrl)
// But also even on keyboards without AltGR we don't want Alt+Ctrl to open menu anyway.
if (io.KeyAlt && !io.KeyCtrl)
io.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f; io.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f;
// We automatically cancel toggling nav layer when any text has been typed while holding Alt. (See #370)
if (io.KeyAlt && !io.KeyCtrl && g.NavWindowingToggleLayer && io.InputQueueCharacters.Size > 0)
g.NavWindowingToggleLayer = false;
#undef NAV_MAP_KEY #undef NAV_MAP_KEY
} }
memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration)); memcpy(io.NavInputsDownDurationPrev, io.NavInputsDownDuration, sizeof(io.NavInputsDownDuration));
@ -9785,6 +9811,11 @@ static void ImGui::NavUpdate()
if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel)) if (!IsActiveIdUsingNavInput(ImGuiNavInput_Cancel))
ClearActiveID(); ClearActiveID();
} }
else if (g.NavLayer != ImGuiNavLayer_Main)
{
// Leave the "menu" layer
NavRestoreLayer(ImGuiNavLayer_Main);
}
else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) else if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow)
{ {
// Exit child window // Exit child window
@ -9801,11 +9832,6 @@ static void ImGui::NavUpdate()
if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal))
ClosePopupToLevel(g.OpenPopupStack.Size - 1, true); ClosePopupToLevel(g.OpenPopupStack.Size - 1, true);
} }
else if (g.NavLayer != ImGuiNavLayer_Main)
{
// Leave the "menu" layer
NavRestoreLayer(ImGuiNavLayer_Main);
}
else else
{ {
// Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
@ -9895,7 +9921,7 @@ static void ImGui::NavUpdate()
// *Fallback* manual-scroll with Nav directional keys when window has no navigable item // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
ImGuiWindow* window = g.NavWindow; ImGuiWindow* window = g.NavWindow;
const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. const float scroll_speed = IM_ROUND(window->CalcFontSize() * 100 * io.DeltaTime); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
{ {
if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)
SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); SetScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
@ -9961,6 +9987,7 @@ static void ImGui::NavUpdateInitResult()
return; return;
// Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called)
// FIXME-NAV: On _NavFlattened windows, g.NavWindow will only be updated during subsequent frame. Not a problem currently.
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name); IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: result NavID 0x%08X in Layer %d Window \"%s\"\n", g.NavInitResultId, g.NavLayer, g.NavWindow->Name);
SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel); SetNavID(g.NavInitResultId, g.NavLayer, 0, g.NavInitResultRectRel);
if (g.NavInitRequestFromMove) if (g.NavInitRequestFromMove)
@ -9986,7 +10013,7 @@ static void ImGui::NavUpdateMoveResult()
} }
// Select which result to use // Select which result to use
ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; ImGuiNavItemData* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
// PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page. // PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
@ -10053,7 +10080,7 @@ static float ImGui::NavUpdatePageUpPageDown()
const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End); const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveIdUsingKey(ImGuiKey_End);
if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed
{ {
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll) if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll)
{ {
// Fallback manual-scroll when window has no navigable item // Fallback manual-scroll when window has no navigable item
if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true))
@ -10174,6 +10201,7 @@ static void ImGui::NavEndFrame()
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_UNUSED(g);
int order = window->FocusOrder; int order = window->FocusOrder;
IM_ASSERT(g.WindowsFocusOrder[order] == window); IM_ASSERT(g.WindowsFocusOrder[order] == window);
return order; return order;
@ -10316,8 +10344,9 @@ static void ImGui::NavUpdateWindowing()
if (apply_focus_window->NavLastIds[0] == 0) if (apply_focus_window->NavLastIds[0] == 0)
NavInitWindow(apply_focus_window, false); NavInitWindow(apply_focus_window, false);
// If the window only has a menu layer, select it directly // If the window has ONLY a menu layer (no main layer), select it directly
if (apply_focus_window->DC.NavLayerActiveMask == (1 << ImGuiNavLayer_Menu)) // FIXME-NAV: This should be done in NavInit.. or in FocusWindow..
if (apply_focus_window->DC.NavLayersActiveMask == (1 << ImGuiNavLayer_Menu))
g.NavLayer = ImGuiNavLayer_Menu; g.NavLayer = ImGuiNavLayer_Menu;
// Request OS level focus // Request OS level focus
@ -10330,10 +10359,12 @@ static void ImGui::NavUpdateWindowing()
// Apply menu/layer toggle // Apply menu/layer toggle
if (apply_toggle_layer && g.NavWindow) if (apply_toggle_layer && g.NavWindow)
{ {
ClearActiveID();
// Move to parent menu if necessary // Move to parent menu if necessary
ImGuiWindow* new_nav_window = g.NavWindow; ImGuiWindow* new_nav_window = g.NavWindow;
while (new_nav_window->ParentWindow while (new_nav_window->ParentWindow
&& (new_nav_window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0 && (new_nav_window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0
&& (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0
&& (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
new_nav_window = new_nav_window->ParentWindow; new_nav_window = new_nav_window->ParentWindow;
@ -10346,8 +10377,8 @@ static void ImGui::NavUpdateWindowing()
g.NavDisableHighlight = false; g.NavDisableHighlight = false;
g.NavDisableMouseHover = true; g.NavDisableMouseHover = true;
// Reinitialize navigation when entering menu bar with the Alt key. We make it persist on Docking Tab Bars. // Reinitialize navigation when entering menu bar with the Alt key.
const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main; const ImGuiNavLayer new_nav_layer = (g.NavWindow->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) ? (ImGuiNavLayer)((int)g.NavLayer ^ 1) : ImGuiNavLayer_Main;
const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL); const bool preserve_layer_1_nav_id = (new_nav_window->DockNodeAsHost != NULL);
if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id) if (new_nav_layer == ImGuiNavLayer_Menu && !preserve_layer_1_nav_id)
g.NavWindow->NavLastIds[new_nav_layer] = 0; g.NavWindow->NavLastIds[new_nav_layer] = 0;
@ -10386,6 +10417,7 @@ void ImGui::NavUpdateWindowingOverlay()
for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--) for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
{ {
ImGuiWindow* window = g.WindowsFocusOrder[n]; ImGuiWindow* window = g.WindowsFocusOrder[n];
IM_ASSERT(window != NULL); // Fix static analyzers
if (!IsWindowNavFocusable(window)) if (!IsWindowNavFocusable(window))
continue; continue;
const char* label = window->Name; const char* label = window->Name;
@ -13929,7 +13961,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
window->DockTabItemRect = host_window->DC.LastItemRect; window->DockTabItemRect = host_window->DC.LastItemRect;
// Update navigation ID on menu layer // Update navigation ID on menu layer
if (g.NavWindow && g.NavWindow->RootWindow == window && (window->DC.NavLayerActiveMask & (1 << ImGuiNavLayer_Menu)) == 0) if (g.NavWindow && g.NavWindow->RootWindow == window && (window->DC.NavLayersActiveMask & (1 << ImGuiNavLayer_Menu)) == 0)
host_window->NavLastIds[1] = window->ID; host_window->NavLastIds[1] = window->ID;
} }
} }
@ -16828,21 +16860,30 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label)
BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : ""); BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f) Scrollbar:%s%s", window->Scroll.x, window->ScrollMax.x, window->Scroll.y, window->ScrollMax.y, window->ScrollbarX ? "X" : "", window->ScrollbarY ? "Y" : "");
BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1); BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems); BulletText("Appearing: %d, Hidden: %d (CanSkip %d Cannot %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesCanSkipItems, window->HiddenFramesCannotSkipItems, window->SkipItems);
BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); for (int layer = 0; layer < ImGuiNavLayer_COUNT; layer++)
BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); {
if (!window->NavRectRel[0].IsInverted()) ImRect r = window->NavRectRel[layer];
BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y)
else {
BulletText("NavRectRel[0]: <None>"); BulletText("NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]);
continue;
}
BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y);
if (IsItemHovered())
GetForegroundDrawList(window)->AddRect(r.Min + window->Pos, r.Max + window->Pos, IM_COL32(255, 255, 0, 255));
}
BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
BulletText("Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window->Viewport ? window->Viewport->Idx : -1, window->ViewportOwned ? " (Owned)" : "", window->ViewportId, window->ViewportPos.x, window->ViewportPos.y); BulletText("Viewport: %d%s, ViewportId: 0x%08X, ViewportPos: (%.1f,%.1f)", window->Viewport ? window->Viewport->Idx : -1, window->ViewportOwned ? " (Owned)" : "", window->ViewportId, window->ViewportPos.x, window->ViewportPos.y);
BulletText("ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1); BulletText("ViewportMonitor: %d", window->Viewport ? window->Viewport->PlatformMonitor : -1);
BulletText("DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible); BulletText("DockId: 0x%04X, DockOrder: %d, Act: %d, Vis: %d", window->DockId, window->DockOrder, window->DockIsActive, window->DockTabIsVisible);
if (window->DockNode || window->DockNodeAsHost) if (window->DockNode || window->DockNodeAsHost)
DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ? "DockNodeAsHost" : "DockNode"); DebugNodeDockNode(window->DockNodeAsHost ? window->DockNodeAsHost : window->DockNode, window->DockNodeAsHost ? "DockNodeAsHost" : "DockNode");
if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); }
if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree, "RootWindowDockTree"); } if (window->RootWindowDockTree != window->RootWindow) { DebugNodeWindow(window->RootWindowDockTree, "RootWindowDockTree"); }
if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); } if (window->ParentWindow != NULL) { DebugNodeWindow(window->ParentWindow, "ParentWindow"); }
if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); } if (window->DC.ChildWindows.Size > 0) { DebugNodeWindowsList(&window->DC.ChildWindows, "ChildWindows"); }
if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) if (window->ColumnsStorage.Size > 0 && TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
{ {
for (int n = 0; n < window->ColumnsStorage.Size; n++) for (int n = 0; n < window->ColumnsStorage.Size; n++)

17
imgui.h
View File

@ -62,7 +62,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.83 WIP" #define IMGUI_VERSION "1.83 WIP"
#define IMGUI_VERSION_NUM 18204 #define IMGUI_VERSION_NUM 18209
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
@ -104,6 +104,10 @@ Index of this file:
#endif #endif
// Warnings // Warnings
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
#endif
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wold-style-cast" #pragma clang diagnostic ignored "-Wold-style-cast"
@ -386,7 +390,7 @@ namespace ImGui
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame().
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame(). IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame().
IMGUI_API void PopStyleVar(int count = 1); IMGUI_API void PopStyleVar(int count = 1);
IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // == tab stop enable. Allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets
IMGUI_API void PopAllowKeyboardFocus(); IMGUI_API void PopAllowKeyboardFocus();
IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame.
IMGUI_API void PopButtonRepeat(); IMGUI_API void PopButtonRepeat();
@ -998,10 +1002,7 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input)
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) ImGuiInputTextFlags_CallbackEdit = 1 << 19 // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 21 // For internal use by functions using InputText() before reformatting data
// Obsolete names (will be removed soon) // Obsolete names (will be removed soon)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@ -3074,6 +3075,10 @@ enum ImDrawCornerFlags_
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif
// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h) // Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)
#ifdef IMGUI_INCLUDE_IMGUI_USER_H #ifdef IMGUI_INCLUDE_IMGUI_USER_H
#include "imgui_user.h" #include "imgui_user.h"

View File

@ -93,7 +93,8 @@ Index of this file:
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -5555,7 +5556,7 @@ static void ShowDemoWindowMisc()
ImGui::InputText("3", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
ImGui::PushAllowKeyboardFocus(false); ImGui::PushAllowKeyboardFocus(false);
ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
//ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool) to disable tabbing through certain widgets."); ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
ImGui::PopAllowKeyboardFocus(); ImGui::PopAllowKeyboardFocus();
ImGui::InputText("5", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop(); ImGui::TreePop();
@ -5581,6 +5582,7 @@ static void ShowDemoWindowMisc()
if (focus_3) ImGui::SetKeyboardFocusHere(); if (focus_3) ImGui::SetKeyboardFocusHere();
ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 3; if (ImGui::IsItemActive()) has_focus = 3;
ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
ImGui::PopAllowKeyboardFocus(); ImGui::PopAllowKeyboardFocus();
if (has_focus) if (has_focus)

View File

@ -54,9 +54,12 @@ Index of this file:
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4127) // condition expression is constant
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
#pragma warning (disable: 6255) // [Static Analyzer] _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead.
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -105,6 +108,9 @@ namespace IMGUI_STB_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration #pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration
#pragma warning (disable: 6011) // (stb_rectpack) Dereferencing NULL pointer 'cur->next'.
#pragma warning (disable: 6385) // (stb_truetype) Reading invalid data from 'buffer': the readable size is '_Old_3`kernel_width' bytes, but '3' bytes may be read.
#pragma warning (disable: 28182) // (stb_rectpack) Dereferencing NULL pointer. 'cur' contains the same NULL value as 'cur->next' did.
#endif #endif
#if defined(__clang__) #if defined(__clang__)
@ -3778,7 +3784,7 @@ void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, Im
if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2])) if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
{ {
pos -= offset; pos -= offset;
const ImTextureID tex_id = font_atlas->TexID; ImTextureID tex_id = font_atlas->TexID;
draw_list->PushTextureID(tex_id); draw_list->PushTextureID(tex_id);
draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow); draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);

View File

@ -54,7 +54,10 @@ Index of this file:
// Visual Studio warnings // Visual Studio warnings
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning (push) #pragma warning (push)
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport) #pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
#pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -111,7 +114,7 @@ struct ImGuiGroupData; // Stacked storage data for BeginGroup()/End
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
struct ImGuiNavMoveResult; // Result of a gamepad/keyboard directional navigation move query result struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
struct ImGuiNextItemData; // Storage for SetNextItem** functions struct ImGuiNextItemData; // Storage for SetNextItem** functions
@ -135,6 +138,7 @@ struct ImGuiWindowSettings; // Storage for a window .ini settings (we ke
typedef int ImGuiDataAuthority; // -> enum ImGuiDataAuthority_ // Enum: for storing the source authority (dock node vs window) of a field typedef int ImGuiDataAuthority; // -> enum ImGuiDataAuthority_ // Enum: for storing the source authority (dock node vs window) of a field
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag() typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
typedef int ImGuiItemAddFlags; // -> enum ImGuiItemAddFlags_ // Flags: for ItemAdd()
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns() typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight() typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
@ -240,6 +244,13 @@ namespace ImStb
#define IMGUI_CDECL #define IMGUI_CDECL
#endif #endif
// Warnings
#if defined(_MSC_VER) && !defined(__clang__)
#define IM_MSVC_WARNING_SUPPRESS(XXXX) __pragma(warning(suppress: XXXX))
#else
#define IM_MSVC_WARNING_SUPPRESS(XXXX)
#endif
// Debug Tools // Debug Tools
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item. // Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
#ifndef IM_DEBUG_BREAK #ifndef IM_DEBUG_BREAK
@ -504,12 +515,12 @@ inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on ran
} }
// Helper: ImBitArray class (wrapper over ImBitArray functions) // Helper: ImBitArray class (wrapper over ImBitArray functions)
// Store 1-bit per value. NOT CLEARED by constructor. // Store 1-bit per value.
template<int BITCOUNT> template<int BITCOUNT>
struct IMGUI_API ImBitArray struct IMGUI_API ImBitArray
{ {
ImU32 Storage[(BITCOUNT + 31) >> 5]; ImU32 Storage[(BITCOUNT + 31) >> 5];
ImBitArray() { } ImBitArray() { ClearAllBits(); }
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); } void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); } void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); } bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
@ -709,32 +720,51 @@ enum ImGuiItemFlags_
ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed. ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
ImGuiItemFlags_Default_ = 0 };
// Flags for ItemAdd()
// FIXME-NAV: _Focusable is _ALMOST_ what you would expect to be called '_TabStop' but because SetKeyboardFocusHere() works on items with no TabStop we distinguish Focusable from TabStop.
enum ImGuiItemAddFlags_
{
ImGuiItemAddFlags_None = 0,
ImGuiItemAddFlags_Focusable = 1 << 0 // FIXME-NAV: In current/legacy scheme, Focusable+TabStop support are opt-in by widgets. We will transition it toward being opt-out, so this flag is expected to eventually disappear.
}; };
// Storage for LastItem data // Storage for LastItem data
enum ImGuiItemStatusFlags_ enum ImGuiItemStatusFlags_
{ {
ImGuiItemStatusFlags_None = 0, ImGuiItemStatusFlags_None = 0,
ImGuiItemStatusFlags_HoveredRect = 1 << 0, ImGuiItemStatusFlags_HoveredRect = 1 << 0, // Mouse position is within item rectangle (does NOT mean that the window is in correct z-order and can be hovered!, this is only one part of the most-common IsItemHovered test)
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // LastItemDisplayRect is valid ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // window->DC.LastItemDisplayRect is valid
ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues. ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected", only state changes, in order to easily handle clipping with less issues.
ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state.
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
ImGuiItemStatusFlags_HoveredWindow = 1 << 7 // Override the HoveredWindow test to allow cross-window hover testing. ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
ImGuiItemStatusFlags_FocusedByCode = 1 << 8, // Set when the Focusable item just got focused from code.
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 9, // Set when the Focusable item just got focused by Tabbing.
ImGuiItemStatusFlags_Focused = ImGuiItemStatusFlags_FocusedByCode | ImGuiItemStatusFlags_FocusedByTabbing
#ifdef IMGUI_ENABLE_TEST_ENGINE #ifdef IMGUI_ENABLE_TEST_ENGINE
, // [imgui_tests only] , // [imgui_tests only]
ImGuiItemStatusFlags_Openable = 1 << 10, // ImGuiItemStatusFlags_Openable = 1 << 20, //
ImGuiItemStatusFlags_Opened = 1 << 11, // ImGuiItemStatusFlags_Opened = 1 << 21, //
ImGuiItemStatusFlags_Checkable = 1 << 12, // ImGuiItemStatusFlags_Checkable = 1 << 22, //
ImGuiItemStatusFlags_Checked = 1 << 13 // ImGuiItemStatusFlags_Checked = 1 << 23 //
#endif #endif
}; };
// Extend ImGuiInputTextFlags_
enum ImGuiInputTextFlagsPrivate_
{
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data
ImGuiInputTextFlags_MergedItem = 1 << 28 // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
};
// Extend ImGuiButtonFlags_ // Extend ImGuiButtonFlags_
enum ImGuiButtonFlagsPrivate_ enum ImGuiButtonFlagsPrivate_
{ {
@ -1025,18 +1055,18 @@ struct ImGuiPopupData
ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; } ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; }
}; };
struct ImGuiNavMoveResult struct ImGuiNavItemData
{ {
ImGuiWindow* Window; // Best candidate window ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window)
ImGuiID ID; // Best candidate ID ImGuiID ID; // Init,Move // Best candidate item ID
ImGuiID FocusScopeId; // Best candidate focus scope ID ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID
float DistBox; // Best candidate box distance to current NavId ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space
float DistCenter; // Best candidate center distance to current NavId float DistBox; // Move // Best candidate box distance to current NavId
float DistAxial; float DistCenter; // Move // Best candidate center distance to current NavId
ImRect RectRel; // Best candidate bounding box in window relative space float DistAxial; // Move // Best candidate axial distance to current NavId
ImGuiNavMoveResult() { Clear(); } ImGuiNavItemData() { Clear(); }
void Clear() { Window = NULL; ID = FocusScopeId = 0; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } void Clear() { Window = NULL; ID = FocusScopeId = 0; RectRel = ImRect(); DistBox = DistCenter = DistAxial = FLT_MAX; }
}; };
enum ImGuiNextWindowDataFlags_ enum ImGuiNextWindowDataFlags_
@ -1507,6 +1537,7 @@ struct ImGuiContext
float WheelingWindowTimer; float WheelingWindowTimer;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
@ -1596,9 +1627,9 @@ struct ImGuiContext
ImGuiKeyModFlags NavMoveRequestKeyMods; ImGuiKeyModFlags NavMoveRequestKeyMods;
ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename? ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag) ImGuiNavItemData NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag) ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around. ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around.
ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags. ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags.
@ -1617,7 +1648,7 @@ struct ImGuiContext
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
int TabFocusRequestNextCounterRegular; // Stored for next frame int TabFocusRequestNextCounterRegular; // Stored for next frame
int TabFocusRequestNextCounterTabStop; // " int TabFocusRequestNextCounterTabStop; // "
bool TabFocusPressed; // bool TabFocusPressed; // Set in NewFrame() when user pressed Tab
// Render // Render
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list) float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
@ -1749,6 +1780,7 @@ struct ImGuiContext
WheelingWindow = NULL; WheelingWindow = NULL;
WheelingWindowTimer = 0.0f; WheelingWindowTimer = 0.0f;
CurrentItemFlags = ImGuiItemFlags_None;
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
@ -1909,8 +1941,8 @@ struct IMGUI_API ImGuiWindowTempData
// Keyboard/Gamepad navigation // Keyboard/Gamepad navigation
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
int NavLayerActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
int NavLayerActiveMaskNext; // Which layers have been written to (accumulator for current frame) short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame)
ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending
bool NavHideHighlightOneFrame; bool NavHideHighlightOneFrame;
bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f)
@ -1932,7 +1964,6 @@ struct IMGUI_API ImGuiWindowTempData
// Local parameters stacks // Local parameters stacks
// We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings.
ImGuiItemFlags ItemFlags; // == g.ItemFlagsStack.back()
float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window). float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window).
float TextWrapPos; // Current text wrap pos. float TextWrapPos; // Current text wrap pos.
ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth) ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth)
@ -2501,7 +2532,7 @@ namespace ImGui
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; } inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; } inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; } inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
inline ImGuiItemFlags GetItemsFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; } inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentItemFlags; }
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void ClearActiveID(); IMGUI_API void ClearActiveID();
@ -2515,12 +2546,11 @@ namespace ImGui
// Basic Helpers for widget code // Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemAddFlags flags = 0);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API void ItemFocusable(ImGuiWindow* window, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect); IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
IMGUI_API void PushMultiItemsWidths(int components, float width_full); IMGUI_API void PushMultiItemsWidths(int components, float width_full);
@ -2530,6 +2560,15 @@ namespace ImGui
IMGUI_API ImVec2 GetContentRegionMaxAbs(); IMGUI_API ImVec2 GetContentRegionMaxAbs();
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess); IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)'
// (New) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Focusable flag to ItemAdd()
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
#endif
// Logging/Capture // Logging/Capture
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name. IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer
@ -2559,7 +2598,7 @@ namespace ImGui
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate); IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
IMGUI_API void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
// Focus Scope (WIP) // Focus Scope (WIP)
// This is generally used to identify a selection set (multiple of which may be in the same window), as selection // This is generally used to identify a selection set (multiple of which may be in the same window), as selection

View File

@ -210,6 +210,8 @@ Index of this file:
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
#endif #endif
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -2296,10 +2298,11 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
ImRect ClipRect; ImRect ClipRect;
int ChannelsCount; int ChannelsCount;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask; ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask;
MergeGroup() { ChannelsCount = 0; }
}; };
int merge_group_mask = 0x00; int merge_group_mask = 0x00;
MergeGroup merge_groups[4]; MergeGroup merge_groups[4];
memset(merge_groups, 0, sizeof(merge_groups));
// 1. Scan channels and take note of those which can be merged // 1. Scan channels and take note of those which can be merged
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@ -2377,7 +2380,6 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized
ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data; ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data;
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage
remaining_mask.ClearAllBits();
remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count); remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count);
remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen); remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen);
IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN); IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN);

View File

@ -59,6 +59,8 @@ Index of this file:
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later #if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types #pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
#endif #endif
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#endif #endif
// Clang/GCC warnings with -Weverything // Clang/GCC warnings with -Weverything
@ -686,7 +688,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
if (!ItemAdd(bb, id)) if (!ItemAdd(bb, id))
return false; return false;
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat; flags |= ImGuiButtonFlags_Repeat;
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
@ -762,7 +764,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
if (!ItemAdd(bb, id)) if (!ItemAdd(bb, id))
return false; return false;
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
flags |= ImGuiButtonFlags_Repeat; flags |= ImGuiButtonFlags_Repeat;
bool hovered, held; bool hovered, held;
@ -1088,7 +1090,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id)) if (!ItemAdd(total_bb, id))
{ {
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false; return false;
} }
@ -1104,7 +1106,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
RenderNavHighlight(total_bb, id); RenderNavHighlight(total_bb, id);
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark); ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
bool mixed_value = (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) != 0; bool mixed_value = (g.CurrentItemFlags & ImGuiItemFlags_MixedValue) != 0;
if (mixed_value) if (mixed_value)
{ {
// Undocumented tristate/mixed/indeterminate checkbox (#2644) // Undocumented tristate/mixed/indeterminate checkbox (#2644)
@ -1124,7 +1126,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(label_pos, label); RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return pressed; return pressed;
} }
@ -1136,11 +1138,11 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
bool pressed; bool pressed;
if (!all_on && any_on) if (!all_on && any_on)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiContext& g = *GImGui;
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_MixedValue; g.CurrentItemFlags |= ImGuiItemFlags_MixedValue;
pressed = Checkbox(label, &all_on); pressed = Checkbox(label, &all_on);
window->DC.ItemFlags = backup_item_flags; g.CurrentItemFlags = backup_item_flags;
} }
else else
{ {
@ -1226,7 +1228,7 @@ bool ImGui::RadioButton(const char* label, bool active)
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(label_pos, label); RenderText(label_pos, label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed; return pressed;
} }
@ -1438,10 +1440,10 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
bool item_add = ItemAdd(bb, id); bool item_add = ItemAdd(bb, id);
window->DC.ItemFlags = item_flags_backup; g.CurrentItemFlags = item_flags_backup;
if (!item_add) if (!item_add)
return false; return false;
@ -1987,13 +1989,15 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
{ {
// All other types assign constant // All other types assign constant
// We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future. // We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
sscanf(buf, format, p_data); if (sscanf(buf, format, p_data) < 1)
return false;
} }
else else
{ {
// Small types need a 32-bit buffer to receive the result from scanf() // Small types need a 32-bit buffer to receive the result from scanf()
int v32; int v32;
sscanf(buf, format, &v32); if (sscanf(buf, format, &v32) < 1)
return false;
if (data_type == ImGuiDataType_S8) if (data_type == ImGuiDataType_S8)
*(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX); *(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
else if (data_type == ImGuiDataType_U8) else if (data_type == ImGuiDataType_U8)
@ -2280,7 +2284,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
} }
if (g.ActiveId != id) if (g.ActiveId != id)
return false; return false;
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false; return false;
switch (data_type) switch (data_type)
@ -2318,8 +2322,9 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb)) if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
return false; return false;
// Default format string when passing NULL // Default format string when passing NULL
@ -2330,11 +2335,10 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
// Tabbing or CTRL-clicking on Drag turns it into an InputText // Tabbing or CTRL-clicking on Drag turns it into an InputText
const bool hovered = ItemHoverable(frame_bb, id); const bool hovered = ItemHoverable(frame_bb, id);
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id); const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;
const bool clicked = (hovered && g.IO.MouseClicked[0]); const bool clicked = (hovered && g.IO.MouseClicked[0]);
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]); const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id) if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
@ -2344,10 +2348,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
FocusWindow(window); FocusWindow(window);
g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id)) if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id))
{
temp_input_is_active = true; temp_input_is_active = true;
FocusableItemUnregister(window);
}
} }
// Experimental: simple click (without moving) turns Drag into an InputText // Experimental: simple click (without moving) turns Drag into an InputText
// FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings. // FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings.
@ -2356,7 +2357,6 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
{ {
g.NavInputId = id; g.NavInputId = id;
temp_input_is_active = true; temp_input_is_active = true;
FocusableItemUnregister(window);
} }
} }
@ -2387,7 +2387,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return value_changed; return value_changed;
} }
@ -2887,7 +2887,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead."); IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly)) if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
return false; return false;
switch (data_type) switch (data_type)
@ -2937,8 +2937,9 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f)); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb)) if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
return false; return false;
// Default format string when passing NULL // Default format string when passing NULL
@ -2949,11 +2950,10 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Tabbing or CTRL-clicking on Slider turns it into an input box // Tabbing or CTRL-clicking on Slider turns it into an input box
const bool hovered = ItemHoverable(frame_bb, id); const bool hovered = ItemHoverable(frame_bb, id);
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id); bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
if (!temp_input_is_active) if (!temp_input_is_active)
{ {
const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id); const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;
const bool clicked = (hovered && g.IO.MouseClicked[0]); const bool clicked = (hovered && g.IO.MouseClicked[0]);
if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id) if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
{ {
@ -2962,10 +2962,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
FocusWindow(window); FocusWindow(window);
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id)) if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id))
{
temp_input_is_active = true; temp_input_is_active = true;
FocusableItemUnregister(window);
}
} }
} }
@ -3001,7 +2998,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (label_size.x > 0.0f) if (label_size.x > 0.0f)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return value_changed; return value_changed;
} }
@ -3292,7 +3289,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
ClearActiveID(); ClearActiveID();
g.CurrentWindow->DC.CursorPos = bb.Min; g.CurrentWindow->DC.CursorPos = bb.Min;
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags); bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
if (init) if (init)
{ {
// First frame we started displaying the InputText widget, we expect it to take the active id. // First frame we started displaying the InputText widget, we expect it to take the active id.
@ -3904,7 +3901,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 inner_size = frame_size; ImVec2 inner_size = frame_size;
if (is_multiline) if (is_multiline)
{ {
if (!ItemAdd(total_bb, id, &frame_bb)) if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
{ {
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
EndGroup(); EndGroup();
@ -3925,15 +3922,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
return false; return false;
} }
draw_window = g.CurrentWindow; // Child window draw_window = g.CurrentWindow; // Child window
draw_window->DC.NavLayerActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it. draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
draw_window->DC.CursorPos += style.FramePadding; draw_window->DC.CursorPos += style.FramePadding;
inner_size.x -= draw_window->ScrollbarSizes.x; inner_size.x -= draw_window->ScrollbarSizes.x;
} }
else else
{ {
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb)) if (!(flags & ImGuiInputTextFlags_MergedItem))
return false; if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
return false;
} }
const bool hovered = ItemHoverable(frame_bb, id); const bool hovered = ItemHoverable(frame_bb, id);
if (hovered) if (hovered)
@ -3942,9 +3941,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We are only allowed to access the state if we are already the active widget. // We are only allowed to access the state if we are already the active widget.
ImGuiInputTextState* state = GetInputTextState(id); ImGuiInputTextState* state = GetInputTextState(id);
const bool focus_requested = FocusableItemRegister(window, id); const bool focus_requested_by_code = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByCode) != 0;
const bool focus_requested_by_code = focus_requested && (g.TabFocusRequestCurrWindow == window && g.TabFocusRequestCurrCounterRegular == window->DC.FocusCounterRegular); const bool focus_requested_by_tabbing = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_clicked = hovered && io.MouseClicked[0];
const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard)); const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
@ -3957,7 +3955,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX; float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start); const bool init_make_active = (user_clicked || user_scroll_finish || user_nav_input_start || focus_requested_by_code || focus_requested_by_tabbing);
const bool init_state = (init_make_active || user_scroll_active); const bool init_state = (init_make_active || user_scroll_active);
if ((init_state && g.ActiveId != id) || init_changed_specs) if ((init_state && g.ActiveId != id) || init_changed_specs)
{ {
@ -3998,7 +3996,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
} }
if (flags & ImGuiInputTextFlags_AlwaysOverwrite) if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863) state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl))) if (!is_multiline && (focus_requested_by_tabbing || (user_clicked && io.KeyCtrl)))
select_all = true; select_all = true;
} }
@ -4613,7 +4611,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{ {
state->CursorAnim += io.DeltaTime; state->CursorAnim += io.DeltaTime;
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll; ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
@ -4666,7 +4664,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited)) if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
MarkItemEdited(id); MarkItemEdited(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0) if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
return enter_pressed; return enter_pressed;
else else
@ -4824,10 +4822,12 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
p++; p++;
i[0] = i[1] = i[2] = 0; i[0] = i[1] = i[2] = 0;
i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha) i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha)
int r;
if (alpha) if (alpha)
sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned) r = sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
else else
sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]); r = sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
IM_UNUSED(r); // Fixes C6031: Return value ignored: 'sscanf'.
} }
if (!(flags & ImGuiColorEditFlags_NoOptions)) if (!(flags & ImGuiColorEditFlags_NoOptions))
OpenPopupOnItemClick("context"); OpenPopupOnItemClick("context");
@ -5765,7 +5765,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
{ {
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushOverrideID(id); TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open; return is_open;
} }
@ -5891,7 +5891,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
TreePushOverrideID(id); TreePushOverrideID(id);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
return is_open; return is_open;
} }
@ -6074,10 +6074,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
bool item_add; bool item_add;
if (flags & ImGuiSelectableFlags_Disabled) if (flags & ImGuiSelectableFlags_Disabled)
{ {
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
item_add = ItemAdd(bb, id); item_add = ItemAdd(bb, id);
window->DC.ItemFlags = backup_item_flags; g.CurrentItemFlags = backup_item_flags;
} }
else else
{ {
@ -6155,10 +6155,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
// Automatically close popups // Automatically close popups
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup)) if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
CloseCurrentPopup(); CloseCurrentPopup();
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
return pressed; return pressed;
} }
@ -6599,7 +6599,7 @@ void ImGui::EndMenuBar()
// To do so we claim focus back, restore NavId and then process the movement request for yet another frame. // To do so we claim focus back, restore NavId and then process the movement request for yet another frame.
// This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost)
const ImGuiNavLayer layer = ImGuiNavLayer_Menu; const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check
FocusWindow(window); FocusWindow(window);
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
@ -6609,6 +6609,7 @@ void ImGui::EndMenuBar()
} }
} }
IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);
IM_ASSERT(window->DC.MenuBarAppending); IM_ASSERT(window->DC.MenuBarAppending);
PopClipRect(); PopClipRect();
@ -6835,7 +6836,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None)) if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None))
ClosePopupToLevel(g.BeginPopupStack.Size, true); ClosePopupToLevel(g.BeginPopupStack.Size, true);
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{ {
@ -6922,7 +6923,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f); RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
} }
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0)); IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
return pressed; return pressed;
} }
@ -7252,6 +7253,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
curr_section_n = section_n; curr_section_n = section_n;
// Store data so we can build an array sorted by width if we need to shrink tabs down // Store data so we can build an array sorted by width if we need to shrink tabs down
IM_MSVC_WARNING_SUPPRESS(6385);
int shrink_buffer_index = shrink_buffer_indexes[section_n]++; int shrink_buffer_index = shrink_buffer_indexes[section_n]++;
g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n; g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n;
g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth; g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth;