Merge remote-tracking branch 'origin/master' into docking

features/sdl_renderer3_multiviewports
ocornut ago%!(EXTRA string=11 months)
commit 36ffdd69d3
  1. 4
      docs/CHANGELOG.txt
  2. 111
      imgui.cpp
  3. 3
      imgui.h
  4. 23
      imgui_internal.h
  5. 19
      imgui_tables.cpp

@ -59,6 +59,10 @@ Other changes:
- Inputs: (OSX) Fixes variety of code which inconsistently required using Ctrl instead of Cmd. - Inputs: (OSX) Fixes variety of code which inconsistently required using Ctrl instead of Cmd.
- e.g. Drags/Sliders now use Cmd+Click to input a value. (#4084) - e.g. Drags/Sliders now use Cmd+Click to input a value. (#4084)
- Some shortcuts still uses Ctrl on Mac: e.g. Ctrl+Tab to switch windows. (#4828) - Some shortcuts still uses Ctrl on Mac: e.g. Ctrl+Tab to switch windows. (#4828)
- Inputs: (OSX) Ctrl+Left Click alias as a Right click. (#2343) [@haldean, @ocornut]
- Inputs: Fixed ImGui::GetKeyName(ImGuiKey_None) from returning "N/A" or "None" depending
on value of IMGUI_DISABLE_OBSOLETE_KEYIO. It always returns "None".
- Windows: BeginChild(): fixed visibility of fully clipped child windows and tables to Test Engine.
- Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed. - Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
Broken during a refactor refactor for 1.89. Holding Shift/R1 to speed up wasn't broken. Broken during a refactor refactor for 1.89. Holding Shift/R1 to speed up wasn't broken.
- Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet] - Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet]

@ -1523,7 +1523,7 @@ static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventT
// - bool down: Is the key down? use false to signify a key release. // - bool down: Is the key down? use false to signify a key release.
// - float analog_value: 0.0f..1.0f // - float analog_value: 0.0f..1.0f
// IMPORTANT: THIS FUNCTION AND OTHER "ADD" GRABS THE CONTEXT FROM OUR INSTANCE. // IMPORTANT: THIS FUNCTION AND OTHER "ADD" GRABS THE CONTEXT FROM OUR INSTANCE.
// WE NEED TO ENSURE THAT ALL FUNCTION CALLS ARE FULLFILLING THIS, WHICH IS WHY GetKeyData() HAS AN EXPLICIT CONTEXT. // WE NEED TO ENSURE THAT ALL FUNCTION CALLS ARE FULFILLING THIS, WHICH IS WHY GetKeyData() HAS AN EXPLICIT CONTEXT.
void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value) void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
{ {
//if (e->Down) { IMGUI_DEBUG_LOG_IO("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); } //if (e->Down) { IMGUI_DEBUG_LOG_IO("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); }
@ -1531,7 +1531,7 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
if (key == ImGuiKey_None || !AppAcceptingEvents) if (key == ImGuiKey_None || !AppAcceptingEvents)
return; return;
ImGuiContext& g = *Ctx; ImGuiContext& g = *Ctx;
IM_ASSERT(ImGui::IsNamedKeyOrModKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API. IM_ASSERT(ImGui::IsNamedKeyOrMod(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API.
IM_ASSERT(ImGui::IsAliasKey(key) == false); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events. IM_ASSERT(ImGui::IsAliasKey(key) == false); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events.
// MacOS: swap Cmd(Super) and Ctrl // MacOS: swap Cmd(Super) and Ctrl
@ -1648,12 +1648,36 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
if (!AppAcceptingEvents) if (!AppAcceptingEvents)
return; return;
// On MacOS X: Convert Ctrl(Super)+Left click into Right-click: handle held button.
if (ConfigMacOSXBehaviors && mouse_button == 0 && MouseCtrlLeftAsRightClick)
{
// Order of both statements matterns: this event will still release mouse button 1
mouse_button = 1;
if (!down)
MouseCtrlLeftAsRightClick = false;
}
// Filter duplicate // Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseButton, (int)mouse_button); const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseButton, (int)mouse_button);
const bool latest_button_down = latest_event ? latest_event->MouseButton.Down : g.IO.MouseDown[mouse_button]; const bool latest_button_down = latest_event ? latest_event->MouseButton.Down : g.IO.MouseDown[mouse_button];
if (latest_button_down == down) if (latest_button_down == down)
return; return;
// On MacOS X: Convert Ctrl(Super)+Left click into Right-click.
// - Note that this is actual physical Ctrl which is ImGuiMod_Super for us.
// - At this point we want from !down to down, so this is handling the initial press.
if (ConfigMacOSXBehaviors && mouse_button == 0 && down)
{
const ImGuiInputEvent* latest_super_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (int)ImGuiMod_Super);
if (latest_super_event ? latest_super_event->Key.Down : g.IO.KeySuper)
{
IMGUI_DEBUG_LOG_IO("[io] Super+Left Click aliased into Right Click\n");
MouseCtrlLeftAsRightClick = true;
AddMouseButtonEvent(1, true); // This is just quicker to write that passing through, as we need to filter duplicate again.
return;
}
}
ImGuiInputEvent e; ImGuiInputEvent e;
e.Type = ImGuiInputEventType_MouseButton; e.Type = ImGuiInputEventType_MouseButton;
e.Source = ImGuiInputSource_Mouse; e.Source = ImGuiInputSource_Mouse;
@ -5863,7 +5887,9 @@ void ImGui::EndChild()
else else
{ {
// Not navigable into // Not navigable into
ItemAdd(bb, 0); // - This is a bit of a fringe use case, mostly useful for undecorated, non-scrolling contents childs, or empty childs.
// - We could later decide to not apply this path if ImGuiChildFlags_FrameStyle or ImGuiChildFlags_Borders is set.
ItemAdd(bb, child_window->ChildId, NULL, ImGuiItemFlags_NoNav);
// But when flattened we directly reach items, adjust active layer mask accordingly // But when flattened we directly reach items, adjust active layer mask accordingly
if (child_window->Flags & ImGuiWindowFlags_NavFlattened) if (child_window->Flags & ImGuiWindowFlags_NavFlattened)
@ -8851,6 +8877,8 @@ ImGuiID ImGui::GetID(const void* ptr_id)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] INPUTS // [SECTION] INPUTS
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// - GetModForModKey() [Internal]
// - FixupKeyChord() [Internal]
// - GetKeyData() [Internal] // - GetKeyData() [Internal]
// - GetKeyIndex() [Internal] // - GetKeyIndex() [Internal]
// - GetKeyName() // - GetKeyName()
@ -8912,21 +8940,25 @@ ImGuiID ImGui::GetID(const void* ptr_id)
// - Shortcut() [Internal] // - Shortcut() [Internal]
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord) static ImGuiKeyChord GetModForModKey(ImGuiKey key)
{ {
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (IsModKey(key))
{
if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl) if (key == ImGuiKey_LeftCtrl || key == ImGuiKey_RightCtrl)
key_chord |= ImGuiMod_Ctrl; return ImGuiMod_Ctrl;
if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift) if (key == ImGuiKey_LeftShift || key == ImGuiKey_RightShift)
key_chord |= ImGuiMod_Shift; return ImGuiMod_Shift;
if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt) if (key == ImGuiKey_LeftAlt || key == ImGuiKey_RightAlt)
key_chord |= ImGuiMod_Alt; return ImGuiMod_Alt;
if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper) if (key == ImGuiKey_LeftSuper || key == ImGuiKey_RightSuper)
key_chord |= ImGuiMod_Super; return ImGuiMod_Super;
} return ImGuiMod_None;
}
ImGuiKeyChord ImGui::FixupKeyChord(ImGuiKeyChord key_chord)
{
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (IsModKey(key))
key_chord |= GetModForModKey(key);
return key_chord; return key_chord;
} }
@ -8987,8 +9019,10 @@ IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));
const char* ImGui::GetKeyName(ImGuiKey key) const char* ImGui::GetKeyName(ImGuiKey key)
{ {
if (key == ImGuiKey_None)
return "None";
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT((IsNamedKeyOrModKey(key) || key == ImGuiKey_None) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code."); IM_ASSERT(IsNamedKeyOrMod(key) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
#else #else
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (IsLegacyKey(key)) if (IsLegacyKey(key))
@ -8999,8 +9033,6 @@ const char* ImGui::GetKeyName(ImGuiKey key)
key = (ImGuiKey)g.IO.KeyMap[key]; key = (ImGuiKey)g.IO.KeyMap[key];
} }
#endif #endif
if (key == ImGuiKey_None)
return "None";
if (key & ImGuiMod_Mask_) if (key & ImGuiMod_Mask_)
key = ConvertSingleModFlagToKey(key); key = ConvertSingleModFlagToKey(key);
if (!IsNamedKey(key)) if (!IsNamedKey(key))
@ -9009,16 +9041,25 @@ const char* ImGui::GetKeyName(ImGuiKey key)
return GKeyNames[key - ImGuiKey_NamedKey_BEGIN]; return GKeyNames[key - ImGuiKey_NamedKey_BEGIN];
} }
// Return untranslated names: on macOS, Cmd key will show as Ctrl, Ctrl key will show as super.
// Lifetime of return value: valid until next call to same function.
const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord) const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
key_chord = FixupKeyChord(key_chord);
const ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (IsModKey(key))
key_chord &= ~GetModForModKey(key); // Return "Ctrl+LeftShift" instead of "Ctrl+Shift+LeftShift"
ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s", ImFormatString(g.TempKeychordName, IM_ARRAYSIZE(g.TempKeychordName), "%s%s%s%s%s",
(key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "", (key_chord & ImGuiMod_Ctrl) ? "Ctrl+" : "",
(key_chord & ImGuiMod_Shift) ? "Shift+" : "", (key_chord & ImGuiMod_Shift) ? "Shift+" : "",
(key_chord & ImGuiMod_Alt) ? "Alt+" : "", (key_chord & ImGuiMod_Alt) ? "Alt+" : "",
(key_chord & ImGuiMod_Super) ? "Super+" : "", (key_chord & ImGuiMod_Super) ? "Super+" : "",
GetKeyName((ImGuiKey)(key_chord & ~ImGuiMod_Mask_))); (key != ImGuiKey_None || key_chord == ImGuiKey_None) ? GetKeyName(key) : "");
size_t len;
if (key == ImGuiKey_None && key_chord != 0)
if ((len = strlen(g.TempKeychordName)) != 0) // Remove trailing '+'
g.TempKeychordName[len - 1] = 0;
return g.TempKeychordName; return g.TempKeychordName;
} }
@ -9159,11 +9200,11 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
} }
// Current score encoding (lower is highest priority): // Current score encoding (lower is highest priority):
// - 0: ImGuiInputFlags_RouteGlobalHigh // - 0: ImGuiInputFlags_RouteGlobalHighest
// - 1: ImGuiInputFlags_RouteFocused (if item active) // - 1: ImGuiInputFlags_RouteFocused (if item active)
// - 2: ImGuiInputFlags_RouteGlobal // - 2: ImGuiInputFlags_RouteGlobalOverFocused
// - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack) // - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack)
// - 254: ImGuiInputFlags_RouteGlobalLow // - 254: ImGuiInputFlags_RouteGlobal
// - 255: never route // - 255: never route
// 'flags' should include an explicit routing policy // 'flags' should include an explicit routing policy
static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags) static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
@ -9193,10 +9234,10 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput
return 255; return 255;
} }
// ImGuiInputFlags_RouteGlobalHigh is default, so calls without flags are not conditional // ImGuiInputFlags_RouteGlobalHighest is default, so calls without flags are not conditional
if (flags & ImGuiInputFlags_RouteGlobal) if (flags & ImGuiInputFlags_RouteGlobalOverFocused)
return 2; return 2;
if (flags & ImGuiInputFlags_RouteGlobalLow) if (flags & ImGuiInputFlags_RouteGlobal)
return 254; return 254;
return 0; return 0;
} }
@ -9227,10 +9268,10 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord)
bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags) bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if ((flags & ImGuiInputFlags_RouteMask_) == 0) if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
flags |= ImGuiInputFlags_RouteGlobalHigh; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut() flags |= ImGuiInputFlags_RouteGlobalHighest; // IMPORTANT: This is the default for SetShortcutRouting() but NOT Shortcut()
else else
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteMask_)); // Check that only 1 routing flag is used IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used
IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None); IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_None);
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. // Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
@ -9247,7 +9288,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
// Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this? // Note how ImGuiInputFlags_RouteAlways won't set routing and thus won't set owner. May want to rework this?
if (flags & ImGuiInputFlags_RouteAlways) if (flags & ImGuiInputFlags_RouteAlways)
{ {
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> always\n", GetKeyChordName(key_chord), owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> always, no register\n", GetKeyChordName(key_chord), owner_id, flags);
return true; return true;
} }
@ -9266,7 +9307,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
} }
// ActiveIdUsingAllKeyboardKeys trumps all for ActiveId // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId
if ((flags & ImGuiInputFlags_RouteGlobalHigh) == 0 && g.ActiveIdUsingAllKeyboardKeys) if ((flags & ImGuiInputFlags_RouteGlobalHighest) == 0 && g.ActiveIdUsingAllKeyboardKeys)
{ {
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (key == ImGuiKey_None) if (key == ImGuiKey_None)
@ -10135,7 +10176,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
ImGuiID ImGui::GetKeyOwner(ImGuiKey key) ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
{ {
if (!IsNamedKeyOrModKey(key)) if (!IsNamedKeyOrMod(key))
return ImGuiKeyOwner_None; return ImGuiKeyOwner_None;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10155,7 +10196,7 @@ ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
// All paths are also testing for key not being locked, for the rare cases that key have been locked with using ImGuiInputFlags_LockXXX flags. // All paths are also testing for key not being locked, for the rare cases that key have been locked with using ImGuiInputFlags_LockXXX flags.
bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id) bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
{ {
if (!IsNamedKeyOrModKey(key)) if (!IsNamedKeyOrMod(key))
return true; return true;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -10189,7 +10230,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(IsNamedKeyOrModKey(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease)))); // Can only use _Any with _LockXXX flags (to eat a key away without an ID to retrieve it) IM_ASSERT(IsNamedKeyOrMod(key) && (owner_id != ImGuiKeyOwner_Any || (flags & (ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease)))); // Can only use _Any with _LockXXX flags (to eat a key away without an ID to retrieve it)
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function! IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function!
//IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X, flags=%08X)\n", GetKeyName(key), owner_id, flags); //IMGUI_DEBUG_LOG("SetKeyOwner(%s, owner_id=0x%08X, flags=%08X)\n", GetKeyName(key), owner_id, flags);
@ -10270,7 +10311,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
//IMGUI_DEBUG_LOG("Shortcut(%s, owner_id=0x%08X, flags=%X)\n", GetKeyChordName(key_chord, g.TempBuffer.Data, g.TempBuffer.Size), owner_id, flags); //IMGUI_DEBUG_LOG("Shortcut(%s, owner_id=0x%08X, flags=%X)\n", GetKeyChordName(key_chord, g.TempBuffer.Data, g.TempBuffer.Size), owner_id, flags);
// When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any. // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any.
if ((flags & ImGuiInputFlags_RouteMask_) == 0) if ((flags & ImGuiInputFlags_RouteTypeMask_) == 0)
flags |= ImGuiInputFlags_RouteFocused; flags |= ImGuiInputFlags_RouteFocused;
// Using 'owner_id == ImGuiKeyOwner_Any/0': auto-assign an owner based on current focus scope (each window has its focus scope by default) // Using 'owner_id == ImGuiKeyOwner_Any/0': auto-assign an owner based on current focus scope (each window has its focus scope by default)
@ -13455,7 +13496,7 @@ static void ImGui::NavUpdateWindowing()
g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer
g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad;
// Register ownership of our mods. Using ImGuiInputFlags_RouteGlobalHigh in the Shortcut() calls instead would probably be correct but may have more side-effects. // Manually register ownership of our mods. Using ImGuiInputFlags_RouteGlobalHighest in the Shortcut() calls instead would probably be correct but may have more side-effects.
if (keyboard_next_window || keyboard_prev_window) if (keyboard_next_window || keyboard_prev_window)
SetKeyOwnersForKeyChord((g.ConfigNavWindowingKeyNext | g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id); SetKeyOwnersForKeyChord((g.ConfigNavWindowingKeyNext | g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id);
} }
@ -21648,7 +21689,7 @@ void ImGui::ShowIDStackToolWindow(bool* p_open)
Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC); Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC);
SameLine(); SameLine();
TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(), "*COPIED*"); TextColored((time_since_copy >= 0.0f && time_since_copy < 0.75f && ImFmod(time_since_copy, 0.25f) < 0.25f * 0.5f) ? ImVec4(1.f, 1.f, 0.3f, 1.f) : ImVec4(), "*COPIED*");
if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, ImGuiInputFlags_RouteGlobal)) if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, ImGuiInputFlags_RouteGlobalOverFocused))
{ {
tool->CopyToClipboardLastTime = (float)g.Time; tool->CopyToClipboardLastTime = (float)g.Time;
char* p = g.TempBuffer.Data; char* p = g.TempBuffer.Data;

@ -28,7 +28,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.90.7 WIP" #define IMGUI_VERSION "1.90.7 WIP"
#define IMGUI_VERSION_NUM 19063 #define IMGUI_VERSION_NUM 19065
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch
@ -2335,6 +2335,7 @@ struct ImGuiIO
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window. bool MouseDownOwnedUnlessPopupClose[5]; // Track if button was clicked inside a dear imgui window.
bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system. bool MouseWheelRequestAxisSwap; // On a non-Mac system, holding SHIFT requests WheelY to perform the equivalent of a WheelX event. On a Mac system this is already enforced by the system.
bool MouseCtrlLeftAsRightClick; // (OSX) Set to true when the current click was a ctrl-click that spawned a simulated right click
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point

@ -1508,26 +1508,27 @@ enum ImGuiInputFlags_
// - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register // - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register
// a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority // a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority
// is claiming the same shortcut. // is claiming the same shortcut.
// - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute(). // - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute()
// - Priorities: GlobalHigh > Focused (when owner is active item) > Global > Focused (when focused window) > GlobalLow. // e.g. if you have a tool window associated to a document, and you want document shortcuts to run when the tool is focused.
// - Priorities: GlobalHighest > Focused (if owner is active item) > GlobalOverFocused > Focused (if in focused window) > Global.
// - Can select only 1 policy among all available. // - Can select only 1 policy among all available.
ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.
ImGuiInputFlags_RouteGlobalLow = 1 << 13, // Register route globally (lowest priority: unless a focused window or active item registered the route) -> recommended Global priority IF you need a Global priority. ImGuiInputFlags_RouteGlobal = 1 << 13, // Register route globally (normal priority: unless a focused window or active item registered the route) -> recommended Global priority.
ImGuiInputFlags_RouteGlobal = 1 << 14, // Register route globally (medium priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). ImGuiInputFlags_RouteGlobalOverFocused = 1 << 14, // Register route globally (higher priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this).
ImGuiInputFlags_RouteGlobalHigh = 1 << 15, // Register route globally (higher priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overriden by this) ImGuiInputFlags_RouteGlobalHighest = 1 << 15, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this)
ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly. ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly.
// Routing polices: extra options // Routing polices: extra options
ImGuiInputFlags_RouteUnlessBgFocused= 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. ImGuiInputFlags_RouteUnlessBgFocused = 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
// [Internal] Mask of which function support which flags // [Internal] Mask of which function support which flags
ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak,
ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress,
ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_,
ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive,
ImGuiInputFlags_RouteMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalLow | ImGuiInputFlags_RouteGlobalHigh, // _Always not part of this! ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways,
ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_,
ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat,
ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteMask_ | ImGuiInputFlags_RouteAlways | ImGuiInputFlags_RouteUnlessBgFocused, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteUnlessBgFocused,
ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease, ImGuiInputFlags_SupportedBySetKeyOwner = ImGuiInputFlags_LockThisFrame | ImGuiInputFlags_LockUntilRelease,
ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_, ImGuiInputFlags_SupportedBySetItemKeyOwner = ImGuiInputFlags_SupportedBySetKeyOwner | ImGuiInputFlags_CondMask_,
}; };
@ -3067,8 +3068,7 @@ struct ImGuiTableInstanceData
ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastTopHeadersRowHeight = LastFrozenHeight = 0.0f; HoveredRowLast = HoveredRowNext = -1; } ImGuiTableInstanceData() { TableInstanceID = 0; LastOuterHeight = LastTopHeadersRowHeight = LastFrozenHeight = 0.0f; HoveredRowLast = HoveredRowNext = -1; }
}; };
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs, incoming RowData // sizeof() ~ 592 bytes + heap allocs described in TableBeginInitMemory()
// sizeof() ~ 580 bytes + heap allocs described in TableBeginInitMemory()
struct IMGUI_API ImGuiTable struct IMGUI_API ImGuiTable
{ {
ImGuiID ID; ImGuiID ID;
@ -3191,6 +3191,7 @@ struct IMGUI_API ImGuiTable
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table). // Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure. // - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics. // - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs.
// sizeof() ~ 136 bytes. // sizeof() ~ 136 bytes.
struct IMGUI_API ImGuiTableTempData struct IMGUI_API ImGuiTableTempData
{ {
@ -3460,7 +3461,7 @@ namespace ImGui
// Inputs // Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; } inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
inline bool IsNamedKeyOrModKey(ImGuiKey key) { return (key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END) || key == ImGuiMod_Ctrl || key == ImGuiMod_Shift || key == ImGuiMod_Alt || key == ImGuiMod_Super; } inline bool IsNamedKeyOrMod(ImGuiKey key) { return (key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END) || key == ImGuiMod_Ctrl || key == ImGuiMod_Shift || key == ImGuiMod_Alt || key == ImGuiMod_Super; }
inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; } inline bool IsLegacyKey(ImGuiKey key) { return key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_LegacyNativeKey_END; }
inline bool IsKeyboardKey(ImGuiKey key) { return key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END; } inline bool IsKeyboardKey(ImGuiKey key) { return key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END; }
inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; } inline bool IsGamepadKey(ImGuiKey key) { return key >= ImGuiKey_Gamepad_BEGIN && key < ImGuiKey_Gamepad_END; }

@ -320,6 +320,12 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
IM_ASSERT(inner_width >= 0.0f); IM_ASSERT(inner_width >= 0.0f);
// If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve. // If an outer size is specified ahead we will be able to early out when not visible. Exact clipping criteria may evolve.
// FIXME: coarse clipping because access to table data causes two issues:
// - instance numbers varying/unstable. may not be a direct problem for users, but could make outside access broken or confusing, e.g. TestEngine.
// - can't implement support for ImGuiChildFlags_ResizeY as we need to somehow pull the height data from somewhere. this also needs stable instance numbers.
// The side-effects of accessing table data on coarse clip would be:
// - always reserving the pooled ImGuiTable data ahead for a fully clipped table (minor IMHO). Also the 'outer_window_is_measuring_size' criteria may already be defeating this in some situations.
// - always performing the GetOrAddByKey() O(log N) query in g.Tables.Map[].
const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0; const bool use_child_window = (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0;
const ImVec2 avail_size = GetContentRegionAvail(); const ImVec2 avail_size = GetContentRegionAvail();
const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f); const ImVec2 actual_outer_size = CalcItemSize(outer_size, ImMax(avail_size.x, 1.0f), use_child_window ? ImMax(avail_size.y, 1.0f) : 0.0f);
@ -328,6 +334,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size) if (use_child_window && IsClippedEx(outer_rect, 0) && !outer_window_is_measuring_size)
{ {
ItemSize(outer_rect); ItemSize(outer_rect);
ItemAdd(outer_rect, id);
return false; return false;
} }
@ -337,7 +344,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Acquire storage for the table // Acquire storage for the table
ImGuiTable* table = g.Tables.GetOrAddByKey(id); ImGuiTable* table = g.Tables.GetOrAddByKey(id);
const ImGuiTableFlags table_last_flags = table->Flags;
// Acquire temporary buffers // Acquire temporary buffers
const int table_idx = g.Tables.GetIndex(table); const int table_idx = g.Tables.GetIndex(table);
@ -355,6 +361,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// Initialize // Initialize
const int previous_frame_active = table->LastFrameActive; const int previous_frame_active = table->LastFrameActive;
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1; const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
const ImGuiTableFlags previous_flags = table->Flags;
table->ID = id; table->ID = id;
table->Flags = flags; table->Flags = flags;
table->LastFrameActive = g.FrameCount; table->LastFrameActive = g.FrameCount;
@ -401,7 +408,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f)); SetNextWindowContentSize(ImVec2(override_content_size.x != FLT_MAX ? override_content_size.x : 0.0f, override_content_size.y != FLT_MAX ? override_content_size.y : 0.0f));
// Reset scroll if we are reactivating it // Reset scroll if we are reactivating it
if ((table_last_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0)
SetNextWindowScroll(ImVec2(0.0f, 0.0f)); SetNextWindowScroll(ImVec2(0.0f, 0.0f));
// Create scrolling region (without border and zero window padding) // Create scrolling region (without border and zero window padding)
@ -514,7 +521,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly. if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
inner_window->DC.CurrentTableIdx = table_idx; inner_window->DC.CurrentTableIdx = table_idx;
if ((table_last_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0) if ((previous_flags & ImGuiTableFlags_Reorderable) && (flags & ImGuiTableFlags_Reorderable) == 0)
table->IsResetDisplayOrderRequest = true; table->IsResetDisplayOrderRequest = true;
// Mark as used to avoid GC // Mark as used to avoid GC
@ -1462,7 +1469,10 @@ void ImGui::EndTable()
// CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414) // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414)
if (inner_window != outer_window) if (inner_window != outer_window)
{ {
short backup_nav_layers_active_mask = inner_window->DC.NavLayersActiveMask;
inner_window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main; // So empty table don't appear to navigate differently.
EndChild(); EndChild();
inner_window->DC.NavLayersActiveMask = backup_nav_layers_active_mask;
} }
else else
{ {
@ -2926,6 +2936,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
} }
// Write output // Write output
// May be able to move all SortSpecs data from table (48 bytes) to ImGuiTableTempData if we decide to write it back on every BeginTable()
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data; ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
if (dirty && sort_specs != NULL) if (dirty && sort_specs != NULL)
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@ -2986,7 +2997,7 @@ float ImGui::TableGetHeaderAngledMaxLabelWidth()
// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn(). // [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
// The intent is that advanced users willing to create customized headers would not need to use this helper // The intent is that advanced users willing to create customized headers would not need to use this helper
// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets. // and can create their own! For example: TableHeader() may be preceded by Checkbox() or other custom widgets.
// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this. // See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy. // This code is constructed to not make much use of internal functions, as it is intended to be a template to copy.
// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public. // FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.

Loading…
Cancel
Save