From 7c71e66370d633419f0a3f233eab4e5735657f67 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 May 2024 17:33:16 +0200 Subject: [PATCH 01/10] Shortcuts, SetShortcutRouting: move ImGuiInputFlags_RouteFromRootWindow evaluation to SetShortcutRouting() for now. (#456) --- imgui.cpp | 16 ++++++++-------- imgui_internal.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a719d463..8e7a677d1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8659,7 +8659,7 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) // - 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.) -bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id, ImGuiID focus_scope_id) +bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id) { ImGuiContext& g = *GImGui; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used @@ -8708,6 +8708,11 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I } } + // Where do we evaluate route for? + ImGuiID focus_scope_id = g.CurrentFocusScopeId; + if (flags & ImGuiInputFlags_RouteFromRootWindow) + focus_scope_id = g.CurrentWindow->RootWindow->ID; // See PushFocusScope() call in Begin() + const int score = CalcRoutingScore(focus_scope_id, owner_id, flags); IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score); if (score == 255) @@ -9715,7 +9720,7 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags) bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id) { - ImGuiContext& g = *GImGui; + //ImGuiContext& g = *GImGui; //IMGUI_DEBUG_LOG("Shortcut(%s, flags=%X, owner_id=0x%08X)\n", GetKeyChordName(key_chord, g.TempBuffer.Data, g.TempBuffer.Size), flags, owner_id); // When using (owner_id == 0/Any): SetShortcutRouting() will use CurrentFocusScopeId and filter with this, so IsKeyPressed() is fine with he 0/Any. @@ -9727,13 +9732,8 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own if (owner_id == ImGuiKeyOwner_Any || owner_id == ImGuiKeyOwner_NoOwner) owner_id = GetRoutingIdFromOwnerId(owner_id); - // Where do we evaluate route for? - ImGuiID focus_scope_id = g.CurrentFocusScopeId; - if (flags & ImGuiInputFlags_RouteFromRootWindow) - focus_scope_id = g.CurrentWindow->RootWindow->ID; // See PushFocusScope() call in Begin() - // Submit route - if (!SetShortcutRouting(key_chord, flags, owner_id, focus_scope_id)) + if (!SetShortcutRouting(key_chord, flags, owner_id)) return false; // Default repeat behavior for Shortcut() diff --git a/imgui_internal.h b/imgui_internal.h index 37bbd7843..d6020f8a7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3265,7 +3265,7 @@ namespace ImGui // - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute() // e.g. if you have a tool window associated to a document, and you want document shortcuts to run when the tool is focused. IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id); - IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id, ImGuiID focus_scope_id); // routing policy and owner_id needs to be explicit and cannot be 0 + IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id); // routing policy and owner_id needs to be explicit and cannot be 0 IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id); IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord); From 1002cfa6d2dc8cbf807bc6b9a0bcd2d54d8e7350 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 May 2024 18:07:43 +0200 Subject: [PATCH 02/10] Demo, Shortcut(): amend Shortcuts demo. (#456) --- imgui_demo.cpp | 55 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index cc8192150..a1a74d391 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6184,12 +6184,14 @@ static void ShowDemoWindowInputs() // Display inputs submitted to ImGuiIO IMGUI_DEMO_MARKER("Inputs & Focus/Inputs"); ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode("Inputs")) + bool inputs_opened = ImGui::TreeNode("Inputs"); + ImGui::SameLine(); + HelpMarker( + "This is a simplified view. See more detailed input state:\n" + "- in 'Tools->Metrics/Debugger->Inputs'.\n" + "- in 'Tools->Debug Log->IO'."); + if (inputs_opened) { - HelpMarker( - "This is a simplified view. See more detailed input state:\n" - "- in 'Tools->Metrics/Debugger->Inputs'.\n" - "- in 'Tools->Debug Log->IO'."); if (ImGui::IsMousePosValid()) ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); else @@ -6220,15 +6222,17 @@ static void ShowDemoWindowInputs() // Display ImGuiIO output flags IMGUI_DEMO_MARKER("Inputs & Focus/Outputs"); ImGui::SetNextItemOpen(true, ImGuiCond_Once); - if (ImGui::TreeNode("Outputs")) + bool outputs_opened = ImGui::TreeNode("Outputs"); + ImGui::SameLine(); + HelpMarker( + "The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui " + "to instruct your application of how to route inputs. Typically, when a value is true, it means " + "Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n" + "The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, " + "and underlying application should ignore mouse inputs (in practice there are many and more subtle " + "rules leading to how those flags are set)."); + if (outputs_opened) { - HelpMarker( - "The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui " - "to instruct your application of how to route inputs. Typically, when a value is true, it means " - "Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n" - "The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, " - "and underlying application should ignore mouse inputs (in practice there are many and more subtle " - "rules leading to how those flags are set)."); ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose); ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard); @@ -6275,14 +6279,6 @@ static void ShowDemoWindowInputs() IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts"); if (ImGui::TreeNode("Shortcuts")) { - ImGui::SeparatorText("Using SetNextItemShortcut()"); - ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S); - ImGui::Button("Save"); - ImGui::SetItemTooltip("Ctrl+S"); // FIXME: Tooltip could be automatically submitted by SetNextItemShortcut - - ImGui::SeparatorText("Using Shortcut()"); - const float line_height = ImGui::GetTextLineHeightWithSpacing(); - const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A; static ImGuiInputFlags other_flags = ImGuiInputFlags_Repeat; static ImGuiInputFlags routing_flags = ImGuiInputFlags_RouteFocused; ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &other_flags, ImGuiInputFlags_Repeat); @@ -6294,8 +6290,24 @@ static void ShowDemoWindowInputs() ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &other_flags, ImGuiInputFlags_RouteUnlessBgFocused); const ImGuiInputFlags flags = other_flags | routing_flags; // Merged flags + ImGui::SeparatorText("Using SetNextItemShortcut()"); + ImGui::Text("Ctrl+S"); + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, flags | ImGuiInputFlags_Tooltip); + ImGui::Button("Save"); + ImGui::Text("Alt+F"); + ImGui::SetNextItemShortcut(ImGuiMod_Alt | ImGuiKey_F, flags | ImGuiInputFlags_Tooltip); + static float f = 0.5f; + ImGui::SliderFloat("Factor", &f, 0.0f, 1.0f); + + ImGui::SeparatorText("Using Shortcut()"); + const float line_height = ImGui::GetTextLineHeightWithSpacing(); + const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A; + + ImGui::Text("Ctrl+A"); ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "..."); + ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f)); + ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true); ImGui::Text("Press CTRL+A and see who receives it!"); ImGui::Separator(); @@ -6338,6 +6350,7 @@ static void ShowDemoWindowInputs() ImGui::EndPopup(); } ImGui::EndChild(); + ImGui::PopStyleColor(); ImGui::TreePop(); } From c150ad50c46b30e80b7c667c3a88b9d0616269d9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 May 2024 18:14:16 +0200 Subject: [PATCH 03/10] Shortcuts: claim mods ownership once pressed. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) --- imgui.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 8e7a677d1..76a506d6d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9743,6 +9743,10 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own if (!IsKeyChordPressed(key_chord, flags, owner_id)) return false; + + // Claim mods during the press + SetKeyOwnersForKeyChord(key_chord & ImGuiMod_Mask_, owner_id); + IM_ASSERT((flags & ~ImGuiInputFlags_SupportedByShortcut) == 0); // Passing flags not supported by this function! return true; } From 374b9a7fb437956ad0435ce3d4082997ecb1af19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 23 May 2024 21:15:01 +0200 Subject: [PATCH 04/10] Demo: Documents: refactor + add Renaming option. (#7233) --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 181 +++++++++++++++++++++++++++------------------ 2 files changed, 108 insertions(+), 74 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0a3263e6f..5871a4f1b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -89,6 +89,7 @@ Other changes: 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] - Demo: Added "Inputs & Focus -> Shortcuts" section. (#456, #2637) +- Demo: Documents: Added shortcuts and renaming tabs/documents. (#7233) - Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen locking without burning resources by running unthrottled code. (#2496, #3907, #6308, #7615) - Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a1a74d391..5d6148c42 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8422,51 +8422,85 @@ static void ShowExampleAppCustomRendering(bool* p_open) // Simplified structure to mimic a Document model struct MyDocument { - const char* Name; // Document title + char Name[32]; // Document title + int UID; // Unique ID (necessary as we can change title) bool Open; // Set when open (we keep an array of all available documents to simplify demo code!) bool OpenPrev; // Copy of Open from last update. bool Dirty; // Set when the document has been modified - bool WantClose; // Set when the document ImVec4 Color; // An arbitrary variable associated to the document - MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)) + MyDocument(int uid, const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f)) { - Name = name; + UID = uid; + snprintf(Name, sizeof(Name), "%s", name); Open = OpenPrev = open; Dirty = false; - WantClose = false; Color = color; } void DoOpen() { Open = true; } - void DoQueueClose() { WantClose = true; } void DoForceClose() { Open = false; Dirty = false; } void DoSave() { Dirty = false; } +}; + +struct ExampleAppDocuments +{ + ImVector Documents; + ImVector CloseQueue; + MyDocument* RenamingDoc = NULL; + bool RenamingStarted = false; + + ExampleAppDocuments() + { + Documents.push_back(MyDocument(0, "Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f))); + Documents.push_back(MyDocument(1, "Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f))); + Documents.push_back(MyDocument(2, "Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f))); + Documents.push_back(MyDocument(3, "Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f))); + Documents.push_back(MyDocument(4, "A Rather Long Title", false, ImVec4(0.4f, 0.8f, 0.8f, 1.0f))); + Documents.push_back(MyDocument(5, "Some Document", false, ImVec4(0.8f, 0.8f, 1.0f, 1.0f))); + } + + // As we allow to change document name, we append a never-changing document ID so tabs are stable + void GetTabName(MyDocument* doc, char* out_buf, size_t out_buf_size) + { + snprintf(out_buf, out_buf_size, "%s###doc%d", doc->Name, doc->UID); + } // Display placeholder contents for the Document - static void DisplayContents(MyDocument* doc) + void DisplayDocContents(MyDocument* doc) { ImGui::PushID(doc); ImGui::Text("Document \"%s\"", doc->Name); ImGui::PushStyleColor(ImGuiCol_Text, doc->Color); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."); ImGui::PopStyleColor(); + + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip); + if (ImGui::Button("Rename..")) + { + RenamingDoc = doc; + RenamingStarted = true; + } + ImGui::SameLine(); + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_M, ImGuiInputFlags_Tooltip); if (ImGui::Button("Modify")) doc->Dirty = true; + ImGui::SameLine(); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, ImGuiInputFlags_Tooltip); if (ImGui::Button("Save")) doc->DoSave(); + ImGui::SameLine(); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_W, ImGuiInputFlags_Tooltip); if (ImGui::Button("Close")) - doc->DoQueueClose(); + CloseQueue.push_back(doc); ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior. ImGui::PopID(); } // Display context menu for the Document - static void DisplayContextMenu(MyDocument* doc) + void DisplayDocContextMenu(MyDocument* doc) { if (!ImGui::BeginPopupContextItem()) return; @@ -8475,45 +8509,32 @@ struct MyDocument sprintf(buf, "Save %s", doc->Name); if (ImGui::MenuItem(buf, "Ctrl+S", false, doc->Open)) doc->DoSave(); + if (ImGui::MenuItem("Rename...", "Ctrl+R", false, doc->Open)) + RenamingDoc = doc; if (ImGui::MenuItem("Close", "Ctrl+W", false, doc->Open)) - doc->DoQueueClose(); + CloseQueue.push_back(doc); ImGui::EndPopup(); } -}; -struct ExampleAppDocuments -{ - ImVector Documents; - - ExampleAppDocuments() + // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface. + // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, + // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for + // the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has + // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively + // give the impression of a flicker for one frame. + // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch. + // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag. + void NotifyOfDocumentsClosedElsewhere() { - Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f))); - Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f))); - Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f))); - Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f))); - Documents.push_back(MyDocument("A Rather Long Title", false)); - Documents.push_back(MyDocument("Some Document", false)); + for (MyDocument& doc : Documents) + { + if (!doc.Open && doc.OpenPrev) + ImGui::SetTabItemClosed(doc.Name); + doc.OpenPrev = doc.Open; + } } }; -// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface. -// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, -// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for -// the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has -// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively -// give the impression of a flicker for one frame. -// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch. -// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag. -static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app) -{ - for (MyDocument& doc : app.Documents) - { - if (!doc.Open && doc.OpenPrev) - ImGui::SetTabItemClosed(doc.Name); - doc.OpenPrev = doc.Open; - } -} - void ShowExampleAppDocuments(bool* p_open) { static ExampleAppDocuments app; @@ -8547,7 +8568,7 @@ void ShowExampleAppDocuments(bool* p_open) } if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0)) for (MyDocument& doc : app.Documents) - doc.DoQueueClose(); + app.CloseQueue.push_back(&doc); if (ImGui::MenuItem("Exit") && p_open) *p_open = false; ImGui::EndMenu(); @@ -8586,7 +8607,7 @@ void ShowExampleAppDocuments(bool* p_open) if (ImGui::BeginTabBar("##tabs", tab_bar_flags)) { if (opt_reorderable) - NotifyOfDocumentsClosedElsewhere(app); + app.NotifyOfDocumentsClosedElsewhere(); // [DEBUG] Stress tests //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on. @@ -8598,20 +8619,23 @@ void ShowExampleAppDocuments(bool* p_open) if (!doc.Open) continue; + // As we allow to change document name, we append a never-changing document id so tabs are stable + char doc_name_buf[64]; + app.GetTabName(&doc, doc_name_buf, sizeof(doc_name_buf)); ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0); - bool visible = ImGui::BeginTabItem(doc.Name, &doc.Open, tab_flags); + bool visible = ImGui::BeginTabItem(doc_name_buf, &doc.Open, tab_flags); // Cancel attempt to close when unsaved add to save queue so we can display a popup. if (!doc.Open && doc.Dirty) { doc.Open = true; - doc.DoQueueClose(); + app.CloseQueue.push_back(&doc); } - MyDocument::DisplayContextMenu(&doc); + app.DisplayDocContextMenu(&doc); if (visible) { - MyDocument::DisplayContents(&doc); + app.DisplayDocContents(&doc); ImGui::EndTabItem(); } } @@ -8620,33 +8644,44 @@ void ShowExampleAppDocuments(bool* p_open) } } - // Update closing queue - static ImVector close_queue; - if (close_queue.empty()) + // Display renaming UI + if (app.RenamingDoc != NULL) { - // Close queue is locked once we started a popup - for (MyDocument& doc : app.Documents) - if (doc.WantClose) + if (app.RenamingStarted) + ImGui::OpenPopup("Rename"); + if (ImGui::BeginPopup("Rename")) + { + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30); + if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue)) { - doc.WantClose = false; - close_queue.push_back(&doc); + ImGui::CloseCurrentPopup(); + app.RenamingDoc = NULL; } + if (app.RenamingStarted) + ImGui::SetKeyboardFocusHere(-1); + ImGui::EndPopup(); + } + else + { + app.RenamingDoc = NULL; + } + app.RenamingStarted = false; } // Display closing confirmation UI - if (!close_queue.empty()) + if (!app.CloseQueue.empty()) { int close_queue_unsaved_documents = 0; - for (int n = 0; n < close_queue.Size; n++) - if (close_queue[n]->Dirty) + for (int n = 0; n < app.CloseQueue.Size; n++) + if (app.CloseQueue[n]->Dirty) close_queue_unsaved_documents++; if (close_queue_unsaved_documents == 0) { // Close documents when all are unsaved - for (int n = 0; n < close_queue.Size; n++) - close_queue[n]->DoForceClose(); - close_queue.clear(); + for (int n = 0; n < app.CloseQueue.Size; n++) + app.CloseQueue[n]->DoForceClose(); + app.CloseQueue.clear(); } else { @@ -8657,37 +8692,35 @@ void ShowExampleAppDocuments(bool* p_open) ImGui::Text("Save change to the following items?"); float item_height = ImGui::GetTextLineHeightWithSpacing(); if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle)) - { - for (int n = 0; n < close_queue.Size; n++) - if (close_queue[n]->Dirty) - ImGui::Text("%s", close_queue[n]->Name); - } + for (MyDocument* doc : app.CloseQueue) + if (doc->Dirty) + ImGui::Text("%s", doc->Name); ImGui::EndChild(); ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f); if (ImGui::Button("Yes", button_size)) { - for (int n = 0; n < close_queue.Size; n++) + for (MyDocument* doc : app.CloseQueue) { - if (close_queue[n]->Dirty) - close_queue[n]->DoSave(); - close_queue[n]->DoForceClose(); + if (doc->Dirty) + doc->DoSave(); + doc->DoForceClose(); } - close_queue.clear(); + app.CloseQueue.clear(); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); if (ImGui::Button("No", button_size)) { - for (int n = 0; n < close_queue.Size; n++) - close_queue[n]->DoForceClose(); - close_queue.clear(); + for (MyDocument* doc : app.CloseQueue) + doc->DoForceClose(); + app.CloseQueue.clear(); ImGui::CloseCurrentPopup(); } ImGui::SameLine(); if (ImGui::Button("Cancel", button_size)) { - close_queue.clear(); + app.CloseQueue.clear(); ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); From 29439bdd27c7847f9421009740a7ffe7832cb934 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 12:31:40 +0200 Subject: [PATCH 05/10] Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY and double-clicking on a border. (#1710) Calculation incorrectly didn't always account for scrollbar as it assumed the other axis would also be auto-fit. --- docs/CHANGELOG.txt | 5 ++++- imgui.cpp | 11 ++++++++++- imgui.h | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 5871a4f1b..746fe3e5e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,10 @@ Breaking changes: Other changes: +- Windows: BeginChild(): fixed visibility of fully clipped child windows and tables to Test Engine. +- Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY + and double-clicking on a border. Calculation incorrectly didn't always account for scrollbar as + it assumed the other axis would also be auto-fit. (#1710) - Inputs: added Shortcut() function (w/ routing policies) in public API. (#456, #2637) - using ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_C); with default policy: - checks that CTRL+C is pressed, @@ -84,7 +88,6 @@ Other changes: - 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. 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] diff --git a/imgui.cpp b/imgui.cpp index 76a506d6d..58a1321e7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5844,10 +5844,18 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont ImVec2 size_max = ((window->Flags & ImGuiWindowFlags_ChildWindow) && !(window->Flags & ImGuiWindowFlags_Popup)) ? ImVec2(FLT_MAX, FLT_MAX) : ImGui::GetMainViewport()->WorkSize - style.DisplaySafeAreaPadding * 2.0f; ImVec2 size_auto_fit = ImClamp(size_desired, size_min, size_max); + // FIXME: CalcWindowAutoFitSize() doesn't take into account that only one axis may be auto-fit when calculating scrollbars, + // we may need to compute/store three variants of size_auto_fit, for x/y/xy. + // Here we implement a workaround for child windows only, but a full solution would apply to normal windows as well: + if ((window->ChildFlags & ImGuiChildFlags_ResizeX) && !(window->ChildFlags & ImGuiChildFlags_ResizeY)) + size_auto_fit.y = window->SizeFull.y; + else if (!(window->ChildFlags & ImGuiChildFlags_ResizeX) && (window->ChildFlags & ImGuiChildFlags_ResizeY)) + size_auto_fit.x = window->SizeFull.x; + // When the window cannot fit all contents (either because of constraints, either because screen is too small), // we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding. ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit); - bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar); + bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar); bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar); if (will_have_scrollbar_x) size_auto_fit.y += style.ScrollbarSize; @@ -6049,6 +6057,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si if (held && g.IO.MouseDoubleClicked[0]) { // Double-clicking bottom or right border auto-fit on this axis + // FIXME: CalcWindowAutoFitSize() doesn't take into account that only one side may be auto-fit when calculating scrollbars. // FIXME: Support top and right borders: rework CalcResizePosSizeFromAnyCorner() to be reusable in both cases. if (border_n == 1 || border_n == 3) // Right and bottom border { diff --git a/imgui.h b/imgui.h index bc1ec840b..497de6a14 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (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_NUM 19066 +#define IMGUI_VERSION_NUM 19067 #define IMGUI_HAS_TABLE /* From 16b72f2d2105caf2b0ecdb10ebbdcdf235ec474b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 14:21:50 +0200 Subject: [PATCH 06/10] Comments --- docs/CHANGELOG.txt | 10 +++++++--- docs/TODO.txt | 2 ++ imgui.cpp | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 746fe3e5e..2b04dd85d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -107,9 +107,12 @@ Breaking changes IF you were using imgui_internal.h versions of Shortcut() or ow versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked() prior to this version: - Inputs (Internals) Renamed ImGuiKeyOwner_None to ImGuiKeyOwner_NoOwner, to make use more - explicit and reduce confusion with the fact it is a non-zero value and cannot be the - default value. -- Inputs (Internals) Shortcut(), SetShortcutRouting(): swapped last two parameters order + explicit and reduce confusion with the fact it is a non-zero value and cannot be a default. +- Inputs (Internals): Renamed symbols global routes: + Renamed ImGuiInputFlags_RouteGlobalLow -> ImGuiInputFlags_RouteGlobal (this is the suggest global route) + Renamed ImGuiInputFlags_RouteGlobal -> ImGuiInputFlags_RouteGlobalOverFocused (override focused route) + Renamed ImGuiInputFlags_RouteGlobalHigh -> ImGuiInputFlags_RouteGlobalHighest +- Inputs (Internals): Shortcut(), SetShortcutRouting(): swapped last two parameters order in function signatures: Before: Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); After: Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0, ImGuiID owner_id = 0); @@ -119,6 +122,7 @@ versions of IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked() prior to this After: IsKeyPressed(ImGuiKey key, ImGuiInputFlags flags, ImGuiID owner_id = 0); Before: IsMouseClicked(ImGuiMouseButton button, ImGuiID owner_id, ImGuiInputFlags flags = 0); After: IsMouseClicked(ImGuiMouseButton button, ImGuiInputFlags flags, ImGuiID owner_id = 0); + - For several reasons those changes makes sense. They are being made because making some of those API public. Only past users of imgui_internal.h with the extra parameters will be affected. Added asserts for valid flags in various functions to detect _some_ misuses, BUT NOT ALL. diff --git a/docs/TODO.txt b/docs/TODO.txt index 80f4e307e..e88fade04 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -175,6 +175,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers (WIP branch) - status-bar: add a per-window status bar helper similar to what menu-bar does. generalize concept of layer0 rect in window (can make _MenuBar window flag obsolete too). + - shortcuts: store multiple keychords in ImGuiKeyChord + - shortcuts: Hovered route (lower than Focused, higher than Global) - shortcuts: local-style shortcut api, e.g. parse "&Save" - shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu - shortcuts: programmatically access shortcuts "Focus("&Save")) diff --git a/imgui.cpp b/imgui.cpp index 58a1321e7..45a3b6f09 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -431,6 +431,7 @@ CODE You can read releases logs https://github.com/ocornut/imgui/releases for more details. - 2024/05/22 (1.90.7) - inputs (internals): renamed ImGuiKeyOwner_None to ImGuiKeyOwner_NoOwner, to make use more explicit and reduce confusion with the default it is a non-zero value and cannot be the default value (never made public, but disclosing as I expect a few users caught on owner-aware inputs). + - inputs (internals): renamed ImGuiInputFlags_RouteGlobalLow -> ImGuiInputFlags_RouteGlobal, ImGuiInputFlags_RouteGlobal -> ImGuiInputFlags_RouteGlobalOverFocused, ImGuiInputFlags_RouteGlobalHigh -> ImGuiInputFlags_RouteGlobalHighest. - inputs (internals): Shortcut(), SetShortcutRouting(): swapped last two parameters order in function signatures: - old: Shortcut(ImGuiKeyChord key_chord, ImGuiID owner_id = 0, ImGuiInputFlags flags = 0); - new: Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0, ImGuiID owner_id = 0); From ef9d525f02c9a2f234afac59171758ef70f0574f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 15:03:53 +0200 Subject: [PATCH 07/10] Shortcuts: added ImGuiInputFlags_RouteActiveItem. (#456, #7618) + rearrange Changelog --- docs/CHANGELOG.txt | 43 ++++++++++++++++++++++++++----------------- imgui.cpp | 20 ++++++++++++++------ imgui.h | 17 +++++++++-------- imgui_demo.cpp | 1 + imgui_internal.h | 2 +- 5 files changed, 51 insertions(+), 32 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 2b04dd85d..6be27caf7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,28 +60,37 @@ Other changes: - Windows: BeginChild(): fixed auto-fit calculation when using either (not both) ResizeX/ResizeY and double-clicking on a border. Calculation incorrectly didn't always account for scrollbar as it assumed the other axis would also be auto-fit. (#1710) -- Inputs: added Shortcut() function (w/ routing policies) in public API. (#456, #2637) - - using ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_C); with default policy: - - checks that CTRL+C is pressed, - - and that current window is in focus stack, - - and that no other requests for CTRL+C have been made from deeper locations of the window/item stack. - - Added ImGuiInputFlags_RouteFocused, ImGuiInputFlags_RouteGlobal and other flags - related to routing policies. (#456, #2637) - - Added ImGuiInputFlags_Repeat for use by Shortcut() and by upcoming (still internal) - extended rework of various input functions. - - About routing system and routing policies: - The general idea is that several callers may register interest in a shortcut, and only one owner gets it. +- Inputs: added shortcut and routing system in public API. (#456, #2637) + - The general idea is that several callers may register interest in a shortcut, and only one owner gets it. Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut. Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts) Child2 -> no call // When Child2 is focused, Parent gets the shortcut. The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical. This is an important property as it facilitate working with foreign code or larger codebase. -- Inputs: added SetNextItemShortcut() to set a shortcut to locally or remotely press or activate - an item (depending on specified routing policy). Items like buttons are not fully activated, in - the sense that they get pressed but an active e.g. InputText() won't be deactivated. (#456) - - Added ImGuiInputFlags_Tooltip to automatically show a tooltip when hovering item. - - Using e.g. ImGuiInputFlags_RouteGlobal the item shortcut may be executed even if its - window is not in focus stack. + - Added Shortcut() function: + e.g. Using ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_C); with default policy: + - checks that CTRL+C is pressed, + - and that current window is in focus stack, + - and that no other requests for CTRL+C have been made from higher priority locations + (e.g. deeper in the window/item stack). + - Added SetNextItemShortcut() to set a shortcut to locally or remotely press or activate + an item (depending on specified routing policy: using ImGuiInputFlags_RouteGlobal the item + shortcut may be executed even if its window is not in focus stack). + Items like buttons are not fully activated, in the sense that they get pressed but another + active item, e.g. InputText() won't be deactivated. + - Added routing policies for Shortcut(), SetNextItemShortcut(): (#456, #2637) + - ImGuiInputFlags_RouteFocused: focus stack route (default) + - ImGuiInputFlags_RouteActiveItem: only route to active item + - ImGuiInputFlags_RouteGlobal: route globally, unless a focus route claim shame shortcut. + - ImGuiInputFlags_RouteGlobalOverFocused + - ImGuiInputFlags_RouteGlobalHighest + - ImGuiInputFlags_RouteAlways: no routing submission, no routing check. + - Added other shortcut/routing options: (#456, #2637) + - ImGuiInputFlags_Repeat: for use by Shortcut() and by upcoming rework of various + input functions (which are still internal for now). + - ImGuiInputFlags_Tooltip: for SetNextItemShortcut() to show a tooltip when hovering item. + - ImGuiInputFlags_RouteUnlessBgFocused + - ImGuiInputFlags_RouteFromRootWindow - 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) - Some shortcuts still uses Ctrl on Mac: e.g. Ctrl+Tab to switch windows. (#4828) diff --git a/imgui.cpp b/imgui.cpp index 45a3b6f09..2e5951840 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8605,7 +8605,7 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) // Current score encoding (lower is highest priority): // - 0: ImGuiInputFlags_RouteGlobalHighest -// - 1: ImGuiInputFlags_RouteFocused (if item active) +// - 1: ImGuiInputFlags_ActiveItem or ImGuiInputFlags_RouteFocused (if item active) // - 2: ImGuiInputFlags_RouteGlobalOverFocused // - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack) // - 254: ImGuiInputFlags_RouteGlobal @@ -8613,10 +8613,9 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) // 'flags' should include an explicit routing policy static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags) { + ImGuiContext& g = *GImGui; if (flags & ImGuiInputFlags_RouteFocused) { - ImGuiContext& g = *GImGui; - // ActiveID gets top priority // (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it) if (owner_id != 0 && g.ActiveId == owner_id) @@ -8637,12 +8636,18 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 255; } - - // ImGuiInputFlags_RouteGlobalHighest is default, so calls without flags are not conditional + if (flags & ImGuiInputFlags_RouteActiveItem) + { + if (owner_id != 0 && g.ActiveId == owner_id) + return 1; + return 255; + } if (flags & ImGuiInputFlags_RouteGlobalOverFocused) return 2; if (flags & ImGuiInputFlags_RouteGlobal) return 254; + + // ImGuiInputFlags_RouteGlobalHighest is default, so calls without flags are not conditional return 0; } @@ -8693,7 +8698,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I return true; } - // Specific culling when there's an active. + // Specific culling when there's an active item. if (g.ActiveId != 0 && g.ActiveId != owner_id) { // Cull shortcuts with no modifiers when it could generate a character. @@ -8707,6 +8712,9 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I return false; } + if (flags & ImGuiInputFlags_RouteActiveItem) + return false; + // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId if ((flags & ImGuiInputFlags_RouteGlobalHighest) == 0 && g.ActiveIdUsingAllKeyboardKeys) { diff --git a/imgui.h b/imgui.h index 497de6a14..cb2ba17b7 100644 --- a/imgui.h +++ b/imgui.h @@ -1483,17 +1483,18 @@ enum ImGuiInputFlags_ // Flags for Shortcut(), SetNextItemShortcut() // - Default policy is RouteFocused. Can select only 1 policy among all available. - // - Priorities: GlobalHighest > Focused (if owner is active item) > GlobalOverFocused > Focused (if in focused window) > Global. + // - Priorities: RouteGlobalHighest >> RouteActiveItem or RouteFocused (if owner is active item) >> RouteGlobalOverFocused >> RouteFocused (if in focused window stack) >> RouteGlobal. ImGuiInputFlags_RouteFocused = 1 << 12, // Focus stack route (default): Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. - ImGuiInputFlags_RouteGlobal = 1 << 13, // Global route (normal priority): unless a focused window or active item registered the route) -> recommended Global priority. - ImGuiInputFlags_RouteGlobalOverFocused = 1 << 14, // Global route (higher priority): unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this). - ImGuiInputFlags_RouteGlobalHighest = 1 << 15, // Global route (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_RouteUnlessBgFocused = 1 << 17, // Option: global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. - ImGuiInputFlags_RouteFromRootWindow = 1 << 18, // Option: route evaluated from the point of view of root window rather than current window. + ImGuiInputFlags_RouteActiveItem = 1 << 13, // Route to active item only. + ImGuiInputFlags_RouteGlobal = 1 << 14, // Global route (normal priority): unless a focused window or active item registered the route) -> recommended Global priority. + ImGuiInputFlags_RouteGlobalOverFocused = 1 << 15, // Global route (higher priority): unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this. + ImGuiInputFlags_RouteGlobalHighest = 1 << 16, // Global route (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. May not be fully honored as user/internal code is likely to always assume they can access keys when active. + ImGuiInputFlags_RouteAlways = 1 << 17, // Do not register route, poll keys directly. + ImGuiInputFlags_RouteUnlessBgFocused = 1 << 18, // Option: global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. + ImGuiInputFlags_RouteFromRootWindow = 1 << 19, // Option: route evaluated from the point of view of root window rather than current window. // Flags for SetNextItemShortcut() - ImGuiInputFlags_Tooltip = 1 << 19, // Automatically display a tooltip when hovering item. + ImGuiInputFlags_Tooltip = 1 << 20, // Automatically display a tooltip when hovering item. }; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5d6148c42..5577913a2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6283,6 +6283,7 @@ static void ShowDemoWindowInputs() static ImGuiInputFlags routing_flags = ImGuiInputFlags_RouteFocused; ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &other_flags, ImGuiInputFlags_Repeat); ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &routing_flags, ImGuiInputFlags_RouteFocused); + ImGui::RadioButton("ImGuiInputFlags_RouteActiveItem", &routing_flags, ImGuiInputFlags_RouteActiveItem); ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &routing_flags, ImGuiInputFlags_RouteAlways); ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &routing_flags, ImGuiInputFlags_RouteGlobal); ImGui::RadioButton("ImGuiInputFlags_RouteGlobalOverFocused", &routing_flags, ImGuiInputFlags_RouteGlobalOverFocused); diff --git a/imgui_internal.h b/imgui_internal.h index d6020f8a7..2ce7060c2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1477,7 +1477,7 @@ enum ImGuiInputFlagsPrivate_ ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways, + ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteActiveItem | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways, ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, From 650cb51bf10d532ccdbff65f5640fd8d39ca5426 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 15:27:43 +0200 Subject: [PATCH 08/10] Shortcuts: renamed ImGuiInputFlags_RouteActiveItem to ImGuiInputFlags_RouteActive. (#456, #7618) Amend ef9d525 --- docs/CHANGELOG.txt | 2 +- imgui.cpp | 4 ++-- imgui.h | 2 +- imgui_demo.cpp | 2 +- imgui_internal.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6be27caf7..edc775738 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -80,7 +80,7 @@ Other changes: active item, e.g. InputText() won't be deactivated. - Added routing policies for Shortcut(), SetNextItemShortcut(): (#456, #2637) - ImGuiInputFlags_RouteFocused: focus stack route (default) - - ImGuiInputFlags_RouteActiveItem: only route to active item + - ImGuiInputFlags_RouteActive: only route to active item - ImGuiInputFlags_RouteGlobal: route globally, unless a focus route claim shame shortcut. - ImGuiInputFlags_RouteGlobalOverFocused - ImGuiInputFlags_RouteGlobalHighest diff --git a/imgui.cpp b/imgui.cpp index 2e5951840..e9a9ec5ce 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8636,7 +8636,7 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 255; } - if (flags & ImGuiInputFlags_RouteActiveItem) + if (flags & ImGuiInputFlags_RouteActive) { if (owner_id != 0 && g.ActiveId == owner_id) return 1; @@ -8712,7 +8712,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I return false; } - if (flags & ImGuiInputFlags_RouteActiveItem) + if (flags & ImGuiInputFlags_RouteActive) return false; // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId diff --git a/imgui.h b/imgui.h index cb2ba17b7..cc97e12af 100644 --- a/imgui.h +++ b/imgui.h @@ -1485,7 +1485,7 @@ enum ImGuiInputFlags_ // - Default policy is RouteFocused. Can select only 1 policy among all available. // - Priorities: RouteGlobalHighest >> RouteActiveItem or RouteFocused (if owner is active item) >> RouteGlobalOverFocused >> RouteFocused (if in focused window stack) >> RouteGlobal. ImGuiInputFlags_RouteFocused = 1 << 12, // Focus stack route (default): Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. - ImGuiInputFlags_RouteActiveItem = 1 << 13, // Route to active item only. + ImGuiInputFlags_RouteActive = 1 << 13, // Route to active item only. ImGuiInputFlags_RouteGlobal = 1 << 14, // Global route (normal priority): unless a focused window or active item registered the route) -> recommended Global priority. ImGuiInputFlags_RouteGlobalOverFocused = 1 << 15, // Global route (higher priority): unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this. ImGuiInputFlags_RouteGlobalHighest = 1 << 16, // Global route (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. May not be fully honored as user/internal code is likely to always assume they can access keys when active. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5577913a2..78b829682 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6283,7 +6283,7 @@ static void ShowDemoWindowInputs() static ImGuiInputFlags routing_flags = ImGuiInputFlags_RouteFocused; ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &other_flags, ImGuiInputFlags_Repeat); ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &routing_flags, ImGuiInputFlags_RouteFocused); - ImGui::RadioButton("ImGuiInputFlags_RouteActiveItem", &routing_flags, ImGuiInputFlags_RouteActiveItem); + ImGui::RadioButton("ImGuiInputFlags_RouteActive", &routing_flags, ImGuiInputFlags_RouteActive); ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &routing_flags, ImGuiInputFlags_RouteAlways); ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &routing_flags, ImGuiInputFlags_RouteGlobal); ImGui::RadioButton("ImGuiInputFlags_RouteGlobalOverFocused", &routing_flags, ImGuiInputFlags_RouteGlobalOverFocused); diff --git a/imgui_internal.h b/imgui_internal.h index 2ce7060c2..fa12bf43c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1477,7 +1477,7 @@ enum ImGuiInputFlagsPrivate_ ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteActiveItem | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways, + ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways, ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, From 5ce3d2995554bc49255ef0994ab68136ef815633 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 15:44:59 +0200 Subject: [PATCH 09/10] Shortcuts: rename ImGuiInputFlags_RouteGlobalHighest to ImGuiInputFlags_RouteGlobalOverActive, made ImGuiInputFlags_RouteGlobalOverFocused and ImGuiInputFlags_RouteGlobalOverActive flags. (#456) --- docs/CHANGELOG.txt | 4 ++-- imgui.cpp | 13 ++++++++----- imgui.h | 21 +++++++++++---------- imgui_demo.cpp | 26 +++++++++++++++----------- imgui_internal.h | 19 +++++++++---------- 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index edc775738..e7e3cf131 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -82,13 +82,13 @@ Other changes: - ImGuiInputFlags_RouteFocused: focus stack route (default) - ImGuiInputFlags_RouteActive: only route to active item - ImGuiInputFlags_RouteGlobal: route globally, unless a focus route claim shame shortcut. - - ImGuiInputFlags_RouteGlobalOverFocused - - ImGuiInputFlags_RouteGlobalHighest - ImGuiInputFlags_RouteAlways: no routing submission, no routing check. - Added other shortcut/routing options: (#456, #2637) - ImGuiInputFlags_Repeat: for use by Shortcut() and by upcoming rework of various input functions (which are still internal for now). - ImGuiInputFlags_Tooltip: for SetNextItemShortcut() to show a tooltip when hovering item. + - ImGuiInputFlags_RouteGlobalOverFocused + - ImGuiInputFlags_RouteGlobalOverActive - ImGuiInputFlags_RouteUnlessBgFocused - ImGuiInputFlags_RouteFromRootWindow - Inputs: (OSX) Fixes variety of code which inconsistently required using Ctrl instead of Cmd. diff --git a/imgui.cpp b/imgui.cpp index e9a9ec5ce..7914492b9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8604,7 +8604,7 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) } // Current score encoding (lower is highest priority): -// - 0: ImGuiInputFlags_RouteGlobalHighest +// - 0: ImGuiInputFlags_RouteGlobalOverActive // - 1: ImGuiInputFlags_ActiveItem or ImGuiInputFlags_RouteFocused (if item active) // - 2: ImGuiInputFlags_RouteGlobalOverFocused // - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack) @@ -8646,8 +8646,9 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 2; if (flags & ImGuiInputFlags_RouteGlobal) return 254; - - // ImGuiInputFlags_RouteGlobalHighest is default, so calls without flags are not conditional + if (flags & ImGuiInputFlags_RouteGlobalOverActive) + return 0; + IM_ASSERT(0); return 0; } @@ -8677,6 +8678,8 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id) { ImGuiContext& g = *GImGui; + if (flags & (ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive)) + flags |= ImGuiInputFlags_RouteGlobal; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner); @@ -8716,7 +8719,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I return false; // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId - if ((flags & ImGuiInputFlags_RouteGlobalHighest) == 0 && g.ActiveIdUsingAllKeyboardKeys) + if ((flags & ImGuiInputFlags_RouteGlobalOverActive) == 0 && g.ActiveIdUsingAllKeyboardKeys) { ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) @@ -12870,7 +12873,7 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : false; // Gamepad starts toggling layer g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_Keyboard : ImGuiInputSource_Gamepad; - // Manually register ownership of our mods. Using ImGuiInputFlags_RouteGlobalHighest in the Shortcut() calls instead would probably be correct but may have more side-effects. + // Manually register ownership of our mods. Using a global route in the Shortcut() calls instead would probably be correct but may have more side-effects. if (keyboard_next_window || keyboard_prev_window) SetKeyOwnersForKeyChord((g.ConfigNavWindowingKeyNext | g.ConfigNavWindowingKeyPrev) & ImGuiMod_Mask_, owner_id); } diff --git a/imgui.h b/imgui.h index cc97e12af..d21db12aa 100644 --- a/imgui.h +++ b/imgui.h @@ -1482,19 +1482,20 @@ enum ImGuiInputFlags_ ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1. // Flags for Shortcut(), SetNextItemShortcut() + // - Routing policies: RouteGlobalOverActive >> RouteActive or RouteFocused (if owner is active item) >> RouteGlobalOverFocused >> RouteFocused (if in focused window stack) >> RouteGlobal. // - Default policy is RouteFocused. Can select only 1 policy among all available. - // - Priorities: RouteGlobalHighest >> RouteActiveItem or RouteFocused (if owner is active item) >> RouteGlobalOverFocused >> RouteFocused (if in focused window stack) >> RouteGlobal. - ImGuiInputFlags_RouteFocused = 1 << 12, // Focus stack route (default): Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window. - ImGuiInputFlags_RouteActive = 1 << 13, // Route to active item only. - ImGuiInputFlags_RouteGlobal = 1 << 14, // Global route (normal priority): unless a focused window or active item registered the route) -> recommended Global priority. - ImGuiInputFlags_RouteGlobalOverFocused = 1 << 15, // Global route (higher priority): unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this. - ImGuiInputFlags_RouteGlobalHighest = 1 << 16, // Global route (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. May not be fully honored as user/internal code is likely to always assume they can access keys when active. - ImGuiInputFlags_RouteAlways = 1 << 17, // Do not register route, poll keys directly. - ImGuiInputFlags_RouteUnlessBgFocused = 1 << 18, // Option: global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. - ImGuiInputFlags_RouteFromRootWindow = 1 << 19, // Option: route evaluated from the point of view of root window rather than current window. + ImGuiInputFlags_RouteActive = 1 << 10, // Route to active item only. + ImGuiInputFlags_RouteFocused = 1 << 11, // Route to windows in the focus stack (DEFAULT). Deep-most focused window takes inputs. Active item takes inputs over deep-most focused window. + ImGuiInputFlags_RouteGlobal = 1 << 12, // Global route (unless a focused window or active item registered the route). + ImGuiInputFlags_RouteAlways = 1 << 13, // Do not register route, poll keys directly. + // - Routing options + ImGuiInputFlags_RouteGlobalOverFocused = 1 << 14, // Option: global route, higher priority than focused route (unless active item in focused route). automatically sets ImGuiInputFlags_RouteGlobal. + ImGuiInputFlags_RouteGlobalOverActive = 1 << 15, // Option: global route, higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active. Automatically sets ImGuiInputFlags_RouteGlobal. + ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. + ImGuiInputFlags_RouteFromRootWindow = 1 << 17, // Option: route evaluated from the point of view of root window rather than current window. // Flags for SetNextItemShortcut() - ImGuiInputFlags_Tooltip = 1 << 20, // Automatically display a tooltip when hovering item. + ImGuiInputFlags_Tooltip = 1 << 18, // Automatically display a tooltip when hovering item. }; #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 78b829682..610a5da65 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6279,17 +6279,21 @@ static void ShowDemoWindowInputs() IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts"); if (ImGui::TreeNode("Shortcuts")) { - static ImGuiInputFlags other_flags = ImGuiInputFlags_Repeat; - static ImGuiInputFlags routing_flags = ImGuiInputFlags_RouteFocused; - ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &other_flags, ImGuiInputFlags_Repeat); - ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &routing_flags, ImGuiInputFlags_RouteFocused); - ImGui::RadioButton("ImGuiInputFlags_RouteActive", &routing_flags, ImGuiInputFlags_RouteActive); - ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &routing_flags, ImGuiInputFlags_RouteAlways); - ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &routing_flags, ImGuiInputFlags_RouteGlobal); - ImGui::RadioButton("ImGuiInputFlags_RouteGlobalOverFocused", &routing_flags, ImGuiInputFlags_RouteGlobalOverFocused); - ImGui::RadioButton("ImGuiInputFlags_RouteGlobalHighest", &routing_flags, ImGuiInputFlags_RouteGlobalHighest); - ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &other_flags, ImGuiInputFlags_RouteUnlessBgFocused); - const ImGuiInputFlags flags = other_flags | routing_flags; // Merged flags + static ImGuiInputFlags route_options = ImGuiInputFlags_Repeat; + static ImGuiInputFlags route_type = ImGuiInputFlags_RouteFocused; + ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &route_options, ImGuiInputFlags_Repeat); + ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive); + ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused); + ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal); + ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways); + ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal); + ImGui::CheckboxFlags("ImGuiInputFlags_RouteGlobalOverFocused", &route_options, ImGuiInputFlags_RouteGlobalOverFocused); + ImGui::CheckboxFlags("ImGuiInputFlags_RouteGlobalOverActive", &route_options, ImGuiInputFlags_RouteGlobalOverActive); + ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused); + ImGui::EndDisabled(); + ImGuiInputFlags flags = route_type | route_options; // Merged flags + if (route_type != ImGuiInputFlags_RouteGlobal) + route_options &= ~(ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive); ImGui::SeparatorText("Using SetNextItemShortcut()"); ImGui::Text("Ctrl+S"); diff --git a/imgui_internal.h b/imgui_internal.h index fa12bf43c..a2375e579 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1461,24 +1461,23 @@ enum ImGuiInputFlagsPrivate_ ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone = 1 << 6, // Stop repeating when released OR if keyboard mods are leaving the None state. Allows going from Mod+Key to Key by releasing Mod. ImGuiInputFlags_RepeatUntilOtherKeyPress = 1 << 7, // Stop repeating when released OR if any other keyboard key is pressed during the repeat - // Flags for SetItemKeyOwner() - // - Condition - ImGuiInputFlags_CondHovered = 1 << 8, // Only set if item is hovered (default to both) - ImGuiInputFlags_CondActive = 1 << 9, // Only set if item is active (default to both) - ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - // Flags for SetKeyOwner(), SetItemKeyOwner() // - Locking key away from non-input aware code. Locking is useful to make input-owner-aware code steal keys from non-input-owner-aware code. If all code is input-owner-aware locking would never be necessary. - ImGuiInputFlags_LockThisFrame = 1 << 10, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. - ImGuiInputFlags_LockUntilRelease = 1 << 11, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. + ImGuiInputFlags_LockThisFrame = 1 << 20, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared at end of frame. + ImGuiInputFlags_LockUntilRelease = 1 << 21, // Further accesses to key data will require EXPLICIT owner ID (ImGuiKeyOwner_Any/0 will NOT accepted for polling). Cleared when the key is released or at end of each frame if key is released. + + // - Condition for SetItemKeyOwner() + ImGuiInputFlags_CondHovered = 1 << 22, // Only set if item is hovered (default to both) + ImGuiInputFlags_CondActive = 1 << 23, // Only set if item is active (default to both) + ImGuiInputFlags_CondDefault_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, // [Internal] Mask of which function support which flags ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak, ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress, ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, - ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteGlobalHighest | ImGuiInputFlags_RouteAlways, - ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, + ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteAlways, + ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive | ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_, From ce4e210dcb6663d670b544c6aa9f50908305985c Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 24 May 2024 16:07:58 +0200 Subject: [PATCH 10/10] Shotcuts: renamed ImGuiInputFlags_RouteGlobalOverFocused -> ImGuiInputFlags_RouteOverFocused, ImGuiInputFlags_RouteGlobalOverActive -> ImGuiInputFlags_RouteOverActive in previsiion of using them with a Hovered route. (#456) --- imgui.cpp | 12 ++++++------ imgui.h | 6 +++--- imgui_demo.cpp | 10 ++++++---- imgui_internal.h | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7914492b9..38fb4496d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8642,11 +8642,11 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput return 1; return 255; } - if (flags & ImGuiInputFlags_RouteGlobalOverFocused) + if (flags & ImGuiInputFlags_RouteOverFocused) return 2; if (flags & ImGuiInputFlags_RouteGlobal) return 254; - if (flags & ImGuiInputFlags_RouteGlobalOverActive) + if (flags & ImGuiInputFlags_RouteOverActive) return 0; IM_ASSERT(0); return 0; @@ -8678,10 +8678,10 @@ static bool IsKeyChordPotentiallyCharInput(ImGuiKeyChord key_chord) bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id) { ImGuiContext& g = *GImGui; - if (flags & (ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive)) - flags |= ImGuiInputFlags_RouteGlobal; IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner); + if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused)) + IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal); // Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified. key_chord = FixupKeyChord(key_chord); @@ -8719,7 +8719,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I return false; // ActiveIdUsingAllKeyboardKeys trumps all for ActiveId - if ((flags & ImGuiInputFlags_RouteGlobalOverActive) == 0 && g.ActiveIdUsingAllKeyboardKeys) + if ((flags & ImGuiInputFlags_RouteOverActive) == 0 && g.ActiveIdUsingAllKeyboardKeys) { ImGuiKey key = (ImGuiKey)(key_chord & ~ImGuiMod_Mask_); if (key == ImGuiKey_None) @@ -15909,7 +15909,7 @@ void ImGui::ShowIDStackToolWindow(bool* p_open) Checkbox("Ctrl+C: copy path to clipboard", &tool->CopyToClipboardOnCtrlC); 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*"); - if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobalOverFocused)) + if (tool->CopyToClipboardOnCtrlC && Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused)) { tool->CopyToClipboardLastTime = (float)g.Time; char* p = g.TempBuffer.Data; diff --git a/imgui.h b/imgui.h index d21db12aa..f52dff4b7 100644 --- a/imgui.h +++ b/imgui.h @@ -1489,9 +1489,9 @@ enum ImGuiInputFlags_ ImGuiInputFlags_RouteGlobal = 1 << 12, // Global route (unless a focused window or active item registered the route). ImGuiInputFlags_RouteAlways = 1 << 13, // Do not register route, poll keys directly. // - Routing options - ImGuiInputFlags_RouteGlobalOverFocused = 1 << 14, // Option: global route, higher priority than focused route (unless active item in focused route). automatically sets ImGuiInputFlags_RouteGlobal. - ImGuiInputFlags_RouteGlobalOverActive = 1 << 15, // Option: global route, higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active. Automatically sets ImGuiInputFlags_RouteGlobal. - ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. + ImGuiInputFlags_RouteOverFocused = 1 << 14, // Option: global route: higher priority than focused route (unless active item in focused route). + ImGuiInputFlags_RouteOverActive = 1 << 15, // Option: global route: higher priority than active item. Unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this. May not be fully honored as user/internal code is likely to always assume they can access keys when active. + ImGuiInputFlags_RouteUnlessBgFocused = 1 << 16, // Option: global route: will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications. ImGuiInputFlags_RouteFromRootWindow = 1 << 17, // Option: route evaluated from the point of view of root window rather than current window. // Flags for SetNextItemShortcut() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 610a5da65..da4ef3181 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -6285,15 +6285,17 @@ static void ShowDemoWindowInputs() ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive); ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused); ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal); - ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways); + ImGui::Indent(); ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal); - ImGui::CheckboxFlags("ImGuiInputFlags_RouteGlobalOverFocused", &route_options, ImGuiInputFlags_RouteGlobalOverFocused); - ImGui::CheckboxFlags("ImGuiInputFlags_RouteGlobalOverActive", &route_options, ImGuiInputFlags_RouteGlobalOverActive); + ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverFocused", &route_options, ImGuiInputFlags_RouteOverFocused); + ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverActive", &route_options, ImGuiInputFlags_RouteOverActive); ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused); ImGui::EndDisabled(); + ImGui::Unindent(); + ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways); ImGuiInputFlags flags = route_type | route_options; // Merged flags if (route_type != ImGuiInputFlags_RouteGlobal) - route_options &= ~(ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive); + route_options &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused); ImGui::SeparatorText("Using SetNextItemShortcut()"); ImGui::Text("Ctrl+S"); diff --git a/imgui_internal.h b/imgui_internal.h index a2375e579..1cc765f74 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1477,7 +1477,7 @@ enum ImGuiInputFlagsPrivate_ ImGuiInputFlags_RepeatMask_ = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateMask_ | ImGuiInputFlags_RepeatUntilMask_, ImGuiInputFlags_CondMask_ = ImGuiInputFlags_CondHovered | ImGuiInputFlags_CondActive, ImGuiInputFlags_RouteTypeMask_ = ImGuiInputFlags_RouteActive | ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteAlways, - ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteGlobalOverFocused | ImGuiInputFlags_RouteGlobalOverActive | ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, + ImGuiInputFlags_RouteOptionsMask_ = ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused | ImGuiInputFlags_RouteFromRootWindow, ImGuiInputFlags_SupportedByIsKeyPressed = ImGuiInputFlags_RepeatMask_, ImGuiInputFlags_SupportedByIsMouseClicked = ImGuiInputFlags_Repeat, ImGuiInputFlags_SupportedByShortcut = ImGuiInputFlags_RepeatMask_ | ImGuiInputFlags_RouteTypeMask_ | ImGuiInputFlags_RouteOptionsMask_,