Skip to content

Commit 91956e8

Browse files
committed
Demo: added variety of usage scenarios, hooking Alt, Mouse Wheel, Home, CTRL+Tab demos.
(relate to issues: 456, 2637, 2620, 2891, 3370, 3724, 4828, 5108, 5242, 5641)
1 parent 2598d43 commit 91956e8

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

imgui_demo.cpp

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8047,6 +8047,249 @@ static void DemoWindowInputs()
80478047
ImGui::Text("- IsKeyPressed(%s): %s", key_name, ImGui::IsKeyPressed(key, false) ? "PRESSED!" : "..");
80488048
ImGui::TreePop();
80498049
}
8050+
8051+
// Miscellaneous examples
8052+
if (ImGui::TreeNode("Usage Scenarios"))
8053+
{
8054+
// We use colored buttons for the demo but this would generally apply to any widget.
8055+
const ImVec2 button_sz(60.0f, 60.0f);
8056+
const ImGuiColorEditFlags button_flags = ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop;
8057+
8058+
if (ImGui::TreeNode("1. Claiming Mouse Wheel"))
8059+
{
8060+
static float value1 = 0.0f;
8061+
ImGui::Text("%.2f", value1);
8062+
ImGui::SameLine();
8063+
HelpMarker("Hover button and use mouse wheel: window scrolling won't be activated.");
8064+
ImGui::ColorButton("Item1", ImVec4(0.4f, 0.4f, 0.8f, 1.0f), button_flags, button_sz);
8065+
ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY);
8066+
if (ImGui::IsItemHovered() || ImGui::IsItemActive())
8067+
value1 += io.MouseWheel;
8068+
8069+
static float value2 = 0.0f;
8070+
ImGui::Text("%.2f", value2);
8071+
ImGui::SameLine();
8072+
HelpMarker("Hold button and use mouse wheel: window scrolling won't be activated.");
8073+
ImGui::ColorButton("Item2", ImVec4(0.4f, 0.4f, 0.8f, 1.0f), button_flags, button_sz);
8074+
ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY, ImGuiInputFlags_CondActive);
8075+
if (ImGui::IsItemActive())
8076+
value2 += io.MouseWheel;
8077+
8078+
ImGui::TreePop();
8079+
}
8080+
8081+
if (ImGui::TreeNode("2. Claiming Alt key"))
8082+
{
8083+
ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
8084+
8085+
static float spinner0 = 0.0f;
8086+
ImGui::Text("%.3f", spinner0);
8087+
ImGui::SameLine();
8088+
HelpMarker("Click, hold ALT drag to tweak value. Notice that Alt doesn't move focus to menu bar.");
8089+
ImGui::Button("Spin me", button_sz);
8090+
if (ImGui::IsItemActive())
8091+
{
8092+
ImGui::SetKeyOwner(ImGuiMod_Alt, ImGui::GetItemID());
8093+
if (ImGui::IsKeyDown(ImGuiMod_Alt)) // Poll on Active: we don't need to check for ownership of ImGuiMod_Alt since we know we unconditionally own it.
8094+
spinner0 += io.MouseDelta.x;
8095+
}
8096+
8097+
// When using of keys is conditioned by item being hovered or active,
8098+
// it creates a natural exclusivity, since only one item can be hovered or active.
8099+
// SetItemKeyOwner(...) is a shortcut for doing 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(..., GetItemID()); }'
8100+
static int value1 = 0;
8101+
ImGui::Text("%d", value1);
8102+
ImGui::SameLine();
8103+
HelpMarker("Item1 claims ALT key when Hovered or Active, counter increase when pressing ALT while Hovered.");
8104+
ImGui::Button("Item1", button_sz);
8105+
ImGui::SetItemKeyOwner(ImGuiMod_Alt); // Claim Alt on Hover and Active
8106+
if (ImGui::IsItemHovered() && ImGui::IsKeyPressed(ImGuiMod_Alt, false)) // Poll on Hover: we don't need to check for ownership of ImGuiMod_Alt since we know we unconditionally own it.
8107+
value1++;
8108+
8109+
ImGui::TreePop();
8110+
}
8111+
8112+
// Routing options are only available for Shortcuts (not Key)
8113+
// Using shortcut functions with only ImGuiMod_Alt means that other modifiers e.g. CTRL+ALT+S won't be affected, which is often desirable.
8114+
// Here we use ImGuiInputFlags_RouteFocused which will claim the Alt shortcut when the window is focused.
8115+
// Notice that opening this node will claim Alt, therefore change the behavior of the key checks in section (2) above.
8116+
if (ImGui::TreeNode("3. Claiming Alt shortcut"))
8117+
{
8118+
// Using Shortcut() with ImGuiInputFlags_RouteFocused means we react when parent window is focused.
8119+
// - Passing 0 (== ImGuiKeyOwner_Any) means current location will be used to identify.
8120+
// As both calls are from the same location, both items will receive the shortcut.
8121+
// - Passing GetItemID() here means they both have their unique id,
8122+
// - Item2 will only receive the shortcut when parent window is focused.
8123+
// - Item3 will only receive the shortcut when active.
8124+
// Not passing an item id would use current location as id so both items will always receive shortcut.
8125+
static bool use_shared_owner = false;
8126+
ImGui::Checkbox("Item2 and Item3 use same owner/location", &use_shared_owner);
8127+
static int value2 = 0;
8128+
ImGui::Text("%d", value2);
8129+
ImGui::SameLine();
8130+
HelpMarker("Item2 reads ALT shortcut when its parent window is focused.");
8131+
ImGui::Button("Item2", button_sz);
8132+
if (ImGui::Shortcut(ImGuiMod_Alt, 0, use_shared_owner ? 0 : ImGui::GetItemID()))
8133+
value2++;
8134+
8135+
static int value3 = 0;
8136+
ImGui::Text("%d", value3);
8137+
ImGui::SameLine();
8138+
HelpMarker("Item3 reads ALT shortcut when its parent window is focused AND it is active. Therefore, only active previous button will get the shortcut");
8139+
ImGui::Button("Item3", button_sz);
8140+
if (ImGui::Shortcut(ImGuiMod_Alt, 0, use_shared_owner ? 0 : ImGui::GetItemID()))
8141+
value3++;
8142+
8143+
ImGui::TreePop();
8144+
}
8145+
8146+
if (ImGui::TreeNode("4. Claiming Home key globally"))
8147+
{
8148+
static bool enable_home_robbery = false;
8149+
static int home_presses = 0;
8150+
ImGui::Checkbox("Global steal ImGuiKey_Home", &enable_home_robbery);
8151+
ImGui::Text("Home presses: %d", home_presses);
8152+
if (enable_home_robbery)
8153+
{
8154+
// Claim ownership is enough to keep Key away from main library behavior or any owner-aware code.
8155+
// - We optionally use the ImGuiInputFlags_LockUntilRelease to keep key away from code that is not owner-aware,
8156+
// but Dear ImGui itself is so that's not technically needed (unless you are stealing from another piece of code).
8157+
ImGuiID robber_id = ImGui::GetID("Some Identifier");
8158+
ImGui::SetKeyOwner(ImGuiKey_Home, robber_id, ImGuiInputFlags_LockUntilRelease);
8159+
if (ImGui::IsKeyPressed(ImGuiKey_Home, ImGuiInputFlags_Repeat, robber_id)) // We unconditionally own the key so no need to test for ownership
8160+
home_presses++;
8161+
}
8162+
ImGui::TreePop();
8163+
}
8164+
8165+
if (ImGui::TreeNode("5. Claiming CTRL+A shortcut globally"))
8166+
{
8167+
// Using a priority of ImGuiInputFlags_RouteGlobal + RouteOverActive means we takes away even from an active item (e.g. InputText)
8168+
// This is better covered in "Shortcut Routing basics" above.
8169+
static bool enable_ctrl_a_robbery = false;
8170+
static int ctrl_a_presses = 0;
8171+
ImGui::Checkbox("Global steal CTRL+A", &enable_ctrl_a_robbery);
8172+
ImGui::Text("CTRL+A presses: %d", ctrl_a_presses);
8173+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_A, enable_ctrl_a_robbery ? ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive : ImGuiInputFlags_RouteAlways))
8174+
ctrl_a_presses++;
8175+
8176+
ImGui::TreePop();
8177+
}
8178+
8179+
if (ImGui::TreeNode("6. Disable ESC key from InputText()"))
8180+
{
8181+
static char buf[9];
8182+
ImGui::InputText("Text", buf, IM_ARRAYSIZE(buf));
8183+
8184+
// - If you don't need to use the key, you can use 'owner_id=0', 'flags=ImGuiInputFlags_LockXXX'
8185+
// as a convenience to hide the key from everyone.
8186+
// - If you need to use the key yourself, you need to use any arbitrary ID, and then use this ID to read the key.
8187+
// e.g. ImGui::SetKeyOwner(ImGuiKey_Escape, ImGui::GetID("robber")); + later use same ID to access the key.
8188+
if (ImGui::IsItemActive())
8189+
ImGui::SetKeyOwner(ImGuiKey_Escape, 0, ImGuiInputFlags_LockUntilRelease);
8190+
ImGui::TreePop();
8191+
}
8192+
8193+
if (ImGui::TreeNode("7. Claiming ESC key away from InputText()"))
8194+
{
8195+
static char buf[9];
8196+
ImGui::InputText("Text", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_EscapeClearsAll);
8197+
if (ImGui::IsItemActive())
8198+
{
8199+
// Using a route which is higher priority than one claimed the ActiveId
8200+
ImGuiID robber_id = ImGui::GetID("robber");
8201+
if (ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, robber_id))
8202+
{
8203+
strcpy(buf, "Esc!");
8204+
ImGui::ClearActiveID();
8205+
}
8206+
}
8207+
ImGui::TreePop();
8208+
}
8209+
8210+
if (ImGui::TreeNode("8. Claiming ESC away from nav logic (e.g. exiting a child)"))
8211+
{
8212+
ImGui::BeginChild("child", ImVec2(-FLT_MIN, 50), true);
8213+
ImGui::Button("Button in child");
8214+
if (ImGui::IsWindowFocused())
8215+
ImGui::SetKeyOwner(ImGuiKey_Escape, ImGui::GetID("")); // any id
8216+
ImGui::EndChild();
8217+
8218+
ImGui::TreePop();
8219+
}
8220+
8221+
if (ImGui::TreeNode("9. Claiming Tab, CTRL+Tab"))
8222+
{
8223+
static int mode = 0;
8224+
static int counter = 0;
8225+
8226+
HelpMarker("Showcasing many variants as a recap.\nPlease read code and comments carefully!");
8227+
8228+
const char* mode_names[] = { "None", "Disable Tab key (item)", "Disable Tab key (global)", "Disable CTRL+Tab (global)", "Disable CTRL+Tab (if focused)", "Read CTRL+Tab (global)", "Replace CTRL+Tab (global)", "Replace CTRL+Tab (if focused)" };
8229+
ImGui::Combo("Operation Mode", &mode, mode_names, IM_ARRAYSIZE(mode_names));
8230+
ImGui::Text("Counter = %d", counter);
8231+
8232+
switch (mode)
8233+
{
8234+
case 1:
8235+
// Item take ownership of Tab key when hovered/active (meaning ALL uses of Tab will be disabled, not just CTRL+Tab)
8236+
ImGui::Button("This Button Steals The Tab Key");
8237+
ImGui::SetItemKeyOwner(ImGuiKey_Tab);
8238+
ImGui::SameLine();
8239+
HelpMarker("While hovering or activating this button, TAB key is stolen (e.g. won't tab out into other systems)");
8240+
break;
8241+
case 2:
8242+
// Take ownership of Tab key (meaning ALL uses of Tab will be disabled, not just CTRL+Tab)
8243+
ImGui::SetKeyOwner(ImGuiKey_Tab, ImGui::GetID("some-id"));
8244+
break;
8245+
case 3:
8246+
// Disable CTRL+Tab shortcuts (global): assign an owner to steal the route to our two shortcuts
8247+
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, 0, ImGui::GetID("some-id"));
8248+
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, 0, ImGui::GetID("some-id"));
8249+
break;
8250+
case 4:
8251+
// Disable CTRL+Tab shortcuts (if focused): assign an owner to steal the route to our two shortcuts, applies focus testing so will only apply if window is in focus chain
8252+
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteFocused, ImGui::GetID("some-id"));
8253+
ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteFocused, ImGui::GetID("some-id"));
8254+
break;
8255+
case 5:
8256+
// Read CTRL+Tab (global): reading keys without interfering with any behaviors (need to specify ImGuiInputFlags_RouteAlways as other policies will interfere)
8257+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteAlways, ImGuiKeyOwner_Any))
8258+
counter++;
8259+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteAlways, ImGuiKeyOwner_Any))
8260+
counter--;
8261+
break;
8262+
case 6:
8263+
{
8264+
// Replace CTRL+Tab (global)
8265+
// - We steal the route and assign it to our ID (so core system won't access it). Our reading queries now need to specify that ID.
8266+
ImGuiID id = ImGui::GetID("My-Ctrl-Tab-Handler");
8267+
//ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiKey_Tab, id, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive);
8268+
//ImGui::SetShortcutRouting(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, id, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive);
8269+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, id))
8270+
counter++; // You could perform some other action here.
8271+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive, id))
8272+
counter--;
8273+
break;
8274+
}
8275+
case 7:
8276+
// Replace CTRL+Tab (if focused)
8277+
// - Passing ImGuiInputFlags_RouteFocused will test for focus and assign a route using a default owner id based on location (so we can use 0 as id)
8278+
// - This would also work if we replaced 0 with ImGui::GetID("My-Ctrl-Tab-Handler")
8279+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_Tab))
8280+
counter++; // You could perform some other action here.
8281+
if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Tab))
8282+
counter--;
8283+
break;
8284+
}
8285+
8286+
static char buf[8] = "";
8287+
ImGui::InputTextWithHint("Dummy", "(dummy input text to test effect of Tabbing)", buf, IM_ARRAYSIZE(buf));
8288+
8289+
ImGui::TreePop();
8290+
}
8291+
ImGui::TreePop();
8292+
}
80508293
ImGui::TreePop();
80518294
}
80528295

0 commit comments

Comments
 (0)