Skip to content

Commit

Permalink
Merge branch 'master' into docking
Browse files Browse the repository at this point in the history
  • Loading branch information
ocornut committed Mar 21, 2023
2 parents 5320a6e + d885094 commit ad44f58
Show file tree
Hide file tree
Showing 6 changed files with 798 additions and 69 deletions.
668 changes: 667 additions & 1 deletion docs/CHANGELOG.txt

Large diffs are not rendered by default.

103 changes: 62 additions & 41 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,9 +1385,9 @@ void ImGuiIO::ClearInputKeys()
MouseWheel = MouseWheelH = 0.0f;
}

static ImGuiInputEvent* FindLatestInputEvent(ImGuiInputEventType type, int arg = -1)
static ImGuiInputEvent* FindLatestInputEvent(ImGuiContext* ctx, ImGuiInputEventType type, int arg = -1)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *ctx;
for (int n = g.InputEventsQueue.Size - 1; n >= 0; n--)
{
ImGuiInputEvent* e = &g.InputEventsQueue[n];
Expand All @@ -1406,6 +1406,8 @@ static ImGuiInputEvent* FindLatestInputEvent(ImGuiInputEventType type, int arg =
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the key end-user would use to emit an 'A' character)
// - bool down: Is the key down? use false to signify a key release.
// - float analog_value: 0.0f..1.0f
// 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.
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); }
Expand All @@ -1414,7 +1416,7 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
return;
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::IsAliasKey(key)); // 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.
IM_ASSERT(key != ImGuiMod_Shortcut); // We could easily support the translation here but it seems saner to not accept it (TestEngine perform a translation itself)

// Verify that backend isn't mixing up using new io.AddKeyEvent() api and old io.KeysDown[] + io.KeyMap[] data.
Expand All @@ -1429,8 +1431,8 @@ void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
BackendUsingLegacyNavInputArray = false;

// Filter duplicate (in particular: key mods and gamepad analog values are commonly spammed)
const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_Key, (int)key);
const ImGuiKeyData* key_data = ImGui::GetKeyData(key);
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Key, (int)key);
const ImGuiKeyData* key_data = ImGui::GetKeyData(&g, key);
const bool latest_key_down = latest_event ? latest_event->Key.Down : key_data->Down;
const float latest_key_analog = latest_event ? latest_event->Key.AnalogValue : key_data->AnalogValue;
if (latest_key_down == down && latest_key_analog == analog_value)
Expand Down Expand Up @@ -1496,7 +1498,7 @@ void ImGuiIO::AddMousePosEvent(float x, float y)
ImVec2 pos((x > -FLT_MAX) ? ImFloorSigned(x) : x, (y > -FLT_MAX) ? ImFloorSigned(y) : y);

// Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_MousePos);
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MousePos);
const ImVec2 latest_pos = latest_event ? ImVec2(latest_event->MousePos.PosX, latest_event->MousePos.PosY) : g.IO.MousePos;
if (latest_pos.x == pos.x && latest_pos.y == pos.y)
return;
Expand All @@ -1518,7 +1520,7 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
return;

// Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(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];
if (latest_button_down == down)
return;
Expand Down Expand Up @@ -1551,14 +1553,14 @@ void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y)

void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(Ctx != NULL);
ImGuiContext& g = *Ctx;
IM_ASSERT(g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport);
if (!AppAcceptingEvents)
return;

// Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_MouseViewport);
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_MouseViewport);
const ImGuiID latest_viewport_id = latest_event ? latest_event->MouseViewport.HoveredViewportID : g.IO.MouseHoveredViewport;
if (latest_viewport_id == viewport_id)
return;
Expand All @@ -1576,7 +1578,7 @@ void ImGuiIO::AddFocusEvent(bool focused)
ImGuiContext& g = *Ctx;

// Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_Focus);
const ImGuiInputEvent* latest_event = FindLatestInputEvent(&g, ImGuiInputEventType_Focus);
const bool latest_focused = latest_event ? latest_event->AppFocused.Focused : !g.IO.AppFocusLost;
if (latest_focused == focused)
return;
Expand Down Expand Up @@ -3666,6 +3668,7 @@ void ImGui::Shutdown()
g.ClipboardHandlerData.clear();
g.MenusIdSubmittedThisFrame.clear();
g.InputTextState.ClearFreeMemory();
g.InputTextDeactivatedState.ClearFreeMemory();

g.SettingsWindows.clear();
g.SettingsHandlers.clear();
Expand Down Expand Up @@ -3844,13 +3847,23 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;

// While most behaved code would make an effort to not steal active id during window move/drag operations,
// we at least need to be resilient to it. Cancelling the move is rather aggressive and users of 'master' branch
// may prefer the weird ill-defined half working situation ('docking' did assert), so may need to rework that.
if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId)
// Clear previous active id
if (g.ActiveId != 0)
{
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() cancel MovingWindow\n");
g.MovingWindow = NULL;
// While most behaved code would make an effort to not steal active id during window move/drag operations,
// we at least need to be resilient to it. Canceling the move is rather aggressive and users of 'master' branch
// may prefer the weird ill-defined half working situation ('docking' did assert), so may need to rework that.
if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId)
{
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() cancel MovingWindow\n");
g.MovingWindow = NULL;
}

// This could be written in a more general way (e.g associate a hook to ActiveId),
// but since this is currently quite an exception we'll leave it as is.
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveId()
if (g.InputTextState.ID == g.ActiveId)
InputTextDeactivateHook(g.ActiveId);
}

// Set active id
Expand All @@ -3876,7 +3889,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (id)
{
g.ActiveIdIsAlive = id;
g.ActiveIdSource = (g.NavActivateId == id || g.NavJustMovedToId == id) ? (ImGuiInputSource)ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
g.ActiveIdSource = (g.NavActivateId == id || g.NavJustMovedToId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
IM_ASSERT(g.ActiveIdSource != ImGuiInputSource_None);
}

// Clear declaration of inputs claimed by the widget
Expand Down Expand Up @@ -3924,11 +3938,17 @@ void ImGui::MarkItemEdited(ImGuiID id)
// This marking is solely to be able to provide info for IsItemDeactivatedAfterEdit().
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
ImGuiContext& g = *GImGui;
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0 || g.DragDropActive);
IM_UNUSED(id); // Avoid unused variable warnings when asserts are compiled out.
if (g.ActiveId == id || g.ActiveId == 0)
{
g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true;
}

// We accept a MarkItemEdited() on drag and drop targets (see https://github.com/ocornut/imgui/issues/1875#issuecomment-978243343)
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id);

//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
g.ActiveIdHasBeenEditedThisFrame = true;
g.ActiveIdHasBeenEditedBefore = true;
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
}

Expand Down Expand Up @@ -5542,7 +5562,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b
FocusWindow(child_window);
NavInitWindow(child_window, false);
SetActiveID(id + 1, child_window); // Steal ActiveId with another arbitrary id so that key-press won't activate child item
g.ActiveIdSource = ImGuiInputSource_Nav;
g.ActiveIdSource = g.NavInputSource;
}
return ret;
}
Expand Down Expand Up @@ -8307,13 +8327,13 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
// - Shortcut() [Internal]
//-----------------------------------------------------------------------------

ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key)
ImGuiKeyData* ImGui::GetKeyData(ImGuiContext* ctx, ImGuiKey key)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *ctx;

// Special storage location for mods
if (key & ImGuiMod_Mask_)
key = ConvertSingleModFlagToKey(key);
key = ConvertSingleModFlagToKey(ctx, key);

#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_END);
Expand Down Expand Up @@ -8362,22 +8382,22 @@ IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames));

const char* ImGui::GetKeyName(ImGuiKey key)
{
ImGuiContext& g = *GImGui;
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
IM_ASSERT((IsNamedKey(key) || key == ImGuiKey_None) && "Support for user key indices was dropped in favor of ImGuiKey. Please update backend and user code.");
#else
if (IsLegacyKey(key))
{
ImGuiIO& io = GetIO();
if (io.KeyMap[key] == -1)
if (g.IO.KeyMap[key] == -1)
return "N/A";
IM_ASSERT(IsNamedKey((ImGuiKey)io.KeyMap[key]));
key = (ImGuiKey)io.KeyMap[key];
IM_ASSERT(IsNamedKey((ImGuiKey)g.IO.KeyMap[key]));
key = (ImGuiKey)g.IO.KeyMap[key];
}
#endif
if (key == ImGuiKey_None)
return "None";
if (key & ImGuiMod_Mask_)
key = ConvertSingleModFlagToKey(key);
key = ConvertSingleModFlagToKey(&g, key);
if (!IsNamedKey(key))
return "Unknown";

Expand Down Expand Up @@ -8472,7 +8492,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
// Apply routing to owner if there's no owner already (RoutingCurr == None at this point)
if (routing_entry->Mods == g.IO.KeyMods)
{
ImGuiKeyOwnerData* owner_data = ImGui::GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
owner_data->OwnerCurr = routing_entry->RoutingCurr;
}
Expand Down Expand Up @@ -8509,7 +8529,7 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
if (key == ImGuiKey_None)
key = ConvertSingleModFlagToKey(mods);
key = ConvertSingleModFlagToKey(&g, mods);
IM_ASSERT(IsNamedKey(key));

// Get (in the majority of case, the linked list will have one element so this should be 2 reads.
Expand Down Expand Up @@ -9242,7 +9262,7 @@ void ImGui::SetNextFrameWantCaptureMouse(bool want_capture_mouse)
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
static const char* GetInputSourceName(ImGuiInputSource source)
{
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Nav", "Clipboard" };
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", "Clipboard" };
IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && source >= 0 && source < ImGuiInputSource_COUNT);
return input_source_names[source];
}
Expand Down Expand Up @@ -9389,7 +9409,7 @@ ImGuiID ImGui::GetKeyOwner(ImGuiKey key)
return ImGuiKeyOwner_None;

ImGuiContext& g = *GImGui;
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
ImGuiID owner_id = owner_data->OwnerCurr;

if (g.ActiveIdUsingAllKeyboardKeys && owner_id != g.ActiveId && owner_id != ImGuiKeyOwner_Any)
Expand All @@ -9413,7 +9433,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
if (key >= ImGuiKey_Keyboard_BEGIN && key < ImGuiKey_Keyboard_END)
return false;

ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_id == ImGuiKeyOwner_Any)
return (owner_data->LockThisFrame == false);

Expand Down Expand Up @@ -9441,7 +9461,8 @@ void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
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((flags & ~ImGuiInputFlags_SupportedBySetKeyOwner) == 0); // Passing flags not supported by this function!

ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiContext& g = *GImGui;
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;

// We cannot lock by default as it would likely break lots of legacy code.
Expand Down Expand Up @@ -9490,7 +9511,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
// Special storage location for mods
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
if (key == ImGuiKey_None)
key = ConvertSingleModFlagToKey(mods);
key = ConvertSingleModFlagToKey(&g, mods);

if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateMask_))))
return false;
Expand Down Expand Up @@ -9941,7 +9962,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
// return false;
const bool is_rect_visible = bb.Overlaps(window->ClipRect);
if (!is_rect_visible)
if (id == 0 || (id != g.ActiveId && id != g.NavId))
if (id == 0 || (id != g.ActiveId && id != g.ActiveIdPreviousFrame && id != g.NavId))
if (!g.LogEnabled)
return false;

Expand Down Expand Up @@ -11232,7 +11253,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
if (g.LastItemData.ID == id)
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);

if (g.ActiveIdSource == ImGuiInputSource_Nav)
if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
g.NavDisableMouseHover = true;
else
g.NavDisableHighlight = true;
Expand Down Expand Up @@ -19290,7 +19311,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
{
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(&g, key);
if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
continue;
Text("%s: 0x%08X%s", GetKeyName(key), owner_data->OwnerCurr,
Expand Down
2 changes: 1 addition & 1 deletion imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345')
#define IMGUI_VERSION "1.89.5 WIP"
#define IMGUI_VERSION_NUM 18941
#define IMGUI_VERSION_NUM 18943
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch
Expand Down
4 changes: 1 addition & 3 deletions imgui_demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5786,8 +5786,6 @@ static void ShowDemoWindowColumns()
ImGui::TreePop();
}

namespace ImGui { extern ImGuiKeyData* GetKeyData(ImGuiKey key); }

static void ShowDemoWindowInputs()
{
IMGUI_DEMO_MARKER("Inputs & Focus");
Expand Down Expand Up @@ -5822,7 +5820,7 @@ static void ShowDemoWindowInputs()
struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
ImGuiKey start_key = (ImGuiKey)0;
#endif
ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); ImGui::SameLine(); ImGui::Text("(%.02f)", ImGui::GetKeyData(key)->DownDuration); }
ImGui::Text("Keys down:"); for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("Chars queue:"); for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine(); ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.

Expand Down
Loading

0 comments on commit ad44f58

Please sign in to comment.