Lines Matching refs:window
49 - How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
98 - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window,.
109 - Double-click on title bar to collapse window.
110 - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin().
111 - Click and drag on lower right corner to resize window (double-click to auto fit window to its contents).
112 - Click and drag on any empty space to move window.
254 MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End();
343 - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
384 - 2018/08/01 (1.63) - removed per-window ImGuiWindowFlags_ResizeFromAnySide beta flag in favor of a global io.ConfigResizeWindowsFromEdges [update 1.67 renamed to ConfigWindowsResizeFromEdges] to enable the feature.
420 - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set.
427 - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up.
434 - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it.
453 - changed prototype of 'ColorEdit4(const char* label, float col[4], bool show_alpha = true)' to 'ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)', where passing flags = 0x01 is a safe no-op (hello dodgy backward compatibility!). - check and run the demo window, under "Color/Picker Widgets", to understand the various new options.
461 - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal.
462 - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore.
484 GetCursorPos()/SetCursorPos() functions now include the scrolled amount. It shouldn't affect the majority of users, but take note that SetCursorPosX(100.0f) puts you at +100 from the starting x position which may include scrolling, not at +100 from the window left side.
560 Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!).
561 It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs.
704 you to animate labels. For example you may want to include varying information in a window title bar,
715 within the same window. This is the most convenient way of distinguishing ID when iterating and
847 Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for
872 Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
873 A: - You can create a dummy window. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags.
913 - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window.
914 this is also useful to set yourself in the context of another window (to get/set other settings)
915 - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug".
943 #define IMGUI_DEBUG_NAV_RECTS 0 // Display the reference navigation rectangle for each window
983 static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
993 static void SetCurrentWindow(ImGuiWindow* window);
996 static void CheckStacksSize(ImGuiWindow* window, bool write);
997 static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges);
1000 static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window);
1025 static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
1028 static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
1033 static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]);
1034 static void RenderOuterBorders(ImGuiWindow* window);
1046 // In your debugger, add GImGui to your watch window and notice how its value changes depending on which location you are currently stepping into.
1082 WindowPadding = ImVec2(8,8); // Padding within a window
1083 WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
1085 WindowMinSize = ImVec2(32,32); // Minimum window size
1087 ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
1089 PopupRounding = 0.0f; // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
2192 ImGuiWindow* window = ImGui::GetCurrentWindow();
2193 window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
2194 window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
2195 if (window->DC.ColumnsSet)
2196 window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
2288 ImGuiWindow* window = g.CurrentWindow;
2305 window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end);
2314 ImGuiWindow* window = g.CurrentWindow;
2321 window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_end, wrap_width);
2366 ImGuiWindow* window = g.CurrentWindow;
2367 RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
2376 ImGuiWindow* window = g.CurrentWindow;
2377 window->DrawList->AddRectFilled(p_min, p_max, fill_col, rounding);
2381 window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2382 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2389 ImGuiWindow* window = g.CurrentWindow;
2393 window->DrawList->AddRect(p_min+ImVec2(1,1), p_max+ImVec2(1,1), GetColorU32(ImGuiCol_BorderShadow), rounding, ImDrawCornerFlags_All, border_size);
2394 window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
2436 ImGuiWindow* window = g.CurrentWindow;
2437 window->DrawList->AddCircleFilled(pos, g.FontSize*0.20f, GetColorU32(ImGuiCol_Text), 8);
2443 ImGuiWindow* window = g.CurrentWindow;
2452 window->DrawList->PathLineTo(ImVec2(bx - third, by - third));
2453 window->DrawList->PathLineTo(ImVec2(bx, by));
2454 window->DrawList->PathLineTo(ImVec2(bx + third*2, by - third*2));
2455 window->DrawList->PathStroke(col, false, thickness);
2465 ImGuiWindow* window = g.CurrentWindow;
2466 if (window->DC.NavHideHighlightOneFrame)
2471 display_rect.ClipWith(window->ClipRect);
2477 bool fully_visible = window->ClipRect.Contains(display_rect);
2479 window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
2480 window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS);
2482 window->DrawList->PopClipRect();
2486 window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f);
2604 static void SetCurrentWindow(ImGuiWindow* window)
2607 g.CurrentWindow = window;
2608 if (window)
2609 g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
2631 void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
2650 g.ActiveIdWindow = window;
2659 void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
2665 const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
2666 if (g.NavWindow != window)
2669 g.NavWindow = window;
2671 window->NavLastIds[nav_layer] = id;
2672 if (window->DC.LastItemId == id)
2673 window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos);
2722 static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
2725 // FIXME-OPT: This could be cached/stored within the window.
2729 if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
2746 ImGuiWindow* window = g.CurrentWindow;
2747 if (window->SkipItems)
2751 const float line_height = ImMax(window->DC.CurrentLineSize.y, size.y);
2752 const float text_base_offset = ImMax(window->DC.CurrentLineTextBaseOffset, text_offset_y);
2753 //if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
2754 window->DC.CursorPosPrevLine = ImVec2(window->DC.CursorPos.x + size.x, window->DC.CursorPos.y);
2755 window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
2756 window->DC.CursorPos.y = (float)(int)(window->DC.CursorPos.y + line_height + g.Style.ItemSpacing.y);
2757 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPosPrevLine.x);
2758 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y - g.Style.ItemSpacing.y);
2759 //if (g.IO.KeyAlt) window->DrawList->AddCircle(window->DC.CursorMaxPos, 3.0f, IM_COL32(255,0,0,255), 4); // [DEBUG]
2761 window->DC.PrevLineSize.y = line_height;
2762 window->DC.PrevLineTextBaseOffset = text_base_offset;
2763 window->DC.CurrentLineSize.y = window->DC.CurrentLineTextBaseOffset = 0.0f;
2766 if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
2781 ImGuiWindow* window = g.CurrentWindow;
2787 // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window.
2790 window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask;
2792 if (g.NavWindow->RootWindowForNav == window->RootWindowForNav)
2793 if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened))
2794 NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id);
2797 window->DC.LastItemId = id;
2798 window->DC.LastItemRect = bb;
2799 window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
2810 //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
2814 window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;
2819 // - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered()
2824 ImGuiWindow* window = g.CurrentWindow;
2829 if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
2833 // Test if we are hovering the right window (our window could be behind another window)
2836 //if (g.HoveredWindow != window)
2838 if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
2843 if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
2846 // Test if interactions on this window are blocked by an active popup or modal
2847 if (!IsWindowContentHoverable(window, flags))
2851 if ((window->DC.ItemFlags & ImGuiItemFlags_Disabled) && !(flags & ImGuiHoveredFlags_AllowWhenDisabled))
2855 // When the window is collapsed (SkipItems==true) that last item will never be overwritten so we need to detect the case.
2856 if (window->DC.LastItemId == window->MoveId && window->WriteAccessed)
2868 ImGuiWindow* window = g.CurrentWindow;
2869 if (g.HoveredWindow != window)
2875 if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
2877 if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
2887 ImGuiWindow* window = g.CurrentWindow;
2888 if (!bb.Overlaps(window->ClipRect))
2895 bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop)
2899 const bool is_tab_stop = (window->DC.ItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
2900 window->FocusIdxAllCounter++;
2902 window->FocusIdxTabCounter++;
2906 if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab))
2907 window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (is_tab_stop ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items.
2909 if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent)
2911 if (is_tab_stop && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent)
2920 void ImGui::FocusableItemUnregister(ImGuiWindow* window)
2922 window->FocusIdxAllCounter--;
2923 window->FocusIdxTabCounter--;
2944 ImGuiWindow* window = GetCurrentWindowRead();
2946 wrap_pos_x = GetContentRegionMax().x + window->Pos.x;
2948 wrap_pos_x += window->Pos.x - window->Scroll.x; // wrap_pos_x is provided is window local space
3085 void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
3087 // Set ActiveId even if the _NoMove flag is set. Without it, dragging away from a window with _NoMove would activate hover on other windows.
3088 // We _also_ call this when clicking in a window empty space when io.ConfigWindowsMoveFromTitleBarOnly is set, but clear g.MovingWindow afterward.
3089 // This is because we want ActiveId to be set even when the window is not permitted to move.
3091 FocusWindow(window);
3092 SetActiveID(window->MoveId, window);
3094 g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
3097 if ((window->Flags & ImGuiWindowFlags_NoMove) || (window->RootWindow->Flags & ImGuiWindowFlags_NoMove))
3100 g.MovingWindow = window;
3103 // Handle mouse moving window
3104 // Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
3110 // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window).
3133 // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others.
3143 // Initiate moving window, handle left-click and right-click focus
3146 // Initiate moving window
3151 // Unless we just made a window/popup appear
3155 // Click to focus window and start moving (after we're done with all our widgets)
3176 // Find the top-most window between HoveredWindow and the front most Modal Window.
3184 ImGuiWindow* window = g.Windows[i];
3185 if (window == modal)
3187 if (window == g.HoveredWindow)
3194 static bool IsWindowActiveAndVisible(ImGuiWindow* window)
3196 return (window->Active) && (!window->Hidden);
3261 // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set).
3262 ImGuiWindow* window = g.HoveredWindow;
3263 ImGuiWindow* scroll_window = window;
3272 // Zoom / Scale window
3273 const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f);
3274 const float scale = new_font_scale / window->FontWindowScale;
3275 window->FontWindowScale = new_font_scale;
3277 const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size;
3278 window->Pos += offset;
3279 window->Size *= scale;
3280 window->SizeFull *= scale;
3303 // Find the window hovered by mouse:
3305 // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
3306 // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
3319 // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward.
3484 // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
3496 g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
3515 ImGuiWindow* window = g.Windows[i];
3516 window->WasActive = window->Active;
3517 window->Active = false;
3518 window->WriteAccessed = false;
3521 // Closing the focused window restore focus to the first active root window in descending z-order
3525 // No window should be open at the beginning of the frame.
3531 // Create implicit/fallback window - which we will only render it if the user has added something to it.
3532 // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
3625 // FIXME: Add a more explicit sort order in the window structure.
3637 static void AddWindowToSortBuffer(ImVector<ImGuiWindow*>* out_sorted_windows, ImGuiWindow* window)
3639 out_sorted_windows->push_back(window);
3640 if (window->Active)
3642 int count = window->DC.ChildWindows.Size;
3644 ImQsort(window->DC.ChildWindows.begin(), (size_t)count, sizeof(ImGuiWindow*), ChildWindowComparer);
3647 ImGuiWindow* child = window->DC.ChildWindows[i];
3673 // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
3675 // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents.
3687 static void AddWindowToDrawData(ImVector<ImDrawList*>* out_render_list, ImGuiWindow* window)
3691 AddDrawListToDrawData(out_render_list, window->DrawList);
3692 for (int i = 0; i < window->DC.ChildWindows.Size; i++)
3694 ImGuiWindow* child = window->DC.ChildWindows[i];
3700 static void AddRootWindowToDrawData(ImGuiWindow* window)
3703 if (window->Flags & ImGuiWindowFlags_Tooltip)
3704 AddWindowToDrawData(&g.DrawDataBuilder.Layers[1], window);
3706 AddWindowToDrawData(&g.DrawDataBuilder.Layers[0], window);
3747 ImGuiWindow* window = GetCurrentWindow();
3748 window->DrawList->PushClipRect(clip_rect_min, clip_rect_max, intersect_with_current_clip_rect);
3749 window->ClipRect = window->DrawList->_ClipRectStack.back();
3754 ImGuiWindow* window = GetCurrentWindow();
3755 window->DrawList->PopClipRect();
3756 window->ClipRect = window->DrawList->_ClipRectStack.back();
3791 // Hide implicit/fallback "Debug" window if it hasn't been used
3797 // Show CTRL+TAB list window
3822 // Initiate moving window + handle left-click and right-click focus
3825 // Sort the window list so that all child windows are after their parent
3831 ImGuiWindow* window = g.Windows[i];
3832 if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it
3834 AddWindowToSortBuffer(&g.WindowsSortBuffer, window);
3860 // Gather ImDrawList to render (for each active window)
3868 ImGuiWindow* window = g.Windows[n];
3869 if (IsWindowActiveAndVisible(window) && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != windows_to_render_front_most[0] && window != windows_to_render_front_most[1])
3870 AddRootWindowToDrawData(window);
3873 if (windows_to_render_front_most[n] && IsWindowActiveAndVisible(windows_to_render_front_most[n])) // NavWindowingTarget is always temporarily displayed as the front-most window
3926 ImGuiWindow* window = g.CurrentWindow;
3934 if (window->SkipItems)
3941 ImRect unclipped_rect = window->ClipRect;
3945 const ImVec2 pos = window->DC.CursorPos;
3961 // Find window given position, search front-to-back
3964 // called, aka before the next Begin(). Moving window isn't affected.
3977 ImGuiWindow* window = g.Windows[i];
3978 if (!window->Active || window->Hidden)
3980 if (window->Flags & ImGuiWindowFlags_NoMouseInputs)
3983 // Using the clipped AABB, a child window will typically be clipped by its parent (not always)
3984 ImRect bb(window->OuterRectClipped);
3985 if ((window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_NoResize))
3994 hovered_window = window;
4165 // NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window.
4211 ImGuiWindow* window = g.CurrentWindow;
4212 return g.ActiveId == window->DC.LastItemId;
4222 ImGuiWindow* window = g.CurrentWindow;
4223 if (g.ActiveId == window->DC.LastItemId && g.ActiveIdPreviousFrame != window->DC.LastItemId)
4232 ImGuiWindow* window = g.CurrentWindow;
4233 return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
4245 ImGuiWindow* window = g.CurrentWindow;
4247 if (g.NavId == 0 || g.NavDisableHighlight || g.NavId != window->DC.LastItemId)
4277 ImGuiWindow* window = GetCurrentWindowRead();
4278 return window->ClipRect.Overlaps(window->DC.LastItemRect);
4283 ImGuiWindow* window = GetCurrentWindowRead();
4284 return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Edited) != 0;
4299 ImGuiWindow* window = GetCurrentWindowRead();
4300 return window->DC.LastItemRect.Min;
4305 ImGuiWindow* window = GetCurrentWindowRead();
4306 return window->DC.LastItemRect.Max;
4311 ImGuiWindow* window = GetCurrentWindowRead();
4312 return window->DC.LastItemRect.GetSize();
4374 ImGuiWindow* window = GetCurrentWindow();
4375 return BeginChildEx(str_id, window->GetID(str_id), size_arg, border, extra_flags);
4387 ImGuiWindow* window = g.CurrentWindow;
4389 IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss
4390 if (window->BeginCount > 1)
4396 ImVec2 sz = window->Size;
4397 if (window->AutoFitChildAxises & (1 << ImGuiAxis_X)) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f
4399 if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y))
4406 if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened))
4408 ItemAdd(bb, window->ChildId);
4409 RenderNavHighlight(bb, window->ChildId);
4411 // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
4412 if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow)
4423 // Helper to create a child window / scrolling region that looks like a normal widget frame.
4444 static void CheckStacksSize(ImGuiWindow* window, bool write)
4446 // NOT checking: DC.ItemWidth, DC.AllowKeyboardFocus, DC.ButtonRepeat, DC.TextWrapPos (per window) to allow user to conveniently push once and not pop (they are cleared on Begin)
4448 short* p_backup = &window->DC.StackSizesBackup[0];
4449 { int current = window->IDStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "PushID/PopID or TreeNode/TreePop Mismatch!"); p_backup++; } // Too few or too many PopID()/TreePop()
4450 { int current = window->DC.GroupStack.Size; if (write) *p_backup = (short)current; else IM_ASSERT(*p_backup == current && "BeginGroup/EndGroup Mismatch!"); p_backup++; } // Too few or too many EndGroup()
4456 IM_ASSERT(p_backup == window->DC.StackSizesBackup + IM_ARRAYSIZE(window->DC.StackSizesBackup));
4459 static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
4461 window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
4462 window->SetWindowSizeAllowFlags = enabled ? (window->SetWindowSizeAllowFlags | flags) : (window->SetWindowSizeAllowFlags & ~flags);
4463 window->SetWindowCollapsedAllowFlags = enabled ? (window->SetWindowCollapsedAllowFlags | flags) : (window->SetWindowCollapsedAllowFlags & ~flags);
4482 // Create window the first time
4483 ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name);
4484 window->Flags = flags;
4485 g.WindowsById.SetVoidPtr(window->ID, window);
4487 // Default/arbitrary window position. Use SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
4488 window->Pos = ImVec2(60, 60);
4492 if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
4495 window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
4496 SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
4497 window->Pos = ImFloor(settings->Pos);
4498 window->Collapsed = settings->Collapsed;
4502 window->Size = window->SizeFull = window->SizeFullAtLastBegin = ImFloor(size);
4503 window->DC.CursorMaxPos = window->Pos; // So first call to CalcSizeContents() doesn't return crazy values
4507 window->AutoFitFramesX = window->AutoFitFramesY = 2;
4508 window->AutoFitOnlyGrows = false;
4512 if (window->Size.x <= 0.0f)
4513 window->AutoFitFramesX = 2;
4514 if (window->Size.y <= 0.0f)
4515 window->AutoFitFramesY = 2;
4516 window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
4519 g.WindowsFocusOrder.push_back(window);
4521 g.Windows.push_front(window); // Quite slow but rare and only once
4523 g.Windows.push_back(window);
4524 return window;
4527 static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size)
4534 new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x;
4535 new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y;
4540 data.Pos = window->Pos;
4541 data.CurrentSize = window->SizeFull;
4549 if (!(window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysAutoResize)))
4552 new_size.y = ImMax(new_size.y, window->TitleBarHeight() + window->MenuBarHeight() + ImMax(0.0f, g.Style.WindowRounding - 1.0f)); // Reduce artifacts with very small windows
4557 static ImVec2 CalcSizeContents(ImGuiWindow* window)
4559 if (window->Collapsed)
4560 if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
4561 return window->SizeContents;
4562 if (window->Hidden && window->HiddenFramesForResize == 0 && window->HiddenFramesRegular > 0)
4563 return window->SizeContents;
4566 sz.x = (float)(int)((window->SizeContentsExplicit.x != 0.0f) ? window->SizeContentsExplicit.x : (window->DC.CursorMaxPos.x - window->Pos.x + window->Scroll.x));
4567 sz.y = (float)(int)((window->SizeContentsExplicit.y != 0.0f) ? window->SizeContentsExplicit.y : (window->DC.CursorMaxPos.y - window->Pos.y + window->Scroll.y));
4568 return sz + window->WindowPadding;
4571 static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
4575 if (window->Flags & ImGuiWindowFlags_Tooltip)
4582 // Maximum window size is determined by the display size
4583 const bool is_popup = (window->Flags & ImGuiWindowFlags_Popup) != 0;
4584 const bool is_menu = (window->Flags & ImGuiWindowFlags_ChildMenu) != 0;
4590 // When the window cannot fit all contents (either because of constraints, either because screen is too small),
4592 ImVec2 size_auto_fit_after_constraint = CalcSizeAfterConstraint(window, size_auto_fit);
4593 if (size_auto_fit_after_constraint.x < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar))
4595 if (size_auto_fit_after_constraint.y < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar))
4601 ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window)
4603 ImVec2 size_contents = CalcSizeContents(window);
4604 return CalcSizeAfterConstraint(window, CalcSizeAutoFit(window, size_contents));
4607 float ImGui::GetWindowScrollMaxX(ImGuiWindow* window)
4609 return ImMax(0.0f, window->SizeContents.x - (window->SizeFull.x - window->ScrollbarSizes.x));
4612 float ImGui::GetWindowScrollMaxY(ImGuiWindow* window)
4614 return ImMax(0.0f, window->SizeContents.y - (window->SizeFull.y - window->ScrollbarSizes.y));
4617 static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window, bool snap_on_edges)
4620 ImVec2 scroll = window->Scroll;
4621 if (window->ScrollTarget.x < FLT_MAX)
4623 float cr_x = window->ScrollTargetCenterRatio.x;
4624 scroll.x = window->ScrollTarget.x - cr_x * (window->SizeFull.x - window->ScrollbarSizes.x);
4626 if (window->ScrollTarget.y < FLT_MAX)
4629 float cr_y = window->ScrollTargetCenterRatio.y;
4630 float target_y = window->ScrollTarget.y;
4631 if (snap_on_edges && cr_y <= 0.0f && target_y <= window->WindowPadding.y)
4633 if (snap_on_edges && cr_y >= 1.0f && target_y >= window->SizeContents.y - window->WindowPadding.y + g.Style.ItemSpacing.y)
4634 target_y = window->SizeContents.y;
4635 scroll.y = target_y - (1.0f - cr_y) * (window->TitleBarHeight() + window->MenuBarHeight()) - cr_y * (window->SizeFull.y - window->ScrollbarSizes.y);
4638 if (!window->Collapsed && !window->SkipItems)
4640 scroll.x = ImMin(scroll.x, ImGui::GetWindowScrollMaxX(window));
4641 scroll.y = ImMin(scroll.y, ImGui::GetWindowScrollMaxY(window));
4655 static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size)
4657 ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left
4658 ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right
4660 ImVec2 size_constrained = CalcSizeAfterConstraint(window, size_expected);
4684 static ImRect GetResizeBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness)
4686 ImRect rect = window->Rect();
4697 static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4])
4700 ImGuiWindowFlags flags = window->Flags;
4701 if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
4703 if (window->WasActive == false) // Early out to avoid running this code for e.g. an hidden implicit/fallback Debug window.
4707 const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
4719 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
4721 // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
4726 ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus);
4727 //GetOverlayDrawList(window)->AddRect(resize_rect.Min, resize_rect.Max, IM_COL32(255, 255, 0, 255));
4734 size_target = CalcSizeAfterConstraint(window, size_auto_fit);
4741 ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + ImLerp(grip.InnerDir * grip_hover_outer_size, grip.InnerDir * -grip_hover_inner_size, grip.CornerPosN); // Corner of the window corresponding to our corner grip
4742 CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPosN, &pos_target, &size_target);
4750 ImRect border_rect = GetResizeBorderRect(window, border_n, grip_hover_inner_size, WINDOWS_RESIZE_FROM_EDGES_HALF_THICKNESS);
4751 ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren);
4752 //GetOverlayDrawList(window)->AddRect(border_rect.Min, border_rect.Max, IM_COL32(255, 255, 0, 255));
4761 ImVec2 border_target = window->Pos;
4767 CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target);
4773 if (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow == window)
4788 size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta);
4792 // Apply back modified position/size to window
4795 window->SizeFull = size_target;
4796 MarkIniSettingsDirty(window);
4800 window->Pos = ImFloor(pos_target);
4801 MarkIniSettingsDirty(window);
4804 window->Size = window->SizeFull;
4807 static void ImGui::RenderOuterBorders(ImGuiWindow* window)
4810 float rounding = window->WindowRounding;
4811 float border_size = window->WindowBorderSize;
4812 if (border_size > 0.0f && !(window->Flags & ImGuiWindowFlags_NoBackground))
4813 window->DrawList->AddRect(window->Pos, window->Pos + window->Size, GetColorU32(ImGuiCol_Border), rounding, ImDrawCornerFlags_All, border_size);
4815 int border_held = window->ResizeBorderHeld;
4832 ImRect border_r = GetResizeBorderRect(window, border_held, rounding, 0.0f);
4833 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI*0.25f, def.OuterAngle);
4834 window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.CornerPosN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI*0.25f);
4835 window->DrawList->PathStroke(GetColorU32(ImGuiCol_SeparatorActive), false, ImMax(2.0f, border_size)); // Thicker than usual
4837 if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
4839 float y = window->Pos.y + window->TitleBarHeight() - 1;
4840 window->DrawList->AddLine(ImVec2(window->Pos.x + border_size, y), ImVec2(window->Pos.x + window->Size.x - border_size, y), GetColorU32(ImGuiCol_Border), g.Style.FrameBorderSize);
4844 void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window)
4846 window->ParentWindow = parent_window;
4847 window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForNav = window;
4849 window->RootWindow = parent_window->RootWindow;
4851 window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
4852 while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened)
4854 IM_ASSERT(window->RootWindowForNav->ParentWindow != NULL);
4855 window->RootWindowForNav = window->RootWindowForNav->ParentWindow;
4859 // Push a new ImGui window to add widgets to.
4860 // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
4861 // - Begin/End can be called multiple times during the frame with the same window name to append content.
4862 // - The window name is used as a unique identifier to preserve window information across frames (and save rudimentary information to the .ini file).
4864 // - Return false when window is collapsed, so you can early out in your code. You always need to call ImGui::End() even if false is returned.
4865 // - Passing 'bool* p_open' displays a Close button on the upper-right corner of the window, the pointed value will be set to false when the button is pressed.
4875 ImGuiWindow* window = FindWindowByName(name);
4876 const bool window_just_created = (window == NULL);
4879 ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here.
4880 window = CreateNewWindow(name, size_on_first_use, flags);
4891 const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame);
4895 window->Flags = (ImGuiWindowFlags)flags;
4897 flags = window->Flags;
4899 // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
4901 ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
4903 window->HasCloseButton = (p_open != NULL);
4906 bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on
4907 const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFramesForResize > 0);
4911 window_just_activated_by_user |= (window->PopupId != popup_ref.PopupId); // We recycle popups so treat window as activated if popup id changed
4912 window_just_activated_by_user |= (window != popup_ref.Window);
4914 window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize);
4915 if (window->Appearing)
4916 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true);
4919 g.CurrentWindowStack.push_back(window);
4920 SetCurrentWindow(window);
4921 CheckStacksSize(window, true);
4925 popup_ref.Window = window;
4927 window->PopupId = popup_ref.PopupId;
4931 window->NavLastIds[0] = 0;
4938 window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0;
4943 window->SetWindowPosVal = g.NextWindowData.PosVal;
4944 window->SetWindowPosPivot = g.NextWindowData.PosPivotVal;
4945 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
4949 SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond);
4954 window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f);
4955 window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f);
4956 SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond);
4960 // Adjust passed "client size" to become a "window size"
4961 window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal;
4962 if (window->SizeContentsExplicit.y != 0.0f)
4963 window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight();
4967 window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
4970 SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
4972 FocusWindow(window);
4973 if (window->Appearing)
4974 SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false);
4976 // When reusing window again multiple times a frame, just append content (don't need to setup again)
4981 UpdateWindowParentAndRootLinks(window, flags, parent_window);
4983 window->Active = true;
4984 window->BeginOrderWithinParent = 0;
4985 window->BeginOrderWithinContext = (short)(g.WindowsActiveCount++);
4986 window->BeginCount = 0;
4987 window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX);
4988 window->LastFrameActive = current_frame;
4989 window->IDStack.resize(1);
4991 // Update stored window name when it changes (which can _only_ happen with the "###" operator, so the ID would stay unchanged).
4994 if (g.NavWindowingList != NULL && (window->Flags & ImGuiWindowFlags_NoNavFocus) == 0) // Window titles visible when using CTRL+TAB
4996 if (window_title_visible_elsewhere && !window_just_created && strcmp(name, window->Name) != 0)
4998 size_t buf_len = (size_t)window->NameBufLen;
4999 window->Name = ImStrdupcpy(window->Name, &buf_len, name);
5000 window->NameBufLen = (int)buf_len;
5006 window->SizeContents = CalcSizeContents(window);
5007 if (window->HiddenFramesRegular > 0)
5008 window->HiddenFramesRegular--;
5009 if (window->HiddenFramesForResize > 0)
5010 window->HiddenFramesForResize--;
5014 window->HiddenFramesForResize = 1;
5016 // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows)
5020 window->HiddenFramesForResize = 1;
5024 window->Size.x = window->SizeFull.x = 0.f;
5026 window->Size.y = window->SizeFull.y = 0.f;
5027 window->SizeContents = ImVec2(0.f, 0.f);
5031 SetCurrentWindow(window);
5034 window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize;
5035 window->WindowPadding = style.WindowPadding;
5036 if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
5037 window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
5038 window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
5039 window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
5041 // Collapse window by double-clicking on title bar
5046 ImRect title_bar_rect = window->TitleBarRect();
5047 if (g.HoveredWindow == window && g.HoveredId == 0 && g.HoveredIdPreviousFrame == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])
5048 window->WantCollapseToggle = true;
5049 if (window->WantCollapseToggle)
5051 window->Collapsed = !window->Collapsed;
5052 MarkIniSettingsDirty(window);
5053 FocusWindow(window);
5058 window->Collapsed = false;
5060 window->WantCollapseToggle = false;
5065 const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents);
5067 if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed)
5071 window->SizeFull.x = size_full_modified.x = size_auto_fit.x;
5073 window->SizeFull.y = size_full_modified.y = size_auto_fit.y;
5075 else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0)
5077 // Auto-fit may only grow window during the first few frames
5078 // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed.
5079 if (!window_size_x_set_by_api && window->AutoFitFramesX > 0)
5080 window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x;
5081 if (!window_size_y_set_by_api && window->AutoFitFramesY > 0)
5082 window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y;
5083 if (!window->Collapsed)
5084 MarkIniSettingsDirty(window);
5087 // Apply minimum/maximum window size constraints and final size
5088 window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull);
5089 window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull;
5094 if (!window->Collapsed)
5097 float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x;
5098 float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y;
5099 window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
5100 window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
5101 if (window->ScrollbarX && !window->ScrollbarY)
5102 window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
5103 window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
5111 window->AutoPosLastDirection = ImGuiDir_None;
5113 window->Pos = g.BeginPopupStack.back().OpenPopupPos;
5116 // Position child window
5120 window->BeginOrderWithinParent = (short)parent_window->DC.ChildWindows.Size;
5121 parent_window->DC.ChildWindows.push_back(window);
5123 window->Pos = parent_window->DC.CursorPos;
5126 const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFramesForResize == 0);
5128 SetWindowPos(window, ImMax(style.DisplaySafeAreaPadding, window->SetWindowPosVal - window->SizeFull * window->SetWindowPosPivot), 0); // Position given a pivot (e.g. for centering)
5130 window->Pos = FindBestWindowPosForPopup(window);
5132 window->Pos = FindBestWindowPosForPopup(window);
5134 window->Pos = FindBestWindowPosForPopup(window);
5137 // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
5138 if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
5140 if (g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
5143 ImVec2 size_for_clamping = ((g.IO.ConfigWindowsMoveFromTitleBarOnly) && !(window->Flags & ImGuiWindowFlags_NoTitleBar)) ? ImVec2(window->Size.x, window->TitleBarHeight()) : window->Size;
5144 window->Pos = ImMax(window->Pos + size_for_clamping, padding) - size_for_clamping;
5145 window->Pos = ImMin(window->Pos, g.IO.DisplaySize - padding);
5148 window->Pos = ImFloor(window->Pos);
5150 // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies)
5151 window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding;
5154 window->FocusIdxAllRequestCurrent = (window->FocusIdxAllRequestNext == INT_MAX || window->FocusIdxAllCounter == -1) ? INT_MAX : (window->FocusIdxAllRequestNext + (window->FocusIdxAllCounter+1)) % (window->FocusIdxAllCounter+1);
5155 window->FocusIdxTabRequestCurrent = (window->FocusIdxTabRequestNext == INT_MAX || window->FocusIdxTabCounter == -1) ? INT_MAX : (window->FocusIdxTabRequestNext + (window->FocusIdxTabCounter+1)) % (window->FocusIdxTabCounter+1);
5156 window->FocusIdxAllCounter = window->FocusIdxTabCounter = -1;
5157 window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX;
5160 window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window, true);
5161 window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX);
5163 // Apply window focus (new and reactivated windows are moved to front)
5177 const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f);
5178 if (!window->Collapsed)
5179 UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
5180 window->ResizeBorderHeld = (signed char)border_held;
5182 // Default item width. Make it proportional to window size if window manually resizes
5183 if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize))
5184 window->ItemWidthDefault = (float)(int)(window->Size.x * 0.65f);
5186 window->ItemWidthDefault = (float)(int)(g.FontSize * 16.0f);
5191 window->DrawList->Clear();
5192 window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0);
5193 window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
5200 // Draw modal window background (darkens what is behind them, all viewports)
5201 const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetFrontMostPopupModal() && window->HiddenFramesForResize <= 0;
5202 const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
5206 window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
5210 if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
5212 ImRect bb = window->Rect();
5214 if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
5215 window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
5218 // Draw window + handle manual resize
5220 const float window_rounding = window->WindowRounding;
5221 const float window_border_size = window->WindowBorderSize;
5223 const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
5224 const ImRect title_bar_rect = window->TitleBarRect();
5225 if (window->Collapsed)
5229 g.Style.FrameBorderSize = window->WindowBorderSize;
5245 window->DrawList->AddRectFilled(window->Pos + ImVec2(0, window->TitleBarHeight()), window->Pos + window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot);
5253 window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top);
5259 ImRect menu_bar_rect = window->MenuBarRect();
5260 menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
5261 window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top);
5262 if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
5263 window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
5267 if (window->ScrollbarX)
5269 if (window->ScrollbarY)
5278 const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPosN);
5279 window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size)));
5280 window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size)));
5281 window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12);
5282 window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]);
5287 RenderOuterBorders(window);
5291 if (g.NavWindowingTargetAnim == window)
5293 float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
5294 ImRect bb = window->Rect();
5296 if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
5299 rounding = window->WindowRounding;
5301 window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f);
5305 window->SizeFullAtLastBegin = window->SizeFull;
5308 // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it.
5309 window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x;
5310 window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight();
5311 window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x));
5312 window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->SizeContentsExplicit.y != 0.0f ? window->SizeContentsExplicit.y : (window->Size.y - window->ScrollbarSizes.y));
5315 // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.)
5316 window->DC.Indent.x = 0.0f + window->WindowPadding.x - window->Scroll.x;
5317 window->DC.GroupOffset.x = 0.0f;
5318 window->DC.ColumnsOffset.x = 0.0f;
5319 window->DC.CursorStartPos = window->Pos + ImVec2(window->DC.Indent.x + window->DC.ColumnsOffset.x, window->TitleBarHeight() + window->MenuBarHeight() + window->WindowPadding.y - window->Scroll.y);
5320 window->DC.CursorPos = window->DC.CursorStartPos;
5321 window->DC.CursorPosPrevLine = window->DC.CursorPos;
5322 window->DC.CursorMaxPos = window->DC.CursorStartPos;
5323 window->DC.CurrentLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f);
5324 window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f;
5325 window->DC.NavHideHighlightOneFrame = false;
5326 window->DC.NavHasScroll = (GetWindowScrollMaxY(window) > 0.0f);
5327 window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext;
5328 window->DC.NavLayerActiveMaskNext = 0x00;
5329 window->DC.MenuBarAppending = false;
5330 window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
5331 window->DC.ChildWindows.resize(0);
5332 window->DC.LayoutType = ImGuiLayoutType_Vertical;
5333 window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
5334 window->DC.ItemFlags = parent_window ? parent_window->DC.ItemFlags : ImGuiItemFlags_Default_;
5335 window->DC.ItemWidth = window->ItemWidthDefault;
5336 window->DC.TextWrapPos = -1.0f; // disabled
5337 window->DC.ItemFlagsStack.resize(0);
5338 window->DC.ItemWidthStack.resize(0);
5339 window->DC.TextWrapPosStack.resize(0);
5340 window->DC.ColumnsSet = NULL;
5341 window->DC.TreeDepth = 0;
5342 window->DC.TreeDepthMayJumpToParentOnPop = 0x00;
5343 window->DC.StateStorage = &window->StateStorage;
5344 window->DC.GroupStack.resize(0);
5345 window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
5347 if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags))
5349 window->DC.ItemFlags = parent_window->DC.ItemFlags;
5350 window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5353 if (window->AutoFitFramesX > 0)
5354 window->AutoFitFramesX--;
5355 if (window->AutoFitFramesY > 0)
5356 window->AutoFitFramesY--;
5361 FocusWindow(window);
5362 NavInitWindow(window, false);
5369 const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
5370 window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
5371 window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
5372 window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
5376 if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos))
5377 window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
5384 if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1))
5388 window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
5389 window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
5390 window->DC.ItemFlags = item_flags_backup;
5405 clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
5416 window->OuterRectClipped = window->Rect();
5417 window->OuterRectClipped.ClipWith(window->ClipRect);
5419 // Pressing CTRL+C while holding on a window copy its content to the clipboard
5430 // Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
5431 window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
5432 window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
5433 window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize;
5434 window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize;
5435 //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE);
5439 window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5440 window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
5441 window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize)));
5442 window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
5446 window->DC.LastItemId = window->MoveId;
5447 window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
5448 window->DC.LastItemRect = title_bar_rect;
5451 PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
5453 // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
5455 window->WriteAccessed = false;
5457 window->BeginCount++;
5462 // Child window can be out of sight and have "negative" clip windows.
5465 if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0)
5466 if (window->OuterRectClipped.Min.x >= window->OuterRectClipped.Max.x || window->OuterRectClipped.Min.y >= window->OuterRectClipped.Max.y)
5467 window->HiddenFramesRegular = 1;
5471 window->HiddenFramesRegular = 1;
5476 window->HiddenFramesRegular = 1;
5479 window->Hidden = (window->HiddenFramesRegular > 0) || (window->HiddenFramesForResize > 0);
5482 window->SkipItems = (window->Collapsed || !window->Active || window->Hidden) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && window->HiddenFramesForResize <= 0;
5484 return !window->SkipItems;
5491 // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file.
5495 // Old API feature: override the window background alpha with a parameter.
5514 ImGuiWindow* window = g.CurrentWindow;
5516 if (window->DC.ColumnsSet != NULL)
5518 PopClipRect(); // Inner window clip rectangle
5521 if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
5524 // Pop from window stack
5526 if (window->Flags & ImGuiWindowFlags_Popup)
5528 CheckStacksSize(window, false);
5532 void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
5535 if (g.WindowsFocusOrder.back() == window)
5537 for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the front most window
5538 if (g.WindowsFocusOrder[i] == window)
5541 g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window;
5546 void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
5550 if (current_front_window == window || current_front_window->RootWindow == window)
5552 for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window
5553 if (g.Windows[i] == window)
5556 g.Windows[g.Windows.Size - 1] = window;
5561 void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
5564 if (g.Windows[0] == window)
5567 if (g.Windows[i] == window)
5570 g.Windows[0] = window;
5575 // Moving window to front of display and set focus (which happens to be back of our sorted list)
5576 void ImGui::FocusWindow(ImGuiWindow* window)
5580 if (g.NavWindow != window)
5582 g.NavWindow = window;
5583 if (window && g.NavDisableMouseHover)
5586 g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
5589 //IMGUI_DEBUG_LOG("FocusWindow(\"%s\")\n", window ? window->Name : NULL);
5593 if (!window)
5596 // Move the root window to the top of the pile
5597 if (window->RootWindow)
5598 window = window->RootWindow;
5601 if (window->Flags & ImGuiWindowFlags_Popup) // FIXME: This statement should be unnecessary. Need further testing before removing it..
5602 if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != window)
5606 BringWindowToFocusFront(window);
5607 if (!(window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus))
5608 BringWindowToDisplayFront(window);
5617 ImGuiWindow* window = g.WindowsFocusOrder[i];
5618 if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow))
5619 if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
5621 ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window);
5630 ImGuiWindow* window = GetCurrentWindow();
5631 window->DC.ItemWidth = (item_width == 0.0f ? window->ItemWidthDefault : item_width);
5632 window->DC.ItemWidthStack.push_back(window->DC.ItemWidth);
5637 ImGuiWindow* window = GetCurrentWindow();
5643 window->DC.ItemWidthStack.push_back(w_item_last);
5645 window->DC.ItemWidthStack.push_back(w_item_one);
5646 window->DC.ItemWidth = window->DC.ItemWidthStack.back();
5651 ImGuiWindow* window = GetCurrentWindow();
5652 window->DC.ItemWidthStack.pop_back();
5653 window->DC.ItemWidth = window->DC.ItemWidthStack.empty() ? window->ItemWidthDefault : window->DC.ItemWidthStack.back();
5658 ImGuiWindow* window = GetCurrentWindowRead();
5659 float w = window->DC.ItemWidth;
5705 ImGuiWindow* window = GetCurrentWindow();
5707 window->DC.ItemFlags |= option;
5709 window->DC.ItemFlags &= ~option;
5710 window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags);
5715 ImGuiWindow* window = GetCurrentWindow();
5716 window->DC.ItemFlagsStack.pop_back();
5717 window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back();
5743 ImGuiWindow* window = GetCurrentWindow();
5744 window->DC.TextWrapPos = wrap_pos_x;
5745 window->DC.TextWrapPosStack.push_back(wrap_pos_x);
5750 ImGuiWindow* window = GetCurrentWindow();
5751 window->DC.TextWrapPosStack.pop_back();
5752 window->DC.TextWrapPos = window->DC.TextWrapPosStack.empty() ? -1.0f : window->DC.TextWrapPosStack.back();
5932 bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
5934 if (window->RootWindow == potential_parent)
5936 while (window != NULL)
5938 if (window == potential_parent)
5940 window = window->ParentWindow;
6007 // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
6008 // Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmaticaly.
6009 // If you want a window to never be focused, you may use the e.g. NoInputs flag.
6010 bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
6012 return window->Active && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
6017 ImGuiWindow* window = GImGui->CurrentWindow;
6018 return window->Size.x;
6023 ImGuiWindow* window = GImGui->CurrentWindow;
6024 return window->Size.y;
6030 ImGuiWindow* window = g.CurrentWindow;
6031 return window->Pos;
6034 void ImGui::SetWindowScrollX(ImGuiWindow* window, float new_scroll_x)
6036 window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
6037 window->Scroll.x = new_scroll_x;
6038 window->DC.CursorMaxPos.x -= window->Scroll.x;
6041 void ImGui::SetWindowScrollY(ImGuiWindow* window, float new_scroll_y)
6043 window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it.
6044 window->Scroll.y = new_scroll_y;
6045 window->DC.CursorMaxPos.y -= window->Scroll.y;
6048 void ImGui::SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond)
6051 if (cond && (window->SetWindowPosAllowFlags & cond) == 0)
6055 window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6056 window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX);
6059 const ImVec2 old_pos = window->Pos;
6060 window->Pos = ImFloor(pos);
6061 window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor
6062 window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected.
6067 ImGuiWindow* window = GetCurrentWindowRead();
6068 SetWindowPos(window, pos, cond);
6073 if (ImGuiWindow* window = FindWindowByName(name))
6074 SetWindowPos(window, pos, cond);
6079 ImGuiWindow* window = GetCurrentWindowRead();
6080 return window->Size;
6083 void ImGui::SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond)
6086 if (cond && (window->SetWindowSizeAllowFlags & cond) == 0)
6090 window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6095 window->AutoFitFramesX = 0;
6096 window->SizeFull.x = ImFloor(size.x);
6100 window->AutoFitFramesX = 2;
6101 window->AutoFitOnlyGrows = false;
6105 window->AutoFitFramesY = 0;
6106 window->SizeFull.y = ImFloor(size.y);
6110 window->AutoFitFramesY = 2;
6111 window->AutoFitOnlyGrows = false;
6122 if (ImGuiWindow* window = FindWindowByName(name))
6123 SetWindowSize(window, size, cond);
6126 void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond)
6129 if (cond && (window->SetWindowCollapsedAllowFlags & cond) == 0)
6131 window->SetWindowCollapsedAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing);
6134 window->Collapsed = collapsed;
6144 ImGuiWindow* window = GetCurrentWindowRead();
6145 return window->Collapsed;
6150 ImGuiWindow* window = GetCurrentWindowRead();
6151 return window->Appearing;
6156 if (ImGuiWindow* window = FindWindowByName(name))
6157 SetWindowCollapsed(window, collapsed, cond);
6169 if (ImGuiWindow* window = FindWindowByName(name))
6170 FocusWindow(window);
6207 g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value.
6232 // FIXME: This is in window space (not screen space!)
6235 ImGuiWindow* window = GetCurrentWindowRead();
6236 ImVec2 mx = window->ContentsRegionRect.Max - window->Pos;
6237 if (window->DC.ColumnsSet)
6238 mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x;
6244 ImGuiWindow* window = GetCurrentWindowRead();
6245 return GetContentRegionMax() - (window->DC.CursorPos - window->Pos);
6253 // In window space (not screen space!)
6256 ImGuiWindow* window = GetCurrentWindowRead();
6257 return window->ContentsRegionRect.Min - window->Pos;
6262 ImGuiWindow* window = GetCurrentWindowRead();
6263 return window->ContentsRegionRect.Max - window->Pos;
6268 ImGuiWindow* window = GetCurrentWindowRead();
6269 return window->ContentsRegionRect.GetWidth();
6298 ImGuiWindow* window = GetCurrentWindow();
6299 return window->DrawList;
6320 ImGuiWindow* window = GetCurrentWindow();
6321 window->FontWindowScale = scale;
6322 g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
6325 // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient.
6326 // Conversion happens as we pass the value to user, but it makes our naming convention confusing because GetCursorPos() == (DC.CursorPos - window.Pos). May want to rename 'DC.CursorPos'.
6329 ImGuiWindow* window = GetCurrentWindowRead();
6330 return window->DC.CursorPos - window->Pos + window->Scroll;
6335 ImGuiWindow* window = GetCurrentWindowRead();
6336 return window->DC.CursorPos.x - window->Pos.x + window->Scroll.x;
6341 ImGuiWindow* window = GetCurrentWindowRead();
6342 return window->DC.CursorPos.y - window->Pos.y + window->Scroll.y;
6347 ImGuiWindow* window = GetCurrentWindow();
6348 window->DC.CursorPos = window->Pos - window->Scroll + local_pos;
6349 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6354 ImGuiWindow* window = GetCurrentWindow();
6355 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + x;
6356 window->DC.CursorMaxPos.x = ImMax(window->DC.CursorMaxPos.x, window->DC.CursorPos.x);
6361 ImGuiWindow* window = GetCurrentWindow();
6362 window->DC.CursorPos.y = window->Pos.y - window->Scroll.y + y;
6363 window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, window->DC.CursorPos.y);
6368 ImGuiWindow* window = GetCurrentWindowRead();
6369 return window->DC.CursorStartPos - window->Pos;
6374 ImGuiWindow* window = GetCurrentWindowRead();
6375 return window->DC.CursorPos;
6380 ImGuiWindow* window = GetCurrentWindow();
6381 window->DC.CursorPos = pos;
6382 window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
6407 ImGuiWindow* window = GetCurrentWindow();
6408 window->ScrollTarget.x = scroll_x;
6409 window->ScrollTargetCenterRatio.x = 0.0f;
6414 ImGuiWindow* window = GetCurrentWindow();
6415 window->ScrollTarget.y = scroll_y + window->TitleBarHeight() + window->MenuBarHeight(); // title bar height canceled out when using ScrollTargetRelY
6416 window->ScrollTargetCenterRatio.y = 0.0f;
6421 // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
6422 ImGuiWindow* window = GetCurrentWindow();
6424 window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y);
6425 window->ScrollTargetCenterRatio.y = center_y_ratio;
6431 ImGuiWindow* window = GetCurrentWindow();
6432 float target_y = window->DC.CursorPosPrevLine.y - window->Pos.y; // Top of last item, in window space
6433 target_y += (window->DC.PrevLineSize.y * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line.
6446 ImGuiWindow* window = GetCurrentWindow();
6447 window->FocusIdxAllRequestNext = window->FocusIdxAllCounter + 1 + offset;
6448 window->FocusIdxTabRequestNext = INT_MAX;
6454 ImGuiWindow* window = g.CurrentWindow;
6455 if (!window->Appearing)
6457 if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent)
6470 ImGuiWindow* window = GImGui->CurrentWindow;
6471 window->DC.StateStorage = tree ? tree : &window->StateStorage;
6476 ImGuiWindow* window = GImGui->CurrentWindow;
6477 return window->DC.StateStorage;
6482 ImGuiWindow* window = GImGui->CurrentWindow;
6483 window->IDStack.push_back(window->GetIDNoKeepAlive(str_id));
6488 ImGuiWindow* window = GImGui->CurrentWindow;
6489 window->IDStack.push_back(window->GetIDNoKeepAlive(str_id_begin, str_id_end));
6494 ImGuiWindow* window = GImGui->CurrentWindow;
6495 window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6501 ImGuiWindow* window = GImGui->CurrentWindow;
6502 window->IDStack.push_back(window->GetIDNoKeepAlive(ptr_id));
6507 ImGuiWindow* window = GImGui->CurrentWindow;
6508 window->IDStack.pop_back();
6513 ImGuiWindow* window = GImGui->CurrentWindow;
6514 return window->GetID(str_id);
6519 ImGuiWindow* window = GImGui->CurrentWindow;
6520 return window->GetID(str_id_begin, str_id_end);
6525 ImGuiWindow* window = GImGui->CurrentWindow;
6526 return window->GetID(ptr_id);
6531 ImGuiWindow* window = GImGui->CurrentWindow;;
6532 return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.CursorPos + size));
6537 ImGuiWindow* window = GImGui->CurrentWindow;;
6538 return window->ClipRect.Overlaps(ImRect(rect_min, rect_max));
6545 ImGuiWindow* window = GetCurrentWindow();
6547 window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
6548 ImGuiGroupData& group_data = window->DC.GroupStack.back();
6549 group_data.BackupCursorPos = window->DC.CursorPos;
6550 group_data.BackupCursorMaxPos = window->DC.CursorMaxPos;
6551 group_data.BackupIndent = window->DC.Indent;
6552 group_data.BackupGroupOffset = window->DC.GroupOffset;
6553 group_data.BackupCurrentLineSize = window->DC.CurrentLineSize;
6554 group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
6555 group_data.BackupLogLinePosY = window->DC.LogLinePosY;
6560 window->DC.GroupOffset.x = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffset.x;
6561 window->DC.Indent = window->DC.GroupOffset;
6562 window->DC.CursorMaxPos = window->DC.CursorPos;
6563 window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
6564 window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6570 ImGuiWindow* window = GetCurrentWindow();
6571 IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
6573 ImGuiGroupData& group_data = window->DC.GroupStack.back();
6575 ImRect group_bb(group_data.BackupCursorPos, window->DC.CursorMaxPos);
6578 window->DC.CursorPos = group_data.BackupCursorPos;
6579 window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
6580 window->DC.Indent = group_data.BackupIndent;
6581 window->DC.GroupOffset = group_data.BackupGroupOffset;
6582 window->DC.CurrentLineSize = group_data.BackupCurrentLineSize;
6583 window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
6584 window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
6588 window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrentLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
6594 // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets.
6596 if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
6597 window->DC.LastItemId = g.ActiveId;
6598 else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
6599 window->DC.LastItemId = g.ActiveIdPreviousFrame;
6600 window->DC.LastItemRect = group_bb;
6602 window->DC.GroupStack.pop_back();
6604 //window->DrawList->AddRect(group_bb.Min, group_bb.Max, IM_COL32(255,0,255,255)); // [Debug]
6609 // pos_x != 0 : align to specified x position (relative to window/group left)
6614 ImGuiWindow* window = GetCurrentWindow();
6615 if (window->SkipItems)
6622 window->DC.CursorPos.x = window->Pos.x - window->Scroll.x + pos_x + spacing_w + window->DC.GroupOffset.x + window->DC.ColumnsOffset.x;
6623 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6628 window->DC.CursorPos.x = window->DC.CursorPosPrevLine.x + spacing_w;
6629 window->DC.CursorPos.y = window->DC.CursorPosPrevLine.y;
6631 window->DC.CurrentLineSize = window->DC.PrevLineSize;
6632 window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
6638 ImGuiWindow* window = GetCurrentWindow();
6639 window->DC.Indent.x += (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6640 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6646 ImGuiWindow* window = GetCurrentWindow();
6647 window->DC.Indent.x -= (indent_w != 0.0f) ? indent_w : g.Style.IndentSpacing;
6648 window->DC.CursorPos.x = window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x;
6683 if (ImGuiWindow* window = FindWindowByName(window_name))
6684 if (window->Active)
6686 // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one.
6687 window->Hidden = true;
6688 window->HiddenFramesRegular = 1;
6800 ImGuiWindow* window = GImGui->CurrentWindow;
6803 ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
6822 // Find the highest popup which is a descendant of the reference window (generally reference window = NavWindow)
6832 // Trim the stack if popups are not direct descendant of the reference window (which is often the NavWindow)
6856 // Instead of using g.OpenPopupStack[remaining-1].Window etc. we should find the highest root window that is behind the popups we are closing.
6857 // The current code will set focus to the parent of the popup window which is incorrect.
6858 // It rarely manifested until now because UpdateMouseMovingWindowNewFrame() would call FocusWindow() again on the clicked window,
6859 // leading to a chain of focusing A (clicked window) then B (parent window of the popup) then A again.
6860 // However if the clicked window has the _NoMove flag set we would be left with B focused.
6895 // A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
6896 // To improve this usage pattern, we avoid nav highlight for a single frame in the parent window.
6897 // Similarly, we could avoid mouse hover highlight in this window but it is less visually problematic.
6898 if (ImGuiWindow* window = g.NavWindow)
6899 window->DC.NavHideHighlightOneFrame = true;
6936 // If 'p_open' is specified for a modal popup window, the popup will have a regular close button which will close the popup.
6941 ImGuiWindow* window = g.CurrentWindow;
6942 const ImGuiID id = window->GetID(name);
6950 // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window.
6983 ImGuiWindow* window = GImGui->CurrentWindow;
6984 ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
7075 ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
7079 ImRect r_outer = GetWindowAllowedExtentRect(window);
7080 if (window->Flags & ImGuiWindowFlags_ChildMenu)
7084 IM_ASSERT(g.CurrentWindow == window);
7092 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7094 if (window->Flags & ImGuiWindowFlags_Popup)
7096 ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Pos.x + 1, window->Pos.y + 1);
7097 return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7099 if (window->Flags & ImGuiWindowFlags_Tooltip)
7109 ImVec2 pos = FindBestWindowPosForPopupEx(ref_pos, window->Size, &window->AutoPosLastDirection, r_outer, r_avoid);
7110 if (window->AutoPosLastDirection == ImGuiDir_None)
7115 return window->Pos;
7162 ImGuiWindow* window = g.CurrentWindow;
7163 if (g.NavLayer != window->DC.NavLayerCurrent)
7169 // When entering through a NavFlattened border, we consider child window items as fully clipped for scoring
7170 if (window->ParentWindow == g.NavWindow)
7172 IM_ASSERT((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened);
7173 if (!window->ClipRect.Contains(cand))
7175 cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window
7180 NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect);
7217 quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right;
7225 ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7237 ImDrawList* draw_list = ImGui::GetOverlayDrawList(window);
7291 static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id)
7297 const ImGuiItemFlags item_flags = window->DC.ItemFlags;
7298 const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos);
7301 if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent)
7320 ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
7333 result->Window = window;
7338 if ((g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet) && window->ClipRect.Overlaps(nav_bb))
7339 if (ImClamp(nav_bb.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y) - ImClamp(nav_bb.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y) >= (nav_bb.Max.y - nav_bb.Min.y) * VISIBLE_RATIO)
7345 result->Window = window;
7350 // Update window-relative bounding box of navigated item
7353 g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window.
7354 g.NavLayer = window->DC.NavLayerCurrent;
7356 g.NavIdTabCounter = window->FocusIdxTabCounter;
7357 window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position)
7386 void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags)
7389 if (g.NavWindow != window || !NavMoveRequestButNoResultYet() || g.NavMoveRequestForward != ImGuiNavForward_None || g.NavLayer != 0)
7392 ImRect bb_rel = window->NavRectRel[0];
7397 bb_rel.Min.x = bb_rel.Max.x = ImMax(window->SizeFull.x, window->SizeContents.x) - window->Scroll.x;
7403 bb_rel.Min.x = bb_rel.Max.x = -window->Scroll.x;
7409 bb_rel.Min.y = bb_rel.Max.y = ImMax(window->SizeFull.y, window->SizeContents.y) - window->Scroll.y;
7415 bb_rel.Min.y = bb_rel.Max.y = -window->Scroll.y;
7431 static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
7433 return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
7457 void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
7460 IM_ASSERT(window == g.NavWindow);
7462 if (!(window->Flags & ImGuiWindowFlags_NoNavInputs))
7463 if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit)
7476 g.NavId = window->NavLastIds[0];
7540 static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
7542 ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
7543 //GetOverlayDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
7548 if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x)
7550 window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x;
7551 window->ScrollTargetCenterRatio.x = 0.0f;
7553 else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x)
7555 window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x;
7556 window->ScrollTargetCenterRatio.x = 1.0f;
7560 window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y;
7561 window->ScrollTargetCenterRatio.y = 0.0f;
7565 window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y;
7566 window->ScrollTargetCenterRatio.y = 1.0f;
7652 // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0
7675 // Exit child window
7698 // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
7748 // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window)
7777 // *Fallback* manual-scroll with Nav directional keys when window has no navigable item
7778 ImGuiWindow* window = g.NavWindow;
7779 const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported.
7780 if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest)
7783 SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed));
7785 SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed));
7791 if (scroll_dir.x != 0.0f && window->ScrollbarX)
7793 SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed));
7798 SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed));
7811 ImGuiWindow* window = g.NavWindow;
7812 ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
7813 if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
7815 float pad = window->CalcFontSize() * 0.5f;
7817 window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel);
7878 // Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
7900 ImGuiWindow* window = g.NavWindow;
7905 if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
7907 // Fallback manual-scroll when window has no navigable item
7909 SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
7911 SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
7915 const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
7916 const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
7939 static int FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N)
7943 if (g.WindowsFocusOrder[i] == window)
7968 if (window_target) // Don't reset windowing target if there's a single window in the list
7995 // Start CTRL-TAB or Square+L/R window selection
7999 if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocusable(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1))
8001 g.NavWindowingTarget = g.NavWindowingTargetAnim = window;
8014 // Select window to focus
8022 // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most)
8046 // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB
8051 // Move window
8080 // If the window only has a menu layer, select it directly
8109 static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
8111 if (window->Flags & ImGuiWindowFlags_Popup)
8113 if ((window->Flags & ImGuiWindowFlags_MenuBar) && strcmp(window->Name, "##MainMenuBar") == 0)
8135 ImGuiWindow* window = g.WindowsFocusOrder[n];
8136 if (!IsWindowNavFocusable(window))
8138 const char* label = window->Name;
8140 label = GetFallbackWindowNameForWindowingList(window);
8141 Selectable(label, g.NavWindowingTarget == window);
8154 ImGuiWindow* window = GetCurrentWindow();
8155 if (window->SkipItems || window->DC.ColumnsSet == NULL)
8162 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8163 columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8167 window->DC.ColumnsOffset.x = GetColumnOffset(columns->Current) - window->DC.Indent.x + g.Style.ItemSpacing.x;
8168 window->DrawList->ChannelsSetCurrent(columns->Current);
8172 window->DC.ColumnsOffset.x = 0.0f;
8173 window->DrawList->ChannelsSetCurrent(0);
8177 window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8178 window->DC.CursorPos.y = columns->LineMinY;
8179 window->DC.CurrentLineSize = ImVec2(0.0f, 0.0f);
8180 window->DC.CurrentLineTextBaseOffset = 0.0f;
8188 ImGuiWindow* window = GetCurrentWindowRead();
8189 return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0;
8194 ImGuiWindow* window = GetCurrentWindowRead();
8195 return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1;
8213 // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning.
8215 ImGuiWindow* window = g.CurrentWindow;
8219 float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x;
8229 ImGuiWindow* window = GetCurrentWindowRead();
8230 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8257 ImGuiWindow* window = GetCurrentWindowRead();
8258 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8269 ImGuiWindow* window = g.CurrentWindow;
8270 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8290 ImGuiWindow* window = GetCurrentWindowRead();
8291 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8301 ImGuiWindow* window = GetCurrentWindowRead();
8302 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8309 static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id)
8311 for (int n = 0; n < window->ColumnsStorage.Size; n++)
8312 if (window->ColumnsStorage[n].ID == id)
8313 return &window->ColumnsStorage[n];
8315 window->ColumnsStorage.push_back(ImGuiColumnsSet());
8316 ImGuiColumnsSet* columns = &window->ColumnsStorage.back();
8324 ImGuiWindow* window = GetCurrentWindow();
8327 IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported
8332 ImGuiID id = window->GetID(str_id ? str_id : "columns");
8336 ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id);
8341 window->DC.ColumnsSet = columns;
8344 const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x);
8345 columns->MinX = window->DC.Indent.x - g.Style.ItemSpacing.x; // Lock our horizontal range
8346 columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f);
8347 columns->StartPosY = window->DC.CursorPos.y;
8348 columns->StartMaxPosX = window->DC.CursorMaxPos.x;
8349 columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y;
8350 window->DC.ColumnsOffset.x = 0.0f;
8351 window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8374 float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f);
8375 float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f);
8377 column->ClipRect.ClipWith(window->ClipRect);
8380 window->DrawList->ChannelsSplit(columns->Count);
8388 ImGuiWindow* window = GetCurrentWindow();
8389 ImGuiColumnsSet* columns = window->DC.ColumnsSet;
8394 window->DrawList->ChannelsMerge();
8396 columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y);
8397 window->DC.CursorPos.y = columns->LineMaxY;
8399 window->DC.CursorMaxPos.x = columns->StartMaxPosX; // Restore cursor max pos, as columns don't grow parent
8403 if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems)
8406 const float y2 = window->DC.CursorPos.y;
8410 float x = window->Pos.x + GetColumnOffset(n);
8431 window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col);
8447 window->DC.ColumnsSet = NULL;
8448 window->DC.ColumnsOffset.x = 0.0f;
8449 window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);
8455 ImGuiWindow* window = GetCurrentWindow();
8460 if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags)
8463 if (window->DC.ColumnsSet != NULL)
8493 ImGuiWindow* window = g.CurrentWindow;
8501 source_id = window->DC.LastItemId;
8518 // We build a throwaway ID based on current ID stack + relative AABB of items in window.
8521 bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0;
8522 if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
8524 source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
8529 SetActiveID(source_id, window);
8530 FocusWindow(window);
8541 source_parent_id = window->IDStack.back();
8546 window = NULL;
8581 window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect;
8653 ImGuiWindow* window = g.CurrentWindow;
8654 if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8659 if (window->SkipItems)
8679 ImGuiWindow* window = g.CurrentWindow;
8680 if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
8682 if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
8685 const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
8686 ImGuiID id = window->DC.LastItemId;
8688 id = window->GetIDFromRectangle(display_rect);
8708 ImGuiWindow* window = g.CurrentWindow;
8734 bool push_clip_rect = !window->ClipRect.Contains(r);
8735 if (push_clip_rect) window->DrawList->PushClipRect(r.Min-ImVec2(1,1), r.Max+ImVec2(1,1));
8736 window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f);
8737 if (push_clip_rect) window->DrawList->PopClipRect();
8741 payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
8797 ImGuiWindow* window = g.CurrentWindow;
8802 const bool log_new_line = ref_pos && (ref_pos->y > window->DC.LogLinePosY + 1);
8804 window->DC.LogLinePosY = ref_pos->y;
8807 if (g.LogStartDepth > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
8808 g.LogStartDepth = window->DC.TreeDepth;
8809 const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth);
8838 ImGuiWindow* window = g.CurrentWindow;
8843 g.LogStartDepth = window->DC.TreeDepth;
8854 ImGuiWindow* window = g.CurrentWindow;
8871 g.LogStartDepth = window->DC.TreeDepth;
8882 ImGuiWindow* window = g.CurrentWindow;
8887 g.LogStartDepth = window->DC.TreeDepth;
8951 void ImGui::MarkIniSettingsDirty(ImGuiWindow* window)
8954 if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings))
9121 // (if a window wasn't opened in this session we preserve its settings)
9125 ImGuiWindow* window = g.Windows[i];
9126 if (window->Flags & ImGuiWindowFlags_NoSavedSettings)
9129 ImGuiWindowSettings* settings = (window->SettingsIdx != -1) ? &g.SettingsWindows[window->SettingsIdx] : ImGui::FindWindowSettings(window->ID);
9132 settings = ImGui::CreateNewWindowSettings(window->Name);
9133 window->SettingsIdx = g.SettingsWindows.index_from_ptr(settings);
9135 IM_ASSERT(settings->ID == window->ID);
9136 settings->Pos = window->Pos;
9137 settings->Size = window->SizeFull;
9138 settings->Collapsed = window->Collapsed;
9296 ImGui::Checkbox("Ctrl shows window begin order", &show_window_begin_order);
9301 static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label)
9312 ImDrawList* overlay_draw_list = GetOverlayDrawList(window); // Render additional visuals into the top-most draw list
9313 if (window && IsItemHovered())
9314 overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255));
9381 static void NodeWindow(ImGuiWindow* window, const char* label)
9383 if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window))
9385 ImGuiWindowFlags flags = window->Flags;
9386 NodeDrawList(window, window->DrawList, "DrawList");
9387 ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y);
9392 ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetWindowScrollMaxX(window), window->Scroll.y, GetWindowScrollMaxY(window));
9393 ImGui::BulletText("Active: %d/%d, WriteAccessed: %d, BeginOrderWithinContext: %d", window->Active, window->WasActive, window->WriteAccessed, (window->Active || window->WasActive) ? window->BeginOrderWithinContext : -1);
9394 ImGui::BulletText("Appearing: %d, Hidden: %d (Reg %d Resize %d), SkipItems: %d", window->Appearing, window->Hidden, window->HiddenFramesRegular, window->HiddenFramesForResize, window->SkipItems);
9395 ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask);
9396 ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL");
9397 if (!window->NavRectRel[0].IsInverted())
9398 ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y);
9401 if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
9402 if (window->ParentWindow != NULL) NodeWindow(window->ParentWindow, "ParentWindow");
9403 if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
9404 if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
9406 for (int n = 0; n < window->ColumnsStorage.Size; n++)
9408 const ImGuiColumnsSet* columns = &window->ColumnsStorage[n];
9419 ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
9459 ImGuiWindow* window = g.OpenPopupStack[i].Window;
9460 ImGui::BulletText("PopupID: %08x, Window: '%s'%s%s", g.OpenPopupStack[i].PopupId, window ? window->Name : "NULL", window && (window->Flags & ImGuiWindowFlags_ChildWindow) ? " ChildWindow" : "", window && (window->Flags & ImGuiWindowFlags_ChildMenu) ? " ChildMenu" : "");
9475 ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
9495 ImGuiWindow* window = g.Windows[n];
9496 if ((window->Flags & ImGuiWindowFlags_ChildWindow) || !window->WasActive)
9499 ImFormatString(buf, IM_ARRAYSIZE(buf), "%d", window->BeginOrderWithinContext);
9501 ImDrawList* overlay_draw_list = GetOverlayDrawList(window);
9502 overlay_draw_list->AddRectFilled(window->Pos, window->Pos + ImVec2(font_size, font_size), IM_COL32(200, 100, 100, 255));
9503 overlay_draw_list->AddText(NULL, font_size, window->Pos, IM_COL32(255, 255, 255, 255), buf);