RangeSelect/MultiSelect: Shallow tweaks/refactors.

Including moving IsFocused back internally for now.
diff --git a/imgui.h b/imgui.h
index 556cc20..cd50da5 100644
--- a/imgui.h
+++ b/imgui.h
@@ -2475,6 +2475,7 @@
 //   you may as well not bother with clipping, as the cost should be negligible (as least on Dear ImGui side).
 //   If you are not sure, always start without clipping and you can work your way to the more optimized version afterwards.
 // - The void* RangeSrc/RangeDst value represent a selectable object. They are the values you pass to SetNextItemSelectionData().
+//   Most likely you will want to store an index here.
 //   Storing an integer index is the easiest thing to do, as SetRange requests will give you two end points and you will need to interpolate
 //   between them to honor range selection. But the code never assume that sortable integers are used (you may store pointers to your object,
 //   and then from the pointer have your own way of iterating from RangeSrc to RangeDst).
@@ -2482,36 +2483,37 @@
 //   e.g. instructive selection (store a bool inside each object), external array (store an array aside from your objects),
 //   hash/map/set (store only selected items in a hash/map/set), or other structures (store indices in an interval tree), etc.
 // Usage flow:
-//   1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection state.
-//      It is because you need to pass its selection state (and you own selection) that we don't store this value in Dear ImGui.
-//      (For the initial frame or when resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*).
-//   2) Honor Clear/SelectAll requests by updating your selection data. [Only required if you are using a clipper in step 4]
-//   3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
-//      This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
-//      If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
-//   4) Submit your items with SetNextItemSelectionData() + Selectable()/TreeNode() calls.
-//      Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()).
-//      When cannot return a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggle" event instead.
-//   5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
-//   6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
+//   Begin
+//     1) Call BeginMultiSelect() with the last saved value of ->RangeSrc and its selection state.
+//        It is because you need to pass its selection state (and you own selection) that we don't store this value in Dear ImGui.
+//        (For the initial frame or when resetting your selection state: you may use the value for your first item or a "null" value that matches the type stored in your void*).
+//     2) Honor Clear/SelectAll requests by updating your selection data. Only required if you are using a clipper in step 4: but you can use same code as step 6 anyway.
+//   Loop
+//     3) Set RangeSrcPassedBy=true if the RangeSrc item is part of the items clipped before the first submitted/visible item. [Only required if you are using a clipper in step 4]
+//        This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
+//        If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrc) { data->RangeSrcPassedBy = true; }
+//     4) Submit your items with SetNextItemSelectionData() + Selectable()/TreeNode() calls.
+//        Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()).
+//        When cannot return a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggle" event instead.
+//   End
+//     5) Call EndMultiSelect(). Save the value of ->RangeSrc for the next frame (you may convert the value in a format that is safe for persistance)
+//     6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)
 // If you submit all items (no clipper), Step 2 and 3 and will be handled by Selectable() on a per-item basis.
 #define IMGUI_HAS_MULTI_SELECT      // Multi-Select/Range-Select WIP branch // <-- This is currently _not_ in the top of imgui.h to prevent merge conflicts.
 struct ImGuiMultiSelectData
 {
-    bool    IsFocused;              // Begin        // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
-    bool    RequestClear;           // Begin, End   // Request user to clear selection
-    bool    RequestSelectAll;       // Begin, End   // Request user to select all
-    bool    RequestSetRange;        // End          // Request user to set or clear selection in the [RangeSrc..RangeDst] range
-    bool    RangeSrcPassedBy;       // In loop      // (If clipping) Need to be set by user if RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
-    bool    RangeValue;             // End          // End: parameter from RequestSetRange request. True = Select Range, False = Unselect range.
-    void*   RangeSrc;               // Begin, End   // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
-    void*   RangeDst;               // End          // End: parameter from RequestSetRange request.
-    int     RangeDirection;         // End          // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
+    bool    RequestClear;           // Begin, End  // 1. Request user to clear selection
+    bool    RequestSelectAll;       // Begin, End  // 2. Request user to select all
+    bool    RequestSetRange;        //        End  // 3. Request user to set or clear selection in the [RangeSrc..RangeDst] range
+    bool    RangeSrcPassedBy;       //    Loop     // (If clipping) Need to be set by user if RangeSrc was part of the clipped set before submitting the visible items. Ignore if not clipping.
+    bool    RangeValue;             //        End  // End: parameter from RequestSetRange request. true = Select Range, false = Unselect Range.
+    void*   RangeSrc;               // Begin, End  // End: parameter from RequestSetRange request + you need to save this value so you can pass it again next frame. / Begin: this is the value you passed to BeginMultiSelect()
+    void*   RangeDst;               //        End  // End: parameter from RequestSetRange request.
+    int     RangeDirection;         //        End  // End: parameter from RequestSetRange request. +1 if RangeSrc came before RangeDst, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values.
 
     ImGuiMultiSelectData()  { Clear(); }
     void Clear()
     {
-        IsFocused = false;
         RequestClear = RequestSelectAll = RequestSetRange = RangeSrcPassedBy = RangeValue = false;
         RangeSrc = RangeDst = NULL;
         RangeDirection = 0;
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index e334d44..f0b9d5d 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -565,6 +565,7 @@
 static void ShowDemoWindowWidgets()
 {
     IMGUI_DEMO_MARKER("Widgets");
+    //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
     if (!ImGui::CollapsingHeader("Widgets"))
         return;
 
@@ -1254,6 +1255,7 @@
     }
 
     IMGUI_DEMO_MARKER("Widgets/Selectables");
+    //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
     if (ImGui::TreeNode("Selectables"))
     {
         // Selectable() has 2 overloads:
@@ -2605,26 +2607,28 @@
     }
 }
 
-// [Advanced] Helper class to simulate storage of a multi-selection state, used by the advanced multi-selection demos.
+// [Advanced] Helper class to simulate storage of a multi-selection state, used by the BeginMultiSelect() demos.
 // We use ImGuiStorage (simple key->value storage) to avoid external dependencies but it's probably not optimal.
 // To store a single-selection:
 // - You only need a single variable and don't need any of this!
 // To store a multi-selection, in your real application you could:
 // - Use intrusively stored selection (e.g. 'bool IsSelected' inside your object). This is by far the simplest
 //   way to store your selection data, but it means you cannot have multiple simultaneous views over your objects.
-//   This is what may of the simpler demos in this file are using (so they are not using this class).
-// - Otherwise, any externally stored unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
+//   This is what many of the simpler demos in this file are using (so they are not using this class).
+// - Use external storage: e.g. unordered_set/set/hash/map/interval trees (storing indices, objects id, etc.)
 //   are generally appropriate. Even a large array of bool might work for you...
 // - If you need to handle extremely large selections, it might be advantageous to support a "negative" mode in
-//   your storage, so "Select All" becomes "Negative=1, Clear" and then sparse unselect can add to the storage.
+//   your storage, so "Select All" becomes "Negative=1 + Clear" and then sparse unselect can add to the storage.
 // About RefItem:
-// - The MultiSelect API requires you to store information about the reference/pivot item (generally the last clicked item).
+// - The BeginMultiSelect() API requires you to store information about the reference/pivot item (generally the last clicked item).
 struct ExampleSelection
 {
-    ImGuiStorage                        Storage;
+    // Data
+    ImGuiStorage                        Storage;        // Selection set
     int                                 SelectionSize;  // Number of selected items (== number of 1 in the Storage, maintained by this class)
     int                                 RangeRef;       // Reference/pivot item (generally last clicked item)
 
+    // Functions
     ExampleSelection()                  { RangeRef = 0; Clear(); }
     void Clear()                        { Storage.Clear(); SelectionSize = 0; }
     bool GetSelected(int n) const       { return Storage.GetInt((ImGuiID)n, 0) != 0; }
@@ -2637,11 +2641,20 @@
     // you will need a way to iterate from one object to another given the ID you use.
     // You are likely to need some kind of data structure to convert 'view index' <> 'object ID'.
     // FIXME-MULTISELECT: Would be worth providing a demo of doing this.
-    // FIXME-MULTISELECT: SetRange() is currently very inefficient since it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
-    void SetRange(int n1, int n2, bool v)   { if (n2 < n1) { int tmp = n2; n2 = n1; n1 = tmp; } for (int n = n1; n <= n2; n++) SetSelected(n, v); }
-    void SelectAll(int count)               { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStorage::ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
+    // FIXME-MULTISELECT: This implementation of SetRange() is inefficient because it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
+    void SetRange(int a, int b, bool v) { if (b < a) { int tmp = b; b = a; a = tmp; } for (int n = a; n <= b; n++) SetSelected(n, v); }
+    void SelectAll(int count)           { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStorage::ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
+
+    // Apply requests coming from BeginMultiSelect() and EndMultiSelect(). Must be done in this order! Order->SelectAll->SetRange.
+    void ApplyRequests(ImGuiMultiSelectData* ms_data, int items_count)
+    {
+        if (ms_data->RequestClear)      { Clear(); }
+        if (ms_data->RequestSelectAll)  { SelectAll(items_count); }
+        if (ms_data->RequestSetRange)   { SetRange((int)(intptr_t)ms_data->RangeSrc, (int)(intptr_t)ms_data->RangeDst, ms_data->RangeValue ? 1 : 0); }
+    }
 };
 
+
 static void ShowDemoWindowMultiSelect()
 {
     IMGUI_DEMO_MARKER("Widgets/Selection State");
@@ -2710,8 +2723,7 @@
             {
                 ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape;
                 ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection.RangeRef, selection.GetSelected(selection.RangeRef));
-                if (multi_select_data->RequestClear)     { selection.Clear(); }
-                if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
+                selection.ApplyRequests(multi_select_data, ITEMS_COUNT);
 
                 for (int n = 0; n < ITEMS_COUNT; n++)
                 {
@@ -2732,9 +2744,7 @@
                 // Apply multi-select requests
                 multi_select_data = ImGui::EndMultiSelect();
                 selection.RangeRef = (int)(intptr_t)multi_select_data->RangeSrc;
-                if (multi_select_data->RequestClear)     { selection.Clear(); }
-                if (multi_select_data->RequestSelectAll) { selection.SelectAll(ITEMS_COUNT); }
-                if (multi_select_data->RequestSetRange)  { selection.SetRange((int)(intptr_t)multi_select_data->RangeSrc, (int)(intptr_t)multi_select_data->RangeDst, multi_select_data->RangeValue ? 1 : 0); }
+                selection.ApplyRequests(multi_select_data, ITEMS_COUNT);
 
                 ImGui::EndListBox();
             }
@@ -2749,7 +2759,7 @@
         // - Showcase having multiple multi-selection scopes in the same window.
         // - Showcase using inside a table.
         IMGUI_DEMO_MARKER("Widgets/Selection State/Multiple Selection (using BeginMultiSelect, advanced)");
-        ImGui::SetNextItemOpen(true, ImGuiCond_Once);
+        //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
         if (ImGui::TreeNode("Multiple Selection (using BeginMultiSelect, advanced)"))
         {
             // Options
@@ -2798,8 +2808,7 @@
                     else
                         flags |= ImGuiMultiSelectFlags_ClearOnClickWindowVoid;
                     ImGuiMultiSelectData* multi_select_data = ImGui::BeginMultiSelect(flags, (void*)(intptr_t)selection->RangeRef, selection->GetSelected(selection->RangeRef));
-                    if (multi_select_data->RequestClear)     { selection->Clear(); }
-                    if (multi_select_data->RequestSelectAll) { selection->SelectAll(ITEMS_COUNT); }
+                    selection->ApplyRequests(multi_select_data, ITEMS_COUNT);
 
                     if (multiple_selection_scopes)
                         ImGui::Text("Selection size: %d", selection->GetSelectionSize());   // Draw counter below Separator and after BeginMultiSelect()
@@ -2817,8 +2826,8 @@
                     clipper.Begin(ITEMS_COUNT);
                     while (clipper.Step())
                     {
-                        // IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeRef was passed over.
-                        if (clipper.DisplayStart > selection->RangeRef)
+                        // IF clipping is used you need to set 'RangeSrcPassedBy = true' if RangeSrc was passed over.
+                        if ((int)(intptr_t)multi_select_data->RangeSrc <= clipper.DisplayStart)
                             multi_select_data->RangeSrcPassedBy = true;
 
                         for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
@@ -2898,9 +2907,7 @@
                     // Apply multi-select requests
                     multi_select_data = ImGui::EndMultiSelect();
                     selection->RangeRef = (int)(intptr_t)multi_select_data->RangeSrc;
-                    if (multi_select_data->RequestClear)     { selection->Clear(); }
-                    if (multi_select_data->RequestSelectAll) { selection->SelectAll(ITEMS_COUNT); }
-                    if (multi_select_data->RequestSetRange)  { selection->SetRange((int)(intptr_t)multi_select_data->RangeSrc, (int)(intptr_t)multi_select_data->RangeDst, multi_select_data->RangeValue ? 1 : 0); }
+                    selection->ApplyRequests(multi_select_data, ITEMS_COUNT);
 
                     if (widget_type == WidgetType_TreeNode)
                         ImGui::PopStyleVar();
diff --git a/imgui_internal.h b/imgui_internal.h
index 96ba7bd..47b3b9a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1588,15 +1588,19 @@
 
 struct IMGUI_API ImGuiMultiSelectState
 {
-    ImGuiID                 FocusScopeId;           // Same as g.CurrentFocusScopeId (unless another selection scope was pushed manually)
+    ImGuiID                 FocusScopeId;           // Copied from g.CurrentFocusScopeId (unless another selection scope was pushed manually)
+    ImGuiMultiSelectFlags   Flags;
+    ImGuiKeyChord           KeyMods;
+    ImGuiWindow*            Window;
     ImGuiMultiSelectData    In;                     // The In requests are set and returned by BeginMultiSelect()
     ImGuiMultiSelectData    Out;                    // The Out requests are finalized and returned by EndMultiSelect()
+    bool                    IsFocused;              // Set if currently focusing the selection scope (any item of the selection). May be used if you have custom shortcut associated to selection.
     bool                    InRangeDstPassedBy;     // (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
     bool                    InRequestSetRangeNav;   // (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
     //ImRect                Rect;                   // Extent of selection scope between BeginMultiSelect() / EndMultiSelect(), used by ImGuiMultiSelectFlags_ClearOnClickRectVoid.
 
     ImGuiMultiSelectState() { Clear(); }
-    void Clear()            { FocusScopeId = 0; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
+    void Clear()            { FocusScopeId = 0; Flags = ImGuiMultiSelectFlags_None; KeyMods = ImGuiMod_None; Window = NULL; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
 };
 
 #endif // #ifdef IMGUI_HAS_MULTI_SELECT
@@ -1945,10 +1949,7 @@
     ImVec2                  NavWindowingAccumDeltaSize;
 
     // Range-Select/Multi-Select
-    ImGuiWindow*            MultiSelectEnabledWindow;           // FIXME-MULTISELECT: We currently don't support recursing/stacking multi-select
-    ImGuiMultiSelectFlags   MultiSelectFlags;
-    ImGuiMultiSelectState   MultiSelectState;
-    ImGuiKeyChord           MultiSelectKeyMods;
+    ImGuiMultiSelectState   MultiSelectState;                   // FIXME-MULTISELECT: We currently don't support recursing/stacking multi-select
 
     // Render
     float                   DimBgRatio;                         // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
@@ -2180,10 +2181,6 @@
         NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
         NavWindowingToggleLayer = false;
 
-        MultiSelectEnabledWindow = NULL;
-        MultiSelectFlags = ImGuiMultiSelectFlags_None;
-        MultiSelectKeyMods = ImGuiMod_None;
-
         DimBgRatio = 0.0f;
 
         DragDropActive = DragDropWithinSource = DragDropWithinTarget = false;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index d4362e3..5f7a286 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6212,7 +6212,7 @@
     const bool was_selected = selected;
 
     // Multi-selection support (header)
-    const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
+    const bool is_multi_select = (g.MultiSelectState.Window == window);
     if (is_multi_select)
     {
         MultiSelectItemHeader(id, &selected);
@@ -6545,7 +6545,7 @@
     if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemflags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
 
     // Multi-selection support (header)
-    const bool is_multi_select = (g.MultiSelectEnabledWindow == window);
+    const bool is_multi_select = (g.MultiSelectState.Window == window);
     const bool was_selected = selected;
     if (is_multi_select)
     {
@@ -6660,23 +6660,19 @@
     ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
 
-    IM_ASSERT(g.MultiSelectEnabledWindow == NULL);   // No recursion allowed yet (we could allow it if we deem it useful)
-    IM_ASSERT(g.MultiSelectFlags == 0);
-    IM_ASSERT(g.MultiSelectState.FocusScopeId == 0);
+    ImGuiMultiSelectState* ms = &g.MultiSelectState;
+    IM_ASSERT(ms->Window == NULL && ms->Flags == 0 && ms->FocusScopeId == 0);   // No recursion allowed yet (we could allow it if we deem it useful)
 
     // FIXME: BeginFocusScope()
-    ImGuiMultiSelectState* ms = &g.MultiSelectState;
     ms->Clear();
     ms->FocusScopeId = window->IDStack.back();
+    ms->Flags = flags;
+    ms->Window = window;
+    ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
     PushFocusScope(ms->FocusScopeId);
-    g.MultiSelectEnabledWindow = window;
-    g.MultiSelectFlags = flags;
-
-    // Report focus
-    ms->In.IsFocused = ms->Out.IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
 
     // Use copy of keyboard mods at the time of the request, otherwise we would requires mods to be held for an extra frame.
-    g.MultiSelectKeyMods = g.NavJustMovedToId ? g.NavJustMovedToKeyMods : g.IO.KeyMods;
+    ms->KeyMods = g.NavJustMovedToId ? g.NavJustMovedToKeyMods : g.IO.KeyMods;
 
     if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
     {
@@ -6688,14 +6684,14 @@
     // FIXME: Polling key mods after the fact (frame following the move request) is incorrect, but latching it would requires non-trivial change in MultiSelectItemFooter()
     if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData)
     {
-        if (g.MultiSelectKeyMods & ImGuiMod_Shift)
+        if (ms->KeyMods & ImGuiMod_Shift)
             ms->InRequestSetRangeNav = true;
-        if ((g.MultiSelectKeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
+        if ((ms->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
             ms->In.RequestClear = true;
     }
 
     // Shortcuts
-    if (ms->In.IsFocused)
+    if (ms->IsFocused)
     {
         // Select All helper shortcut (CTRL+A)
         // Note: we are comparing FocusScope so we don't need to be testing for IsWindowFocused()
@@ -6708,10 +6704,8 @@
                 ms->In.RequestClear = true;
     }
 
-#ifdef IMGUI_DEBUG_MULTISELECT
-    if (ms->In.RequestClear)     IMGUI_DEBUG_LOG("BeginMultiSelect: RequestClear\n");
-    if (ms->In.RequestSelectAll) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestSelectAll\n");
-#endif
+    //if (ms->In.RequestClear)     IMGUI_DEBUG_LOG("BeginMultiSelect: RequestClear\n");
+    //if (ms->In.RequestSelectAll) IMGUI_DEBUG_LOG("BeginMultiSelect: RequestSelectAll\n");
 
     return &ms->In;
 }
@@ -6724,27 +6718,25 @@
 
     // Clear selection when clicking void?
     // We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
-    if (g.MultiSelectFlags & ImGuiMultiSelectFlags_ClearOnClickWindowVoid)
+    if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickWindowVoid)
         if (IsWindowHovered() && g.HoveredId == 0)
             if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
             {
-                state->Out.RequestClear = true;
-                state->Out.RequestSelectAll = state->Out.RequestSetRange = false;
+                ms->Out.RequestClear = true;
+                ms->Out.RequestSelectAll = ms->Out.RequestSetRange = false;
             }
 
     // Unwind
-    if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
+    if (ms->Flags & ImGuiMultiSelectFlags_NoUnselect)
         ms->Out.RangeValue = true;
-    g.MultiSelectState.FocusScopeId = 0;
+    ms->FocusScopeId = 0;
+    ms->Window = NULL;
+    ms->Flags = ImGuiMultiSelectFlags_None;
     PopFocusScope();
-    g.MultiSelectEnabledWindow = NULL;
-    g.MultiSelectFlags = ImGuiMultiSelectFlags_None;
 
-#ifdef IMGUI_DEBUG_MULTISELECT
-    if (ms->Out.RequestClear)     IMGUI_DEBUG_LOG("EndMultiSelect: RequestClear\n");
-    if (ms->Out.RequestSelectAll) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSelectAll\n");
-    if (ms->Out.RequestSetRange)  IMGUI_DEBUG_LOG("EndMultiSelect: RequestSetRange %p..%p = %d\n", ms->Out.RangeSrc, ms->Out.RangeDst, ms->Out.RangeValue);
-#endif
+    //if (ms->Out.RequestClear)     IMGUI_DEBUG_LOG("EndMultiSelect: RequestClear\n");
+    //if (ms->Out.RequestSelectAll) IMGUI_DEBUG_LOG("EndMultiSelect: RequestSelectAll\n");
+    //if (ms->Out.RequestSetRange)  IMGUI_DEBUG_LOG("EndMultiSelect: RequestSetRange %p..%p = %d\n", ms->Out.RangeSrc, ms->Out.RangeDst, ms->Out.RangeValue);
 
     return &ms->Out;
 }
@@ -6788,13 +6780,13 @@
     if (ms->InRequestSetRangeNav)
     {
         IM_ASSERT(id != 0);
-        IM_ASSERT((g.MultiSelectKeyMods & ImGuiMod_Shift) != 0);
+        IM_ASSERT((ms->KeyMods & ImGuiMod_Shift) != 0);
         const bool is_range_dst = !ms->InRangeDstPassedBy && g.NavJustMovedToId == id;     // Assume that g.NavJustMovedToId is not clipped.
         if (is_range_dst)
             ms->InRangeDstPassedBy = true;
         if (is_range_src || is_range_dst || ms->In.RangeSrcPassedBy != ms->InRangeDstPassedBy)
             selected = ms->In.RangeValue;
-        else if ((g.MultiSelectKeyMods & ImGuiMod_Ctrl) == 0)
+        else if ((ms->KeyMods & ImGuiMod_Ctrl) == 0)
             selected = false;
     }
 
@@ -6810,11 +6802,11 @@
     void* item_data = g.NextItemData.SelectionData;
     g.NextItemData.FocusScopeId = 0;
 
+    const bool is_multiselect = (ms->Flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0;
     bool selected = *p_selected;
     bool pressed = *p_pressed;
-    const bool is_multiselect = (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoMultiSelect) == 0;
-    bool is_ctrl = (g.MultiSelectKeyMods & ImGuiMod_Ctrl) != 0;
-    bool is_shift = (g.MultiSelectKeyMods & ImGuiMod_Shift) != 0;
+    bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
+    bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
 
     // Auto-select as you navigate a list
     if (g.NavJustMovedToId == id)
@@ -6866,7 +6858,7 @@
         }
         else
         {
-            selected = (!is_ctrl || (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)) ? true : !selected;
+            selected = (!is_ctrl || (ms->Flags & ImGuiMultiSelectFlags_NoUnselect)) ? true : !selected;
             ms->Out.RangeSrc = ms->Out.RangeDst = item_data;
             ms->Out.RangeValue = selected;
         }
@@ -6903,7 +6895,7 @@
     }
 
     // Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
-    if (ms->Out.RangeSrc == item_data && is_ctrl && is_shift && is_multiselect && !(g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect))
+    if (ms->Out.RangeSrc == item_data && is_ctrl && is_shift && is_multiselect && !(ms->Flags & ImGuiMultiSelectFlags_NoUnselect))
         ms->Out.RangeValue = selected;
 
     *p_selected = selected;