MultiSelect: Box-Select: Refactor into its own structure, designed for single-instance but closer to being reusable outside Multi-Select.

Kept same member names.
diff --git a/imgui.cpp b/imgui.cpp
index 8f9a8fb..d82d48c 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3083,8 +3083,8 @@
             float max_y = window->ClipRect.Max.y;
 
             // Add box selection range
-            if (ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect)
-                if (ms->Storage->Window == window && ms->Storage->BoxSelectActive)
+            if (ImGuiBoxSelectState* bs = &g.BoxSelectState)
+                if (bs->BoxSelectActive && bs->BoxSelectWindow == window)
                 {
                     // FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos.
                     // RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that.
@@ -3093,8 +3093,8 @@
                     max_y += g.Style.ItemSpacing.y;
 
                     // Box-select on 2D area requires different clipping.
-                    if (ms->BoxSelectUnclipMode)
-                        data->Ranges.push_back(ImGuiListClipperRange::FromPositions(ms->BoxSelectUnclipRect.Min.y, ms->BoxSelectUnclipRect.Max.y, 0, 0));
+                    if (bs->BoxSelectUnclipMode)
+                        data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->BoxSelectUnclipRect.Min.y, bs->BoxSelectUnclipRect.Max.y, 0, 0));
                 }
 
             const int off_min = (is_nav_request && g.NavMoveClipDir == ImGuiDir_Up) ? -1 : 0;
@@ -14997,6 +14997,8 @@
     // Details for MultiSelect
     if (TreeNode("MultiSelect", "MultiSelect (%d)", g.MultiSelectStorage.GetAliveCount()))
     {
+        ImGuiBoxSelectState* ms = &g.BoxSelectState;
+        Text("BoxSelect ID=0x%08X, Starting = %d, Active %d", ms->BoxSelectId, ms->BoxSelectStarting, ms->BoxSelectActive);
         for (int n = 0; n < g.MultiSelectStorage.GetMapSize(); n++)
             if (ImGuiMultiSelectState* state = g.MultiSelectStorage.TryGetMapData(n))
                 DebugNodeMultiSelectState(state);
diff --git a/imgui_internal.h b/imgui_internal.h
index 968a941..165e3c0 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -22,6 +22,7 @@
 // [SECTION] Navigation support
 // [SECTION] Typing-select support
 // [SECTION] Columns support
+// [SECTION] Box-select support
 // [SECTION] Multi-select support
 // [SECTION] Docking support
 // [SECTION] Viewport support
@@ -123,6 +124,7 @@
 struct ImRect;                      // An axis-aligned rectangle (2 points)
 struct ImDrawDataBuilder;           // Helper to build a ImDrawData instance
 struct ImDrawListSharedData;        // Data shared between all ImDrawList instances
+struct ImGuiBoxSelectState;         // Box-selection state (currently used by multi-selection, could potentially be used by others)
 struct ImGuiColorMod;               // Stacked color modifier, backup of modified data so we can restore it
 struct ImGuiContext;                // Main Dear ImGui context
 struct ImGuiContextHook;            // Hook for extensions like ImGuiTestEngine
@@ -1706,6 +1708,32 @@
 };
 
 //-----------------------------------------------------------------------------
+// [SECTION] Box-select support
+//-----------------------------------------------------------------------------
+
+struct ImGuiBoxSelectState
+{
+    // Active box-selection data (persistent, 1 active at a time)
+    ImGuiID                 BoxSelectId;
+    bool                    BoxSelectActive;
+    bool                    BoxSelectStarting;
+    bool                    BoxSelectFromVoid;
+    ImGuiKeyChord           BoxSelectKeyMods : 16;  // Latched key-mods for box-select logic.
+    ImVec2                  BoxSelectStartPosRel;   // Start position in window-relative space (to support scrolling)
+    ImVec2                  BoxSelectEndPosRel;     // End position in window-relative space
+    ImGuiWindow*            BoxSelectWindow;
+
+    // Temporary/Transient data
+    bool                    BoxSelectUnclipMode;    // Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
+    ImRect                  BoxSelectRectPrev;      // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
+    ImRect                  BoxSelectRectCurr;
+    ImRect                  BoxSelectUnclipRect;    // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
+    ImGuiSelectionUserData  BoxSelectLastitem;
+
+    ImGuiBoxSelectState()   { memset(this, 0, sizeof(*this)); }
+};
+
+//-----------------------------------------------------------------------------
 // [SECTION] Multi-select support
 //-----------------------------------------------------------------------------
 
@@ -1724,12 +1752,7 @@
     ImVec2                  ScopeRectMin;
     ImVec2                  BackupCursorMaxPos;
     ImGuiID                 BoxSelectId;
-    ImRect                  BoxSelectRectPrev;
-    ImRect                  BoxSelectRectCurr;  // Selection rectangle in absolute coordinates (derived every frame from Storage->BoxSelectStartPosRel + MousePos)
-    ImRect                  BoxSelectUnclipRect;// Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
-    ImGuiSelectionUserData  BoxSelectLastitem;
     ImGuiKeyChord           KeyMods;
-    bool                    BoxSelectUnclipMode;
     bool                    LoopRequestClear;
     bool                    LoopRequestSelectAll;
     bool                    IsEndIO;            // Set when switching IO from BeginMultiSelect() to EndMultiSelect() state.
@@ -1740,7 +1763,7 @@
     bool                    RangeDstPassedBy;   // Set by the item that matches NavJustMovedToId when IsSetRange is set.
 
     ImGuiMultiSelectTempData()  { Clear(); }
-    void Clear()            { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); BoxSelectLastitem = -1; } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
+    void Clear()            { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
     void ClearIO()          { IO.Requests.resize(0); IO.RangeSrcItem = IO.NavIdItem = (ImGuiSelectionUserData)-1; IO.NavIdSelected = IO.RangeSrcReset = false; }
 };
 
@@ -1755,15 +1778,7 @@
     ImGuiSelectionUserData  RangeSrcItem;       //
     ImGuiSelectionUserData  NavIdItem;          // SetNextItemSelectionUserData() value for NavId (if part of submitted items)
 
-    bool                    BoxSelectActive;
-    bool                    BoxSelectStarting;
-    bool                    BoxSelectFromVoid;
-    ImGuiKeyChord           BoxSelectKeyMods : 16; // Latched key-mods for box-select logic.
-    ImVec2                  BoxSelectStartPosRel;  // Start position in window-relative space (to support scrolling)
-    ImVec2                  BoxSelectEndPosRel;    // End position in window-relative space
-
-    ImGuiMultiSelectState() { Init(0); }
-    void Init(ImGuiID id)   { Window = NULL; ID = id; LastFrameActive = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; BoxSelectActive = BoxSelectStarting = BoxSelectFromVoid = false; BoxSelectKeyMods = 0; }
+    ImGuiMultiSelectState() { Window = NULL; ID = 0; LastFrameActive = 0; RangeSelected = NavIdSelected = -1; RangeSrcItem = NavIdItem = ImGuiSelectionUserData_Invalid; }
 };
 
 #endif // #ifdef IMGUI_HAS_MULTI_SELECT
@@ -2203,6 +2218,7 @@
     ImVector<ImGuiShrinkWidthItem>  ShrinkWidthBuffer;
 
     // Multi-Select state
+    ImGuiBoxSelectState             BoxSelectState;
     ImGuiMultiSelectTempData*       CurrentMultiSelect;
     int                             MultiSelectTempDataStacked; // Temporary multi-select data size (because we leave previous instances undestructed, we generally don't use MultiSelectTempData.Size)
     ImVector<ImGuiMultiSelectTempData> MultiSelectTempData;
@@ -3389,6 +3405,7 @@
     // Multi-Select API
     IMGUI_API void          MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
     IMGUI_API void          MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
+    inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.BoxSelectId == id && g.BoxSelectState.BoxSelectActive) ? &g.BoxSelectState : NULL; }
 
     // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
     IMGUI_API void          SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 050136a..7470b60 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -19,6 +19,7 @@
 // [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
 // [SECTION] Widgets: Selectable
 // [SECTION] Widgets: Typing-Select support
+// [SECTION] Widgets: Box-Select support
 // [SECTION] Widgets: Multi-Select support
 // [SECTION] Widgets: ListBox
 // [SECTION] Widgets: PlotLines, PlotHistogram
@@ -6788,7 +6789,7 @@
         if (!is_multi_select)
             return false;
         // Extra layer of "no logic clip" for box-select support
-        if (!g.CurrentMultiSelect->BoxSelectUnclipMode || !g.CurrentMultiSelect->BoxSelectUnclipRect.Overlaps(bb))
+        if (!g.BoxSelectState.BoxSelectUnclipMode || !g.BoxSelectState.BoxSelectUnclipRect.Overlaps(bb))
             return false;
     }
 
@@ -7110,40 +7111,22 @@
 #endif
 }
 
-
 //-------------------------------------------------------------------------
-// [SECTION] Widgets: Multi-Select support
+// [SECTION] Widgets: Box-Select support
 //-------------------------------------------------------------------------
-// - DebugLogMultiSelectRequests() [Internal]
 // - BoxSelectStart() [Internal]
 // - BoxSelectScrollWithMouseDrag() [Internal]
-// - BeginMultiSelect()
-// - EndMultiSelect()
-// - SetNextItemSelectionUserData()
-// - MultiSelectItemHeader() [Internal]
-// - MultiSelectItemFooter() [Internal]
-// - DebugNodeMultiSelectState() [Internal]
-// - ImGuiSelectionBasicStorage
 //-------------------------------------------------------------------------
 
-static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io)
+static void BoxSelectStart(ImGuiID id, ImGuiSelectionUserData clicked_item)
 {
     ImGuiContext& g = *GImGui;
-    for (const ImGuiSelectionRequest& req : io->Requests)
-    {
-        if (req.Type == ImGuiSelectionRequestType_Clear)     IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: Clear\n", function);
-        if (req.Type == ImGuiSelectionRequestType_SelectAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SelectAll\n", function);
-        if (req.Type == ImGuiSelectionRequestType_SetRange)  IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetRange %" IM_PRId64 "..%" IM_PRId64 " (0x%" IM_PRIX64 "..0x%" IM_PRIX64 ") = %d\n", function, req.RangeFirstItem, req.RangeLastItem, req.RangeFirstItem, req.RangeLastItem, req.RangeSelected);
-    }
-}
-
-static void BoxSelectStart(ImGuiMultiSelectState* storage, ImGuiSelectionUserData clicked_item)
-{
-    ImGuiContext& g = *GImGui;
-    storage->BoxSelectStarting = true; // Consider starting box-select.
-    storage->BoxSelectFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid);
-    storage->BoxSelectKeyMods = g.IO.KeyMods;
-    storage->BoxSelectStartPosRel = storage->BoxSelectEndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos);
+    ImGuiBoxSelectState* bs = &g.BoxSelectState;
+    bs->BoxSelectId = id;
+    bs->BoxSelectStarting = true; // Consider starting box-select.
+    bs->BoxSelectFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid);
+    bs->BoxSelectKeyMods = g.IO.KeyMods;
+    bs->BoxSelectStartPosRel = bs->BoxSelectEndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos);
 }
 
 static void BoxSelectScrollWithMouseDrag(ImGuiWindow* window, const ImRect& inner_r)
@@ -7165,6 +7148,31 @@
     }
 }
 
+
+//-------------------------------------------------------------------------
+// [SECTION] Widgets: Multi-Select support
+//-------------------------------------------------------------------------
+// - DebugLogMultiSelectRequests() [Internal]
+// - BeginMultiSelect()
+// - EndMultiSelect()
+// - SetNextItemSelectionUserData()
+// - MultiSelectItemHeader() [Internal]
+// - MultiSelectItemFooter() [Internal]
+// - DebugNodeMultiSelectState() [Internal]
+// - ImGuiSelectionBasicStorage
+//-------------------------------------------------------------------------
+
+static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSelectIO* io)
+{
+    ImGuiContext& g = *GImGui;
+    for (const ImGuiSelectionRequest& req : io->Requests)
+    {
+        if (req.Type == ImGuiSelectionRequestType_Clear)     IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: Clear\n", function);
+        if (req.Type == ImGuiSelectionRequestType_SelectAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SelectAll\n", function);
+        if (req.Type == ImGuiSelectionRequestType_SetRange)  IMGUI_DEBUG_LOG_SELECTION("[selection] %s: Request: SetRange %" IM_PRId64 "..%" IM_PRId64 " (0x%" IM_PRIX64 "..0x%" IM_PRIX64 ") = %d\n", function, req.RangeFirstItem, req.RangeLastItem, req.RangeFirstItem, req.RangeLastItem, req.RangeSelected);
+    }
+}
+
 // Return ImGuiMultiSelectIO structure. Lifetime: valid until corresponding call to EndMultiSelect().
 ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags)
 {
@@ -7245,50 +7253,57 @@
     }
 
     // Box-select handling: update active state.
-    ms->BoxSelectUnclipMode = false;
+    ImGuiBoxSelectState* bs = &g.BoxSelectState;
     if (flags & ImGuiMultiSelectFlags_BoxSelect)
     {
         ms->BoxSelectId = GetID("##BoxSelect");
         KeepAliveID(ms->BoxSelectId);
+    }
+    if ((flags & ImGuiMultiSelectFlags_BoxSelect) && ms->BoxSelectId == bs->BoxSelectId)
+    {
+        bs->BoxSelectUnclipMode = false;
 
         // BoxSelectStarting is set by MultiSelectItemFooter() when considering a possible box-select. We validate it here and lock geometry.
-        if (storage->BoxSelectStarting && IsMouseDragPastThreshold(0))
+        if (bs->BoxSelectStarting && IsMouseDragPastThreshold(0))
         {
-            storage->BoxSelectActive = true;
-            storage->BoxSelectStarting = false;
+            bs->BoxSelectActive = true;
+            bs->BoxSelectWindow = ms->Storage->Window;
+            bs->BoxSelectStarting = false;
             SetActiveID(ms->BoxSelectId, window);
-            if (storage->BoxSelectFromVoid && (storage->BoxSelectKeyMods & ImGuiMod_Shift) == 0)
+            if (bs->BoxSelectFromVoid && (bs->BoxSelectKeyMods & ImGuiMod_Shift) == 0)
                 request_clear = true;
         }
-        else if ((storage->BoxSelectStarting || storage->BoxSelectActive) && g.IO.MouseDown[0] == false)
+        else if ((bs->BoxSelectStarting || bs->BoxSelectActive) && g.IO.MouseDown[0] == false)
         {
-            storage->BoxSelectActive = storage->BoxSelectStarting = false;
+            bs->BoxSelectId = 0;
+            bs->BoxSelectActive = bs->BoxSelectStarting = false;
             if (g.ActiveId == ms->BoxSelectId)
                 ClearActiveID();
         }
-        if (storage->BoxSelectActive)
+        if (bs->BoxSelectActive)
         {
             // Current frame absolute prev/current rectangles are used to toggle selection.
             // They are derived from positions relative to scrolling space.
             const ImRect scope_rect = window->InnerClipRect;
-            ImVec2 start_pos_abs = WindowPosRelToAbs(window, storage->BoxSelectStartPosRel);
-            ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, storage->BoxSelectEndPosRel); // Clamped already
+            ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->BoxSelectStartPosRel);
+            ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->BoxSelectEndPosRel); // Clamped already
             ImVec2 curr_end_pos_abs = g.IO.MousePos;
             if (ms->Flags & ImGuiMultiSelectFlags_ScopeWindow)  // Box-select scrolling only happens with ScopeWindow
                 curr_end_pos_abs = ImClamp(curr_end_pos_abs, scope_rect.Min, scope_rect.Max);
-            ms->BoxSelectRectPrev.Min = ImMin(start_pos_abs, prev_end_pos_abs);
-            ms->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs);
-            ms->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs);
-            ms->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs);
+            bs->BoxSelectLastitem = -1;
+            bs->BoxSelectRectPrev.Min = ImMin(start_pos_abs, prev_end_pos_abs);
+            bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs);
+            bs->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs);
+            bs->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs);
 
             // Box-select 2D mode detects horizontal changes (vertical ones are already picked by Clipper)
             // Storing an extra rect used by widgets supporting box-select.
             if (flags & ImGuiMultiSelectFlags_BoxSelect2d)
-                if (ms->BoxSelectRectPrev.Min.x != ms->BoxSelectRectCurr.Min.x || ms->BoxSelectRectPrev.Max.x != ms->BoxSelectRectCurr.Max.x)
+                if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
                 {
-                    ms->BoxSelectUnclipRect = ms->BoxSelectRectPrev;
-                    ms->BoxSelectUnclipRect.Add(ms->BoxSelectRectCurr);
-                    ms->BoxSelectUnclipMode = true;
+                    bs->BoxSelectUnclipRect = bs->BoxSelectRectPrev;
+                    bs->BoxSelectUnclipRect.Add(bs->BoxSelectRectCurr);
+                    bs->BoxSelectUnclipMode = true;
                 }
 
             //GetForegroundDrawList()->AddRect(ms->BoxSelectNoClipRect.Min, ms->BoxSelectNoClipRect.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
@@ -7338,11 +7353,12 @@
             storage->NavIdSelected = -1;
         }
 
-        if ((ms->Flags & ImGuiMultiSelectFlags_BoxSelect) && storage->BoxSelectActive)
+        ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId);
+        if ((ms->Flags & ImGuiMultiSelectFlags_BoxSelect) && bs != NULL)
         {
             // Box-select: render selection rectangle
-            ms->Storage->BoxSelectEndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view
-            ImRect box_select_r = ms->BoxSelectRectCurr;
+            bs->BoxSelectEndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view
+            ImRect box_select_r = bs->BoxSelectRectCurr;
             box_select_r.ClipWith(scope_rect);
             window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
             window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavHighlight)); // FIXME-MULTISELECT: Styling
@@ -7353,6 +7369,8 @@
             //GetForegroundDrawList()->AddRect(scroll_r.Min, scroll_r.Max, IM_COL32(0, 255, 0, 255));
             if ((ms->Flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms->Flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0 && !scroll_r.Contains(g.IO.MousePos))
                 BoxSelectScrollWithMouseDrag(window, scroll_r);
+
+            bs->BoxSelectUnclipMode = false;
         }
     }
 
@@ -7365,8 +7383,8 @@
     if (scope_hovered && g.HoveredId == 0 && g.ActiveId == 0)
     {
         if (ms->Flags & ImGuiMultiSelectFlags_BoxSelect)
-            if (!storage->BoxSelectActive && !storage->BoxSelectStarting && g.IO.MouseClickedCount[0] == 1)
-                BoxSelectStart(storage, ImGuiSelectionUserData_Invalid);
+            if (!g.BoxSelectState.BoxSelectActive && !g.BoxSelectState.BoxSelectStarting && g.IO.MouseClickedCount[0] == 1)
+                BoxSelectStart(ms->BoxSelectId, ImGuiSelectionUserData_Invalid);
 
         if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickVoid)
             if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
@@ -7516,21 +7534,21 @@
     }
 
     // Box-select handling
-    if (ms->Storage->BoxSelectActive)
+    if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
     {
-        const bool rect_overlap_curr = ms->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
-        const bool rect_overlap_prev = ms->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
+        const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
+        const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
         if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
         {
             selected = !selected;
             ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, item_data, item_data };
             ImGuiSelectionRequest* prev_req = (ms->IO.Requests.Size > 0) ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL;
-            if (prev_req && prev_req->Type == ImGuiSelectionRequestType_SetRange && prev_req->RangeLastItem == ms->BoxSelectLastitem && prev_req->RangeSelected == selected)
+            if (prev_req && prev_req->Type == ImGuiSelectionRequestType_SetRange && prev_req->RangeLastItem == bs->BoxSelectLastitem && prev_req->RangeSelected == selected)
                 prev_req->RangeLastItem = item_data; // Merge span into same request
             else
                 ms->IO.Requests.push_back(req);
         }
-        ms->BoxSelectLastitem = item_data;
+        bs->BoxSelectLastitem = item_data;
     }
 
     // Right-click handling: this could be moved at the Selectable() level.
@@ -7558,8 +7576,8 @@
         // Box-select
         ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
         if (ms->Flags & ImGuiMultiSelectFlags_BoxSelect)
-            if (selected == false && !storage->BoxSelectActive && !storage->BoxSelectStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
-                BoxSelectStart(storage, item_data);
+            if (selected == false && !g.BoxSelectState.BoxSelectActive && !g.BoxSelectState.BoxSelectStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
+                BoxSelectStart(ms->BoxSelectId, item_data);
 
         //----------------------------------------------------------------------------------------
         // ACTION                      | Begin  | Pressed/Activated  | End
@@ -7645,7 +7663,6 @@
         return;
     Text("RangeSrcItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), RangeSelected = %d", storage->RangeSrcItem, storage->RangeSrcItem, storage->RangeSelected);
     Text("NavIdItem = %" IM_PRId64 " (0x%" IM_PRIX64 "), NavIdSelected = %d", storage->NavIdItem, storage->NavIdItem, storage->NavIdSelected);
-    Text("BoxSelect Starting = %d, Active %d", storage->BoxSelectStarting, storage->BoxSelectActive);
     TreePop();
 #else
     IM_UNUSED(storage);