MultiSelect: Transition to use FocusScope bits merged in master.

Preserve ability to shift+arrow into an item that is part of FocusScope but doesn't carry a selection without breaking selection.
diff --git a/imgui.cpp b/imgui.cpp
index 3cdd6fb..733a5df 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3822,7 +3822,6 @@
     g.MenusIdSubmittedThisFrame.clear();
     g.InputTextState.ClearFreeMemory();
     g.InputTextDeactivatedState.ClearFreeMemory();
-    g.MultiSelectScopeWindow = NULL;
 
     g.SettingsWindows.clear();
     g.SettingsHandlers.clear();
diff --git a/imgui_internal.h b/imgui_internal.h
index 41dac9c..dd58534 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1210,6 +1210,7 @@
     ImGuiNextItemDataFlags_HasOpen      = 1 << 1,
     ImGuiNextItemDataFlags_HasShortcut  = 1 << 2,
     ImGuiNextItemDataFlags_HasRefVal    = 1 << 3,
+    ImGuiNextItemDataFlags_HasSelectionData = 1 << 4,
 };
 
 struct ImGuiNextItemData
@@ -1217,6 +1218,7 @@
     ImGuiNextItemDataFlags      Flags;
     ImGuiItemFlags              ItemFlags;          // Currently only tested/used for ImGuiItemFlags_AllowOverlap.
     // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem()
+    ImGuiID                     FocusScopeId;       // Set by SetNextItemSelectionUserData() (!= 0 signify value has been set)
     ImGuiSelectionUserData      SelectionUserData;  // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values)
     float                       Width;              // Set by SetNextItemWidth()
     ImGuiKeyChord               Shortcut;           // Set by SetNextItemShortcut()
@@ -1713,13 +1715,14 @@
 
 struct IMGUI_API ImGuiMultiSelectState
 {
+    ImGuiID                 FocusScopeId;           // Same as CurrentWindow->DC.FocusScopeIdCurrent (unless another selection scope was pushed manually)
     ImGuiMultiSelectData    In;                     // The In requests are set and returned by BeginMultiSelect()
     ImGuiMultiSelectData    Out;                    // The Out requests are finalized and returned by EndMultiSelect()
     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.
 
     ImGuiMultiSelectState() { Clear(); }
-    void Clear() { In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
+    void Clear()            { FocusScopeId = 0; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
 };
 
 #endif // #ifdef IMGUI_HAS_MULTI_SELECT
@@ -2117,10 +2120,9 @@
     ImVec2                  NavWindowingAccumDeltaSize;
 
     // Range-Select/Multi-Select
-    ImGuiID                 MultiSelectScopeId;
-    ImGuiWindow*            MultiSelectScopeWindow;
+    bool                    MultiSelectEnabled;
     ImGuiMultiSelectFlags   MultiSelectFlags;
-    ImGuiMultiSelectState   MultiSelectState;
+    ImGuiMultiSelectState   MultiSelectState;                   // 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)
@@ -2385,9 +2387,8 @@
         NavWindowingToggleLayer = false;
         NavWindowingToggleKey = ImGuiKey_None;
 
-        MultiSelectScopeId = 0;
-        MultiSelectScopeWindow = NULL;
-        MultiSelectFlags = 0;
+        MultiSelectEnabled = false;
+        MultiSelectFlags = ImGuiMultiSelectFlags_None;
 
         DimBgRatio = 0.0f;
 
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 62b063d..4da2569 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6466,7 +6466,7 @@
     const bool was_selected = selected;
 
     // Multi-selection support (header)
-    const bool is_multi_select = (g.MultiSelectScopeWindow == window);
+    const bool is_multi_select = g.MultiSelectEnabled;
     if (is_multi_select)
     {
         flags |= ImGuiTreeNodeFlags_OpenOnArrow;
@@ -6814,7 +6814,7 @@
     if ((flags & ImGuiSelectableFlags_AllowOverlap) || (g.LastItemData.InFlags & ImGuiItemFlags_AllowOverlap)) { button_flags |= ImGuiButtonFlags_AllowOverlap; }
 
     // Multi-selection support (header)
-    const bool is_multi_select = (g.MultiSelectScopeWindow == window);
+    const bool is_multi_select = g.MultiSelectEnabled;
     const bool was_selected = selected;
     if (is_multi_select)
     {
@@ -7120,17 +7120,20 @@
 
 ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected)
 {
-    ImGuiContext& g = *ImGui::GetCurrentContext();
+    ImGuiContext& g = *GImGui;
     ImGuiWindow* window = g.CurrentWindow;
 
-    IM_ASSERT(g.MultiSelectScopeId == 0);    // No recursion allowed yet (we could allow it if we deem it useful)
+    IM_ASSERT(g.MultiSelectEnabled == false);   // No recursion allowed yet (we could allow it if we deem it useful)
     IM_ASSERT(g.MultiSelectFlags == 0);
+    IM_ASSERT(g.MultiSelectState.FocusScopeId == 0);
 
+    // FIXME: BeginFocusScope()
     ImGuiMultiSelectState* ms = &g.MultiSelectState;
-    g.MultiSelectScopeId = window->IDStack.back();
-    g.MultiSelectScopeWindow = window;
-    g.MultiSelectFlags = flags;
     ms->Clear();
+    ms->FocusScopeId = window->IDStack.back();
+    PushFocusScope(ms->FocusScopeId);
+    g.MultiSelectEnabled = true;
+    g.MultiSelectFlags = flags;
 
     if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
     {
@@ -7139,7 +7142,7 @@
     }
 
     // Auto clear when using Navigation to move within the selection (we compare SelectScopeId so it possible to use multiple lists inside a same window)
-    if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.MultiSelectScopeId)
+    if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData)
     {
         if (g.IO.KeyShift)
             ms->InRequestSetRangeNav = true;
@@ -7162,14 +7165,16 @@
 
 ImGuiMultiSelectData* ImGui::EndMultiSelect()
 {
-    ImGuiContext& g = *ImGui::GetCurrentContext();
+    ImGuiContext& g = *GImGui;
     ImGuiMultiSelectState* ms = &g.MultiSelectState;
-    IM_ASSERT(g.MultiSelectScopeId != 0);
+    IM_ASSERT(g.MultiSelectState.FocusScopeId == g.CurrentFocusScopeId);
+
     if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
         ms->Out.RangeValue = true;
-    g.MultiSelectScopeId = 0;
-    g.MultiSelectScopeWindow = NULL;
-    g.MultiSelectFlags = 0;
+    g.MultiSelectState.FocusScopeId = 0;
+    PopFocusScope();
+    g.MultiSelectEnabled = false;
+    g.MultiSelectFlags = ImGuiMultiSelectFlags_None;
 
 #ifdef IMGUI_DEBUG_MULTISELECT
     if (ms->Out.RequestClear)     printf("[%05d] EndMultiSelect: RequestClear\n", g.FrameCount);
@@ -7185,18 +7190,22 @@
     // Note that flags will be cleared by ItemAdd(), so it's only useful for Navigation code!
     // This designed so widgets can also cheaply set this before calling ItemAdd(), so we are not tied to MultiSelect api.
     ImGuiContext& g = *GImGui;
-    if (g.MultiSelectScopeId != 0)
+    if (g.MultiSelectState.FocusScopeId != 0)
         g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
     else
         g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData;
     g.NextItemData.SelectionUserData = selection_user_data;
+    g.NextItemData.FocusScopeId = g.CurrentFocusScopeId;
 }
 
 void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected)
 {
     ImGuiContext& g = *GImGui;
+    ImGuiWindow* window = g.CurrentWindow;
     ImGuiMultiSelectState* ms = &g.MultiSelectState;
 
+    IM_UNUSED(window);
+    IM_ASSERT(g.NextItemData.FocusScopeId == g.CurrentFocusScopeId && "Forgot to call SetNextItemSelectionUserData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
     IM_ASSERT((g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid) && "Forgot to call SetNextItemSelectionUserData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
     void* item_data = (void*)g.NextItemData.SelectionUserData;