|
@@ -4116,6 +4116,45 @@ static void UpdateAliasKey(ImGuiKey key, bool v, float analog_value)
|
|
key_data->AnalogValue = analog_value;
|
|
key_data->AnalogValue = analog_value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Rewrite routing data buffers to strip old entries + sort by key to make queries not touch scattered data.
|
|
|
|
+// Entries D,A,B,B,A,C,B --> A,A,B,B,B,C,D
|
|
|
|
+// Index A:1 B:2 C:5 D:0 --> A:0 B:2 C:5 D:6
|
|
|
|
+// See 'Metrics->Key Owners & Shortcut Routing' to visualize the result of that operation.
|
|
|
|
+static void UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ rt->EntriesNext.resize(0);
|
|
|
|
+ for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
|
|
|
|
+ {
|
|
|
|
+ const int new_routing_start_idx = rt->EntriesNext.Size;
|
|
|
|
+ ImGuiKeyRoutingData* routing_entry;
|
|
|
|
+ for (int old_routing_idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; old_routing_idx != -1; old_routing_idx = routing_entry->NextEntryIndex)
|
|
|
|
+ {
|
|
|
|
+ routing_entry = &rt->Entries[old_routing_idx];
|
|
|
|
+ routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry
|
|
|
|
+ routing_entry->RoutingNext = ImGuiKeyOwner_None;
|
|
|
|
+ routing_entry->RoutingNextScore = 255;
|
|
|
|
+ if (routing_entry->RoutingCurr == ImGuiKeyOwner_None)
|
|
|
|
+ continue;
|
|
|
|
+ rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer
|
|
|
|
+
|
|
|
|
+ // 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);
|
|
|
|
+ if (owner_data->OwnerCurr == ImGuiKeyOwner_None)
|
|
|
|
+ owner_data->OwnerCurr = routing_entry->RoutingCurr;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Rewrite linked-list
|
|
|
|
+ rt->Index[key - ImGuiKey_NamedKey_BEGIN] = (ImGuiKeyRoutingIndex)(new_routing_start_idx < rt->EntriesNext.Size ? new_routing_start_idx : -1);
|
|
|
|
+ for (int n = new_routing_start_idx; n < rt->EntriesNext.Size; n++)
|
|
|
|
+ rt->EntriesNext[n].NextEntryIndex = (ImGuiKeyRoutingIndex)((n + 1 < rt->EntriesNext.Size) ? n + 1 : -1);
|
|
|
|
+ }
|
|
|
|
+ rt->Entries.swap(rt->EntriesNext); // Swap new and old indexes
|
|
|
|
+}
|
|
|
|
+
|
|
// [Internal] Do not use directly (should read io.KeyMods instead)
|
|
// [Internal] Do not use directly (should read io.KeyMods instead)
|
|
static ImGuiKeyChord GetMergedModsFromBools()
|
|
static ImGuiKeyChord GetMergedModsFromBools()
|
|
{
|
|
{
|
|
@@ -4234,6 +4273,8 @@ static void ImGui::UpdateKeyboardInputs()
|
|
owner_data->OwnerNext = ImGuiKeyOwner_None;
|
|
owner_data->OwnerNext = ImGuiKeyOwner_None;
|
|
owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down; // Clear LockUntilRelease when key is not Down anymore
|
|
owner_data->LockThisFrame = owner_data->LockUntilRelease = owner_data->LockUntilRelease && key_data->Down; // Clear LockUntilRelease when key is not Down anymore
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ UpdateKeyRoutingTable(&g.KeysRoutingTable);
|
|
}
|
|
}
|
|
|
|
|
|
static void ImGui::UpdateMouseInputs()
|
|
static void ImGui::UpdateMouseInputs()
|
|
@@ -4794,6 +4835,9 @@ void ImGui::Shutdown()
|
|
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
|
|
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
|
|
g.MovingWindow = NULL;
|
|
g.MovingWindow = NULL;
|
|
|
|
+
|
|
|
|
+ g.KeysRoutingTable.Clear();
|
|
|
|
+
|
|
g.ColorStack.clear();
|
|
g.ColorStack.clear();
|
|
g.StyleVarStack.clear();
|
|
g.StyleVarStack.clear();
|
|
g.FontStack.clear();
|
|
g.FontStack.clear();
|
|
@@ -7955,6 +7999,128 @@ ImVec2 ImGui::GetKeyVector2d(ImGuiKey key_left, ImGuiKey key_right, ImGuiKey key
|
|
GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
|
|
GetKeyData(key_down)->AnalogValue - GetKeyData(key_up)->AnalogValue);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// owner_id may be None/Any, but routing_id needs to be always be set, so we default to GetID("") aka current ID stack.
|
|
|
|
+static inline ImGuiID GetRoutingIdFromOwnerId(ImGuiID owner_id)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ return (owner_id != ImGuiKeyOwner_None && owner_id != ImGuiKeyOwner_Any) ? owner_id : g.CurrentWindow->IDStack.back();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
|
|
|
|
+{
|
|
|
|
+ // Majority of shortcuts will be Key + any number of Mods
|
|
|
|
+ // We accept _Single_ mod with ImGuiKey_None.
|
|
|
|
+ // - Shortcut(ImGuiKey_S | ImGuiMod_Ctrl); // Legal
|
|
|
|
+ // - Shortcut(ImGuiKey_S | ImGuiMod_Ctrl | ImGuiMod_Shift); // Legal
|
|
|
|
+ // - Shortcut(ImGuiMod_Ctrl); // Legal
|
|
|
|
+ // - Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift); // Not legal
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable;
|
|
|
|
+ ImGuiKeyRoutingData* routing_data;
|
|
|
|
+ ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
|
|
+ ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
|
|
+ if (key == ImGuiKey_None)
|
|
|
|
+ key = ConvertSingleModFlagToKey(mods);
|
|
|
|
+ IM_ASSERT(IsNamedKey(key));
|
|
|
|
+
|
|
|
|
+ // Get (in the majority of case, the linked list will have one element so this should be 2 reads.
|
|
|
|
+ // Subsequent elements will be contiguous in memory as list is sorted/rebuilt in NewFrame).
|
|
|
|
+ for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; idx = routing_data->NextEntryIndex)
|
|
|
|
+ {
|
|
|
|
+ routing_data = &rt->Entries[idx];
|
|
|
|
+ if (routing_data->Mods == mods)
|
|
|
|
+ return routing_data;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Add
|
|
|
|
+ ImGuiKeyRoutingIndex idx = (ImGuiKeyRoutingIndex)rt->Entries.Size;
|
|
|
|
+ rt->Entries.push_back(ImGuiKeyRoutingData());
|
|
|
|
+ routing_data = &rt->Entries[idx];
|
|
|
|
+ routing_data->Mods = (ImU16)mods;
|
|
|
|
+ routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; // Setup linked list
|
|
|
|
+ rt->Index[key - ImGuiKey_NamedKey_BEGIN] = idx;
|
|
|
|
+ return routing_data;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Request a desired route for an input chord (key + mods).
|
|
|
|
+// Return true if the route is available this frame.
|
|
|
|
+// - Routes and key ownership are attributed at the beginning of next frame based on best score and mod state.
|
|
|
|
+// (Conceptually this does a "Submit for next frame" + "Test for current frame".
|
|
|
|
+// As such, it could be called TrySetXXX or SubmitXXX, or the Submit and Test operations should be separate.)
|
|
|
|
+// - 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_None': allows disabling/locking a shortcut.
|
|
|
|
+bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags, ImGuiWindow* location)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ IM_ASSERT(owner_id != ImGuiKeyOwner_None);
|
|
|
|
+
|
|
|
|
+ // Calculate our score
|
|
|
|
+ int score = 255;
|
|
|
|
+ bool always_set_next_route = false;
|
|
|
|
+ if (flags & ImGuiInputFlags_RouteFocused)
|
|
|
|
+ {
|
|
|
|
+ if (location == NULL)
|
|
|
|
+ location = g.CurrentWindow;
|
|
|
|
+ ImGuiWindow* focused = g.NavWindow;
|
|
|
|
+
|
|
|
|
+ if (g.ActiveId != 0 && g.ActiveId == owner_id)
|
|
|
|
+ {
|
|
|
|
+ // ActiveID gets top priority (0)
|
|
|
|
+ // (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it)
|
|
|
|
+ score = 0;
|
|
|
|
+ }
|
|
|
|
+ else if (focused != NULL && focused->RootWindow == location->RootWindow) // Early out
|
|
|
|
+ {
|
|
|
|
+ // Score based on distance to focused window (lower is better)
|
|
|
|
+ // Assuming both windows are submitting a routing request,
|
|
|
|
+ // - When WindowA...... is focused -> WindowA scores 1 (best), WindowA/ChildB scores 255 (no match)
|
|
|
|
+ // - When Window/ChildB is focused -> WindowA scores 2, WindowA/ChildB scores 1 (best)
|
|
|
|
+ // Assuming only WindowA is submitting a routing request,
|
|
|
|
+ // - When Window/ChildB is focused -> WindowA scores 2 (best), WindowA/ChildB doesn't have a scoe.
|
|
|
|
+ for (int next_score = 1; focused != NULL; next_score++)
|
|
|
|
+ {
|
|
|
|
+ if (focused == location)
|
|
|
|
+ {
|
|
|
|
+ score = (ImU8)next_score;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ focused = (focused->RootWindow != focused) ? focused->ParentWindow : NULL; // FIXME: This could be later abstracted as a focus path
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (score == 255)
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ score = 0;
|
|
|
|
+ always_set_next_route = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Submit routing for NEXT frame (assuming score is sufficient)
|
|
|
|
+ // FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <).
|
|
|
|
+ ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
|
|
|
|
+ const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id); // FIXME: Location
|
|
|
|
+ //const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore);
|
|
|
|
+ if (score < routing_data->RoutingNextScore || always_set_next_route)
|
|
|
|
+ {
|
|
|
|
+ routing_data->RoutingNext = routing_id;
|
|
|
|
+ routing_data->RoutingNextScore = (ImU8)score;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Return routing state for CURRENT frame
|
|
|
|
+ return routing_data->RoutingCurr == routing_id;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// Currently unused by core (but used by tests)
|
|
|
|
+// Note: this cannot be turned into GetShortcutRouting() because we do the owner_id->routing_id translation, name would be more misleading.
|
|
|
|
+bool ImGui::TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id)
|
|
|
|
+{
|
|
|
|
+ const ImGuiID routing_id = GetRoutingIdFromOwnerId(owner_id);
|
|
|
|
+ ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
|
|
|
|
+ return routing_data->RoutingCurr == routing_id;
|
|
|
|
+}
|
|
|
|
+
|
|
// Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..511: they are legacy native keycodes.
|
|
// Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..511: they are legacy native keycodes.
|
|
// Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown(ImGuiKey_A) (>= 1.87)
|
|
// Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown(ImGuiKey_A) (>= 1.87)
|
|
bool ImGui::IsKeyDown(ImGuiKey key)
|
|
bool ImGui::IsKeyDown(ImGuiKey key)
|
|
@@ -7986,6 +8152,7 @@ bool ImGui::IsKeyPressed(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
const float t = key_data->DownDuration;
|
|
const float t = key_data->DownDuration;
|
|
if (t < 0.0f)
|
|
if (t < 0.0f)
|
|
return false;
|
|
return false;
|
|
|
|
+ IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function!
|
|
|
|
|
|
bool pressed = (t == 0.0f);
|
|
bool pressed = (t == 0.0f);
|
|
if (!pressed && ((flags & ImGuiInputFlags_Repeat) != 0))
|
|
if (!pressed && ((flags & ImGuiInputFlags_Repeat) != 0))
|
|
@@ -8044,6 +8211,7 @@ bool ImGui::IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInput
|
|
const float t = g.IO.MouseDownDuration[button];
|
|
const float t = g.IO.MouseDownDuration[button];
|
|
if (t < 0.0f)
|
|
if (t < 0.0f)
|
|
return false;
|
|
return false;
|
|
|
|
+ IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByIsKeyPressed) == 0); // Passing flags not supported by this function!
|
|
|
|
|
|
const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
|
|
const bool repeat = (flags & ImGuiInputFlags_Repeat) != 0;
|
|
const bool pressed = (t == 0.0f) || (repeat && t > g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0);
|
|
const bool pressed = (t == 0.0f) || (repeat && t > g.IO.KeyRepeatDelay && CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0);
|
|
@@ -8392,6 +8560,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)
|
|
{
|
|
{
|
|
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(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);
|
|
ImGuiKeyOwnerData* owner_data = GetKeyOwnerData(key);
|
|
owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
|
|
owner_data->OwnerCurr = owner_data->OwnerNext = owner_id;
|
|
@@ -8417,7 +8586,10 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
|
if ((flags & ImGuiInputFlags_CondMask_) == 0)
|
|
if ((flags & ImGuiInputFlags_CondMask_) == 0)
|
|
flags |= ImGuiInputFlags_CondDefault_;
|
|
flags |= ImGuiInputFlags_CondDefault_;
|
|
if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive)))
|
|
if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive)))
|
|
- SetKeyOwner(key, id, flags);
|
|
|
|
|
|
+ {
|
|
|
|
+ IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function!
|
|
|
|
+ SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// - Need to decide how to handle shortcut translations for Non-Mac <> Mac
|
|
// - Need to decide how to handle shortcut translations for Non-Mac <> Mac
|
|
@@ -8425,6 +8597,11 @@ void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
|
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags flags)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
+
|
|
|
|
+ if (flags & ImGuiInputFlags_RouteFocused)
|
|
|
|
+ if (!SetShortcutRouting(key_chord, owner_id, ImGuiInputFlags_RouteFocused, g.CurrentWindow))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_);
|
|
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
ImGuiKey mods = (ImGuiKey)(key_chord & ImGuiMod_Mask_);
|
|
if (g.IO.KeyMods != mods)
|
|
if (g.IO.KeyMods != mods)
|
|
@@ -8436,6 +8613,8 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiInputFlags
|
|
|
|
|
|
if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_))))
|
|
if (!IsKeyPressed(key, owner_id, (flags & (ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_))))
|
|
return false;
|
|
return false;
|
|
|
|
+ IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function!
|
|
|
|
+
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -13080,7 +13259,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
TreePop();
|
|
TreePop();
|
|
}
|
|
}
|
|
|
|
|
|
- if (TreeNode("Key Owners"))
|
|
|
|
|
|
+ if (TreeNode("Key Owners & Shortcut Routing"))
|
|
{
|
|
{
|
|
TextUnformatted("Key Owners:");
|
|
TextUnformatted("Key Owners:");
|
|
if (BeginListBox("##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8)))
|
|
if (BeginListBox("##owners", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8)))
|
|
@@ -13096,6 +13275,24 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
}
|
|
}
|
|
EndListBox();
|
|
EndListBox();
|
|
}
|
|
}
|
|
|
|
+ TextUnformatted("Shortcut Routing:");
|
|
|
|
+ if (BeginListBox("##routes", ImVec2(-FLT_MIN, GetTextLineHeightWithSpacing() * 8)))
|
|
|
|
+ {
|
|
|
|
+ for (ImGuiKey key = ImGuiKey_NamedKey_BEGIN; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1))
|
|
|
|
+ {
|
|
|
|
+ ImGuiKeyRoutingTable* rt = &g.KeysRoutingTable;
|
|
|
|
+ for (ImGuiKeyRoutingIndex idx = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; idx != -1; )
|
|
|
|
+ {
|
|
|
|
+ char key_chord_name[64];
|
|
|
|
+ ImGuiKeyRoutingData* routing_data = &rt->Entries[idx];
|
|
|
|
+ GetKeyChordName(key | routing_data->Mods, key_chord_name, IM_ARRAYSIZE(key_chord_name));
|
|
|
|
+ Text("%s: 0x%08X", key_chord_name, routing_data->RoutingCurr);
|
|
|
|
+ DebugLocateItemOnHover(routing_data->RoutingCurr);
|
|
|
|
+ idx = routing_data->NextEntryIndex;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ EndListBox();
|
|
|
|
+ }
|
|
Text("(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask);
|
|
Text("(ActiveIdUsing: AllKeyboardKeys: %d, NavDirMask: 0x%X)", g.ActiveIdUsingAllKeyboardKeys, g.ActiveIdUsingNavDirMask);
|
|
TreePop();
|
|
TreePop();
|
|
}
|
|
}
|