Skip to content

Commit fc512a2

Browse files
committed
Inputs: Added Shortcut(), SetNextItemShortcut(). Added ImGuiInputFlags, ImGuiInputFlags_RouteXXXX. (#456, #2637)
1 parent 85513de commit fc512a2

File tree

4 files changed

+75
-47
lines changed

4 files changed

+75
-47
lines changed

docs/CHANGELOG.txt

+17
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,23 @@ Breaking changes:
5656

5757
Other changes:
5858

59+
- Inputs: added Shortcut() function (w/ routing policies) in public API. (#456, #2637)
60+
- using ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_C); with default policy:
61+
- checks that CTRL+C is pressed,
62+
- and that current window is in focus stack,
63+
- and that no other requests for CTRL+C have been made from deeper locations of the window/item stack.
64+
- Added ImGuiInputFlags_RouteFocused, ImGuiInputFlags_RouteGlobal and other flags
65+
related to routing policies. (#456, #2637)
66+
- Added ImGuiInputFlags_Repeat for use by Shortcut() and by upcoming (still internal)
67+
extended rework of various input functions.
68+
- About routing system and routing policies:
69+
The general idea is that several callers may register interest in a shortcut, and only one owner gets it.
70+
Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
71+
Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
72+
Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
73+
The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical.
74+
This is an important property as it facilitate working with foreign code or larger codebase.
75+
- Inputs: added SetNextItemShortcut() to set a shortcut to activate an item. (#456)
5976
- Inputs: (OSX) Fixes variety of code which inconsistently required using Ctrl instead of Cmd.
6077
- e.g. Drags/Sliders now use Cmd+Click to input a value. (#4084)
6178
- Some shortcuts still uses Ctrl on Mac: e.g. Ctrl+Tab to switch windows. (#4828)

imgui.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -9681,6 +9681,11 @@ void ImGui::SetNextItemShortcut(ImGuiKeyChord key_chord)
96819681
g.NextItemData.Shortcut = key_chord;
96829682
}
96839683

9684+
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags)
9685+
{
9686+
return Shortcut(key_chord, flags, ImGuiKeyOwner_Any);
9687+
}
9688+
96849689
bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id)
96859690
{
96869691
//ImGuiContext& g = *GImGui;
@@ -12310,7 +12315,7 @@ void ImGui::NavUpdateCreateMoveRequest()
1231012315
g.NavMoveScrollFlags = ImGuiScrollFlags_None;
1231112316
if (window && !g.NavWindowingTarget && !(window->Flags & ImGuiWindowFlags_NoNavInputs))
1231212317
{
12313-
const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | ImGuiInputFlags_RepeatRateNavMove;
12318+
const ImGuiInputFlags repeat_mode = ImGuiInputFlags_Repeat | (ImGuiInputFlags)ImGuiInputFlags_RepeatRateNavMove;
1231412319
if (!IsActiveIdUsingNavDir(ImGuiDir_Left) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadLeft, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_LeftArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) { g.NavMoveDir = ImGuiDir_Left; }
1231512320
if (!IsActiveIdUsingNavDir(ImGuiDir_Right) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadRight, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_RightArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) { g.NavMoveDir = ImGuiDir_Right; }
1231612321
if (!IsActiveIdUsingNavDir(ImGuiDir_Up) && ((nav_gamepad_active && IsKeyPressed(ImGuiKey_GamepadDpadUp, repeat_mode, ImGuiKeyOwner_NoOwner)) || (nav_keyboard_active && IsKeyPressed(ImGuiKey_UpArrow, repeat_mode, ImGuiKeyOwner_NoOwner)))) { g.NavMoveDir = ImGuiDir_Up; }

imgui.h

+38
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: f
210210
typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload()
211211
typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
212212
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
213+
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for Shortcut(), SetNextItemShortcut()
213214
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText(), InputTextMultiline()
214215
typedef int ImGuiKeyChord; // -> ImGuiKey | ImGuiMod_XXX // Flags: for IsKeyChordPressed(), Shortcut() etc. an ImGuiKey optionally OR-ed with one or more ImGuiMod_XXX values.
215216
typedef int ImGuiPopupFlags; // -> enum ImGuiPopupFlags_ // Flags: for OpenPopup*(), BeginPopupContext*(), IsPopupOpen()
@@ -938,6 +939,24 @@ namespace ImGui
938939
IMGUI_API const char* GetKeyName(ImGuiKey key); // [DEBUG] returns English name of the key. Those names a provided for debugging purpose and are not meant to be saved persistently not compared.
939940
IMGUI_API void SetNextFrameWantCaptureKeyboard(bool want_capture_keyboard); // Override io.WantCaptureKeyboard flag next frame (said flag is left for your application to handle, typically when true it instructs your app to ignore inputs). e.g. force capture keyboard when your widget is being hovered. This is equivalent to setting "io.WantCaptureKeyboard = want_capture_keyboard"; after the next NewFrame() call.
940941

942+
// Inputs Utilities: Shortcut Testing & Routing
943+
// - ImGuiKeyChord = a ImGuiKey + optional ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super.
944+
// ImGuiKey_C // Accepted by functions taking ImGuiKey or ImGuiKeyChord arguments)
945+
// ImGuiMod_Ctrl | ImGuiKey_C // Accepted by functions taking ImGuiKeyChord arguments)
946+
// only ImGuiMod_XXX values are legal to combine with an ImGuiKey. You CANNOT combine two ImGuiKey values.
947+
// - The general idea is that several callers may register interest in a shortcut, and only one owner gets it.
948+
// Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
949+
// Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
950+
// Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
951+
// The whole system is order independent, so if Child1 makes its calls before Parent, results will be identical.
952+
// This is an important property as it facilitate working with foreign code or larger codebase.
953+
// - To understand the difference:
954+
// - IsKeyChordPressed() compares mods and call IsKeyPressed() -> function has no side-effect.
955+
// - Shortcut() submits a route, routes are resolved, if it currently can be routed it calls IsKeyChordPressed() -> function has (desirable) side-effects as it can prevents another call from getting the route.
956+
// - Visualize registered routes in 'Metrics/Debugger->Inputs'.
957+
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0);
958+
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord);
959+
941960
// Inputs Utilities: Mouse specific
942961
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
943962
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
@@ -1454,6 +1473,25 @@ enum ImGuiKey : int
14541473
#endif
14551474
};
14561475

1476+
// Flags for Shortcut(), SetNextItemShortcut(),
1477+
// (and for upcoming extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner() that are still in imgui_internal.h)
1478+
// Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function)
1479+
enum ImGuiInputFlags_
1480+
{
1481+
ImGuiInputFlags_None = 0,
1482+
ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
1483+
1484+
// Flags for Shortcut()
1485+
// - Default policy is RouteFocused. Can select only 1 policy among all available.
1486+
// - Priorities: GlobalHighest > Focused (if owner is active item) > GlobalOverFocused > Focused (if in focused window) > Global.
1487+
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.
1488+
ImGuiInputFlags_RouteGlobal = 1 << 13, // Global route (normal priority): unless a focused window or active item registered the route) -> recommended Global priority.
1489+
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).
1490+
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)
1491+
ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly.
1492+
ImGuiInputFlags_RouteUnlessBgFocused = 1 << 17, // Option combine with others: global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
1493+
};
1494+
14571495
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO
14581496
// OBSOLETED in 1.88 (from July 2022): ImGuiNavInput and io.NavInputs[].
14591497
// Official backends between 1.60 and 1.86: will keep working and feed gamepad inputs as long as IMGUI_DISABLE_OBSOLETE_KEYIO is not set.

imgui_internal.h

+14-46
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // E
169169
typedef int ImGuiActivateFlags; // -> enum ImGuiActivateFlags_ // Flags: for navigation/focus function (will be for ActivateItem() later)
170170
typedef int ImGuiDebugLogFlags; // -> enum ImGuiDebugLogFlags_ // Flags: for ShowDebugLogWindow(), g.DebugLogFlags
171171
typedef int ImGuiFocusRequestFlags; // -> enum ImGuiFocusRequestFlags_ // Flags: for FocusWindow();
172-
typedef int ImGuiInputFlags; // -> enum ImGuiInputFlags_ // Flags: for IsKeyPressed(), IsMouseClicked(), SetKeyOwner(), SetItemKeyOwner() etc.
173172
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag(), g.LastItemData.InFlags
174173
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for g.LastItemData.StatusFlags
175174
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
@@ -1442,15 +1441,13 @@ struct ImGuiKeyOwnerData
14421441
ImGuiKeyOwnerData() { OwnerCurr = OwnerNext = ImGuiKeyOwner_NoOwner; LockThisFrame = LockUntilRelease = false; }
14431442
};
14441443

1444+
// Extend ImGuiInputFlags_
14451445
// Flags for extended versions of IsKeyPressed(), IsMouseClicked(), Shortcut(), SetKeyOwner(), SetItemKeyOwner()
14461446
// Don't mistake with ImGuiInputTextFlags! (which is for ImGui::InputText() function)
1447-
enum ImGuiInputFlags_
1447+
enum ImGuiInputFlagsPrivate_
14481448
{
1449-
ImGuiInputFlags_None = 0,
1450-
14511449
// Flags for IsKeyPressed(), IsKeyChordPressed(), IsMouseClicked(), Shortcut()
14521450
// - Repeat mode
1453-
ImGuiInputFlags_Repeat = 1 << 0, // Enable repeat. Return true on successive repeats. Default for legacy IsKeyPressed(). NOT Default for legacy IsMouseClicked(). MUST BE == 1.
14541451
ImGuiInputFlags_RepeatRateDefault = 1 << 1, // Repeat rate: Regular (default)
14551452
ImGuiInputFlags_RepeatRateNavMove = 1 << 2, // Repeat rate: Fast
14561453
ImGuiInputFlags_RepeatRateNavTweak = 1 << 3, // Repeat rate: Faster
@@ -1472,33 +1469,6 @@ enum ImGuiInputFlags_
14721469
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.
14731470
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.
14741471

1475-
// Flags for Shortcut() and low-level SetShortcutRouting()
1476-
// - Routing Policies
1477-
// The general idea is that several callers register interest in a shortcut, and only one owner gets it.
1478-
// Parent -> call Shortcut(Ctrl+S) // When Parent is focused, Parent gets the shortcut.
1479-
// Child1 -> call Shortcut(Ctrl+S) // When Child1 is focused, Child1 gets the shortcut (Child1 overrides Parent shortcuts)
1480-
// Child2 -> no call // When Child2 is focused, Parent gets the shortcut.
1481-
// The whole system is order independent, so if Child1 does it calls before Parent results will be identical.
1482-
// This is an important property as it facilitate working with foreign code or larger codebase.
1483-
// - Visualize registered routes in 'Metrics->Inputs' and submitted routes in 'Debug Log->InputRouting'.
1484-
// - When a policy (except for _RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(),
1485-
// allowing the system to decide where to route the input among other route-aware calls.
1486-
// (* Using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key)).
1487-
// - Shortcut() uses ImGuiInputFlags_RouteFocused by default. Meaning that a Shortcut() call will register
1488-
// a route and only succeed when parent window is in the focus-stack and if no-one with a higher priority
1489-
// is claiming the same shortcut.
1490-
// - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute()
1491-
// e.g. if you have a tool window associated to a document, and you want document shortcuts to run when the tool is focused.
1492-
// - Priorities: GlobalHighest > Focused (if owner is active item) > GlobalOverFocused > Focused (if in focused window) > Global.
1493-
// - Can select only 1 policy among all available.
1494-
ImGuiInputFlags_RouteFocused = 1 << 12, // (Default) Honor focus route: Accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.
1495-
ImGuiInputFlags_RouteGlobal = 1 << 13, // Register route globally (normal priority: unless a focused window or active item registered the route) -> recommended Global priority.
1496-
ImGuiInputFlags_RouteGlobalOverFocused = 1 << 14, // Register route globally (higher priority: unless an active item registered the route, e.g. CTRL+A registered by InputText will take priority over this).
1497-
ImGuiInputFlags_RouteGlobalHighest = 1 << 15, // Register route globally (highest priority: unlikely you need to use that: will interfere with every active items, e.g. CTRL+A registered by InputText will be overridden by this)
1498-
ImGuiInputFlags_RouteAlways = 1 << 16, // Do not register route, poll keys directly.
1499-
// Routing polices: extra options
1500-
ImGuiInputFlags_RouteUnlessBgFocused = 1 << 17, // Global routes will not be applied if underlying background/void is focused (== no Dear ImGui windows are focused). Useful for overlay applications.
1501-
15021472
// [Internal] Mask of which function support which flags
15031473
ImGuiInputFlags_RepeatRateMask_ = ImGuiInputFlags_RepeatRateDefault | ImGuiInputFlags_RepeatRateNavMove | ImGuiInputFlags_RepeatRateNavTweak,
15041474
ImGuiInputFlags_RepeatUntilMask_ = ImGuiInputFlags_RepeatUntilRelease | ImGuiInputFlags_RepeatUntilKeyModsChange | ImGuiInputFlags_RepeatUntilKeyModsChangeFromNone | ImGuiInputFlags_RepeatUntilOtherKeyPress,
@@ -2014,7 +1984,7 @@ struct ImGuiContext
20141984
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
20151985
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
20161986

2017-
// [EXPERIMENTAL] Key/Input Ownership + Shortcut Routing system
1987+
// Key/Input Ownership + Shortcut Routing system
20181988
// - The idea is that instead of "eating" a given key, we can link to an owner.
20191989
// - Input query can then read input by specifying ImGuiKeyOwner_Any (== 0), ImGuiKeyOwner_NoOwner (== -1) or a custom ID.
20201990
// - Routing is requested ahead of time for a given chord (Key + Mods) and granted in NewFrame().
@@ -3275,23 +3245,21 @@ namespace ImGui
32753245
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button, ImGuiID owner_id);
32763246
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button, ImGuiID owner_id);
32773247

3278-
// [EXPERIMENTAL] Shortcut Routing
3279-
// - ImGuiKeyChord = a ImGuiKey optionally OR-red with ImGuiMod_Alt/ImGuiMod_Ctrl/ImGuiMod_Shift/ImGuiMod_Super.
3280-
// ImGuiKey_C (accepted by functions taking ImGuiKey or ImGuiKeyChord)
3281-
// ImGuiKey_C | ImGuiMod_Ctrl (accepted by functions taking ImGuiKeyChord)
3282-
// ONLY ImGuiMod_XXX values are legal to 'OR' with an ImGuiKey. You CANNOT 'OR' two ImGuiKey values.
3283-
// - When using one of the routing option, e.g. ImGuiInputFlags_RouteFocused:
3248+
// Shortcut Testing & Routing
3249+
// - Set Shortcut() and SetNextItemShortcut() in imgui.h
3250+
// - When a policy (except for ImGuiInputFlags_RouteAlways *) is set, Shortcut() will register itself with SetShortcutRouting(),
3251+
// allowing the system to decide where to route the input among other route-aware calls.
3252+
// (* using ImGuiInputFlags_RouteAlways is roughly equivalent to calling IsKeyChordPressed(key) and bypassing route registration and check)
3253+
// - When using one of the routing option:
3254+
// - The default route is ImGuiInputFlags_RouteFocused (accept inputs if window is in focus stack. Deep-most focused window takes inputs. ActiveId takes inputs over deep-most focused window.)
32843255
// - Routes are requested given a chord (key + modifiers) and a routing policy.
32853256
// - Routes are resolved during NewFrame(): if keyboard modifiers are matching current ones: SetKeyOwner() is called + route is granted for the frame.
3286-
// - One route may be granted to a single owner. When multiple requests are made we have policies to select the winning route (e.g. deep most window).
3257+
// - Each route may be granted to a single owner. When multiple requests are made we have policies to select the winning route (e.g. deep most window).
32873258
// - Multiple read sites may use the same owner id can all access the granted route.
32883259
// - When owner_id is 0 we use the current Focus Scope ID as a owner ID in order to identify our location.
3289-
// - TL;DR;
3290-
// - IsKeyChordPressed() compares mods + call IsKeyPressed() -> function has no side-effect.
3291-
// - Shortcut() submits a route then if currently can be routed calls IsKeyChordPressed() -> function has (desirable) side-effects.
3292-
// - Use Tools->Metrics/Debugger->Inputs to view input routes.
3293-
IMGUI_API void SetNextItemShortcut(ImGuiKeyChord key_chord);
3294-
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags = 0, ImGuiID owner_id = 0);
3260+
// - You can chain two unrelated windows in the focus stack using SetWindowParentWindowForFocusRoute()
3261+
// e.g. if you have a tool window associated to a document, and you want document shortcuts to run when the tool is focused.
3262+
IMGUI_API bool Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id);
32953263
IMGUI_API bool SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID owner_id); // owner_id needs to be explicit and cannot be 0
32963264
IMGUI_API bool TestShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id);
32973265
IMGUI_API ImGuiKeyRoutingData* GetShortcutRoutingData(ImGuiKeyChord key_chord);

0 commit comments

Comments
 (0)