Drags, Sliders: ongoing drags may be cancelled using Escape or Gamepad Triangle, reverting to the initial value. (#8564, #9534)
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 2ce0769..c095395 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -55,6 +55,8 @@
 - Drags, Sliders:
   - Fixed an overflow using `ImGuiSliderFlags_Logarithmic` with S32/S64 types which
     leads to clamped interactions. (#9526, #3361, #1823, #1316, #642) [@lailoken]
+  - Ongoing drags may be cancelled using Escape or Gamepad Triangle, reverting
+    to the initial value. (#8564, #9534)
 - TreeNode:
   - Fixed issues/asserts with 32+ deep trees when using ImGuiTreeNodeFlags_DrawLinesXXX
     features or other features requiring stack storage. (#9509) [@lasrod]
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 19d03d0..5de0dfb 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -2660,6 +2660,17 @@
     return true;
 }
 
+static bool ShortcutsForCancel(ImGuiID id)
+{
+    ImGuiContext& g = *GImGui;
+    bool is_cancel_with_keyboard = ImGui::Shortcut(ImGuiKey_Escape, ImGuiInputFlags_None, id);
+    bool is_cancel_with_gamepad = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0 && ImGui::Shortcut(ImGuiKey_NavGamepadCancel, ImGuiInputFlags_None, id);
+    //bool is_cancel_with_mouse = ImGui::IsMouseClicked(ImGuiMouseButton_Right, ImGuiInputFlags_None, id);
+    //if (is_cancel_with_mouse)
+    //    ImGui::SetKeyOwner(ImGuiKey_MouseRight, id);
+    return is_cancel_with_keyboard || is_cancel_with_gamepad; //|| is_cancel_with_mouse
+}
+
 bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
 {
     // Read imgui.cpp "API BREAKING CHANGES" section for 1.78 if you hit this assert.
@@ -2673,6 +2684,15 @@
             ClearActiveID();
         else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
             ClearActiveID();
+        if (ShortcutsForCancel(id) && g.ActiveId == id)
+        {
+            // Canceling action reverts to initial value
+            size_t data_size = DataTypeGetInfo(data_type)->Size;
+            bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
+            memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
+            ClearActiveID();
+            return value_changed;
+        }
     }
     if (g.ActiveId != id)
         return false;
@@ -3281,6 +3301,15 @@
             if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
                 ClearActiveID();
         }
+        if (ShortcutsForCancel(id) && g.ActiveId == id)
+        {
+            // Canceling action reverts to initial value
+            size_t data_size = DataTypeGetInfo(data_type)->Size;
+            bool value_changed = memcmp(p_v, &g.ActiveIdValueOnActivation, data_size);
+            memcpy(p_v, &g.ActiveIdValueOnActivation, data_size);
+            ClearActiveID();
+            return value_changed;
+        }
     }
 
     switch (data_type)