Viewport: Switched to using unified platform-absolute mouse coordinates, which simplify lots of problems and simplify/reduce tricky conversions, makes ImVec2 less ambiguous. Fixed various viewport/windowing/popups/synchronization bugs. Settings on host-viewport are stored as relative (made settings decently compatible between viewport enable/disabled settings). Merged ImGuiViewport::Pos and ::PlatformPos. Tweaked thumbnails. Better, smaller code. (#1542)

This commit is contained in:
omar 2018-04-20 21:29:16 +02:00
parent 17a7f352b5
commit 456bbffcc4
6 changed files with 197 additions and 287 deletions

View File

@ -322,7 +322,7 @@ static void ImGui_ImplSDL2_CreateWindow(ImGuiViewport* viewport)
#if SDL_HAS_ALWAYS_ON_TOP #if SDL_HAS_ALWAYS_ON_TOP
sdl_flags |= (viewport->Flags & imGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0; sdl_flags |= (viewport->Flags & imGuiViewportFlags_TopMost) ? SDL_WINDOW_ALWAYS_ON_TOP : 0;
#endif #endif
data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->Pos.x, (int)viewport->Pos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags);
data->WindowOwned = true; data->WindowOwned = true;
if (use_opengl) if (use_opengl)
data->GLContext = SDL_GL_CreateContext(data->Window); data->GLContext = SDL_GL_CreateContext(data->Window);

View File

@ -406,7 +406,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
data->DwExStyle |= WS_EX_TOPMOST; data->DwExStyle |= WS_EX_TOPMOST;
// Create window // Create window
RECT rect = { (LONG)viewport->PlatformPos.x, (LONG)viewport->PlatformPos.y, (LONG)(viewport->PlatformPos.x + viewport->Size.x), (LONG)(viewport->PlatformPos.y + viewport->Size.y) }; RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle);
data->Hwnd = ::CreateWindowEx( data->Hwnd = ::CreateWindowEx(
data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name
@ -514,8 +514,8 @@ static float ImGui_ImplWin32_GetWindowDpiScale(ImGuiViewport* viewport)
// The first frame a viewport is created we don't have a window yet // The first frame a viewport is created we don't have a window yet
return ImGui_ImplWin32_GetDpiScaleForRect( return ImGui_ImplWin32_GetDpiScaleForRect(
(int)(viewport->PlatformPos.x), (int)(viewport->PlatformPos.y), (int)(viewport->Pos.x), (int)(viewport->Pos.y),
(int)(viewport->PlatformPos.x + viewport->Size.x), (int)(viewport->PlatformPos.y + viewport->Size.y)); (int)(viewport->Pos.x + viewport->Size.x), (int)(viewport->Pos.y + viewport->Size.y));
} }
static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

447
imgui.cpp
View File

@ -758,16 +758,11 @@ static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window);
// Viewports // Viewports
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
static inline ImVec2 ConvertViewportPosToPlatformPos(const ImVec2& imgui_pos, ImGuiViewport* viewport) { return imgui_pos - viewport->Pos + viewport->PlatformPos; }
static inline ImVec2 ConvertPlatformPosToViewportPos(const ImVec2& platform_pos, ImGuiViewport* viewport) { return platform_pos - viewport->PlatformPos + viewport->Pos; }
static inline ImVec2 ConvertViewportPosToViewportPos(const ImVec2& imgui_pos, ImGuiViewport* viewport_src, ImGuiViewport* viewport_dst) { if (viewport_src == viewport_dst) return imgui_pos; return (imgui_pos - viewport_src->Pos + viewport_src->PlatformPos - viewport_dst->PlatformPos + viewport_dst->Pos); }
static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size); static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, ImGuiViewportFlags flags, const ImVec2& platform_pos, const ImVec2& size);
static void UpdateViewports(); static void UpdateViewports();
static void UpdateSelectWindowViewport(ImGuiWindow* window); static void UpdateSelectWindowViewport(ImGuiWindow* window);
static void UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport); static void UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport);
static void SetCurrentViewport(ImGuiViewportP* viewport); static void SetCurrentViewport(ImGuiViewportP* viewport);
static void SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewportP* old_viewport, ImGuiViewportP* new_viewport);
static void TranslateOrEraseViewports(int viewport_idx_min, int viewport_idx_max, float delta_x, int delta_idx, ImGuiViewport* viewport_to_erase);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1932,8 +1927,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
Flags = FlagsPreviousFrame = 0; Flags = FlagsPreviousFrame = 0;
Viewport = NULL; Viewport = NULL;
ViewportId = 0; ViewportId = 0;
ViewportPlatformAllowMonitorExtend = -1; ViewportAllowPlatformMonitorExtend = -1;
ViewportPlatformPos = ImVec2(FLT_MAX, FLT_MAX); ViewportPos = ImVec2(FLT_MAX, FLT_MAX);
PosFloat = Pos = ImVec2(0.0f, 0.0f); PosFloat = Pos = ImVec2(0.0f, 0.0f);
Size = SizeFull = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f);
SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f);
@ -2774,20 +2769,16 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
} }
} }
static ImVec2 NavCalcPreferredMousePos(ImGuiViewportP** out_viewport) static ImVec2 NavCalcPreferredRefPos()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow) if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
{
if (out_viewport) *out_viewport = g.MouseRefViewport;
return ImFloor(g.IO.MousePos); return ImFloor(g.IO.MousePos);
}
// When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item // When navigation is active and mouse is disabled, decide on an arbitrary position around the bottom left of the currently navigated item
const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer]; const ImRect& rect_rel = g.NavWindow->NavRectRel[g.NavLayer];
ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight()));
ImRect visible_rect = g.NavWindow->Viewport->GetRect(); ImRect visible_rect = g.NavWindow->Viewport->GetRect();
if (out_viewport) *out_viewport = g.NavWindow->Viewport;
return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta.
} }
@ -3120,7 +3111,7 @@ static void ImGui::NavUpdate()
if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos))
{ {
IM_ASSERT(!g.NavDisableHighlight && g.NavDisableMouseHover); IM_ASSERT(!g.NavDisableHighlight && g.NavDisableMouseHover);
g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(NULL); g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredRefPos();
g.IO.WantSetMousePos = true; g.IO.WantSetMousePos = true;
} }
g.NavMousePosDirty = false; g.NavMousePosDirty = false;
@ -3303,36 +3294,34 @@ static void ImGui::NavUpdate()
g.NavScoringCount = 0; g.NavScoringCount = 0;
#if IMGUI_DEBUG_NAV_RECTS #if IMGUI_DEBUG_NAV_RECTS
if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList(g.NavWindow)->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) GetOverlayDrawList(g.NavWindow)->AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG]
if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames == 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(NULL); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames == 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredRefPos(NULL); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); GetOverlayDrawList(g.NavWindow)->AddCircleFilled(p, 3.0f, col); GetOverlayDrawList(g.NavWindow)->AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); }
#endif #endif
} }
static void ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport) static void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
{
window->Viewport = viewport;
window->ViewportId = viewport->ID;
window->ViewportOwned = (viewport->Window == window);
}
static void ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
return; return;
if (!(host_viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) || window->Viewport == host_viewport) if (!(viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) || window->Viewport == viewport)
return;
if (!viewport->GetRect().Contains(window->Rect()))
return; return;
ImRect host_viewport_rect = host_viewport->GetRect(); // Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child)
ImVec2 window_pos_in_host_viewport = ConvertViewportPosToViewportPos(window->Pos, window->Viewport, host_viewport);
ImRect window_rect_in_host_viewport = ImRect(window_pos_in_host_viewport, window_pos_in_host_viewport + window->Size);
if (!host_viewport_rect.Contains(window_rect_in_host_viewport))
return;
// Move to the existing viewport
ImGuiViewportP* old_viewport = window->Viewport; ImGuiViewportP* old_viewport = window->Viewport;
SetWindowViewportTranslateToPreservePlatformPos(window, window->Viewport, host_viewport);
// Move child/hosted windows as well (FIXME-OPT)
if (window->ViewportOwned) if (window->ViewportOwned)
{
for (int n = 0; n < g.Windows.Size; n++) for (int n = 0; n < g.Windows.Size; n++)
if (g.Windows[n]->Viewport == old_viewport) if (g.Windows[n]->Viewport == old_viewport)
SetWindowViewportTranslateToPreservePlatformPos(g.Windows[n], old_viewport, host_viewport); SetWindowViewport(g.Windows[n], viewport);
window->ViewportOwned = false; SetWindowViewport(window, viewport);
}
} }
static void ImGui::NewFrameUpdateMovingWindow() static void ImGui::NewFrameUpdateMovingWindow()
@ -3384,6 +3373,7 @@ static void ImGui::NewFrameUpdateMovingWindow()
// If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves. // If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves.
// This search won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window. // This search won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
// FIXME-VIEWPORT: Need a proper notion of focus. At least use the equivalent of LastFrameAsRefViewport on a per-window basis.
static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos) static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -3391,40 +3381,62 @@ static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 m
for (int n = 0; n < g.Viewports.Size; n++) for (int n = 0; n < g.Viewports.Size; n++)
{ {
ImGuiViewportP* viewport = g.Viewports[n]; ImGuiViewportP* viewport = g.Viewports[n];
ImRect platform_rect = ImRect(viewport->PlatformPos, viewport->PlatformPos + viewport->Size); if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && viewport->GetRect().Contains(mouse_platform_pos))
if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && platform_rect.Contains(mouse_platform_pos))
if (best_candidate == NULL || best_candidate->LastFrameAsRefViewport < viewport->LastFrameAsRefViewport) if (best_candidate == NULL || best_candidate->LastFrameAsRefViewport < viewport->LastFrameAsRefViewport)
best_candidate = viewport; best_candidate = viewport;
} }
return best_candidate; return best_candidate;
} }
static void TranslateWindow(ImGuiWindow* window, const ImVec2& delta)
{
window->Pos += delta;
window->PosFloat += delta;
window->ClipRect.Translate(delta);
window->WindowRectClipped.Translate(delta);
window->InnerRect.Translate(delta);
window->DC.CursorPos += delta;
window->DC.CursorStartPos += delta;
window->DC.CursorMaxPos += delta;
window->DC.LastItemRect.Translate(delta);
window->DC.LastItemDisplayRect.Translate(delta);
}
static void ImGui::UpdateViewports() static void ImGui::UpdateViewports()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size); IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size);
// Mouse handling: latch the expected mouse OS position (if any) before processing viewport erasure // Update mouse reference viewport
ImGuiViewportP* viewport_ref = g.IO.MousePosViewport ? FindViewportByID(g.IO.MousePosViewport) : g.Viewports[0]; g.MouseRefPrevViewport = g.MouseRefViewport;
const ImVec2 mouse_platform_pos = ConvertViewportPosToPlatformPos(g.IO.MousePos, viewport_ref); g.MouseRefViewport = g.IO.MousePosViewport ? FindViewportByID(g.IO.MousePosViewport) : g.Viewports[0];
// Update main viewport with current size (and OS window position, if known)
ImGuiViewportP* main_viewport = g.Viewports[0];
IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
ImVec2 main_viewport_platform_pos = ImVec2(0.0f, 0.0f);
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
main_viewport_platform_pos = g.PlatformIO.Platform_GetWindowPos(main_viewport);
AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_CanHostOtherWindows, main_viewport_platform_pos, g.IO.DisplaySize);
g.CurrentViewport = NULL; g.CurrentViewport = NULL;
for (int n = 0; n < g.Viewports.Size; n++) for (int n = 0; n < g.Viewports.Size; n++)
{ {
// Erase unused viewports // Erase unused viewports
ImGuiViewportP* viewport = g.Viewports[n]; ImGuiViewportP* viewport = g.Viewports[n];
IM_ASSERT(viewport->Idx == n); viewport->Idx = n;
if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2) if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2)
{ {
// Translate windows like if we were resizing the viewport to be zero-width // Clear references to this viewport in windows (window->ViewportId becomes the master data)
TranslateOrEraseViewports(n + 1, g.Viewports.Size, viewport->Pos.x - viewport->GetNextX(), -1, viewport); for (int window_n = 0; window_n < g.Windows.Size; window_n++)
if (g.Windows[window_n]->Viewport == viewport)
g.Windows[window_n]->Viewport = NULL;
g.Viewports.erase(g.Viewports.Data + n); g.Viewports.erase(g.Viewports.Data + n);
// Destroy // Destroy
if (viewport == viewport_ref) viewport_ref = NULL; if (viewport == g.MouseRefViewport) g.MouseRefViewport = main_viewport;
if (viewport == g.MouseRefViewport) g.MouseRefViewport = NULL; if (viewport == g.MouseRefPrevViewport) g.MouseRefPrevViewport = main_viewport;
if (viewport == g.MouseRefPrevViewport) g.MouseRefPrevViewport = NULL;
if (viewport == g.MouseHoveredLastViewport) g.MouseHoveredLastViewport = NULL; if (viewport == g.MouseHoveredLastViewport) g.MouseHoveredLastViewport = NULL;
IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL); IM_ASSERT(viewport->RendererUserData == NULL && viewport->PlatformUserData == NULL && viewport->PlatformHandle == NULL);
IM_ASSERT(g.PlatformIO.Viewports.contains(viewport) == false); IM_ASSERT(g.PlatformIO.Viewports.contains(viewport) == false);
@ -3433,22 +3445,21 @@ static void ImGui::UpdateViewports()
continue; continue;
} }
// Translate resized viewports
if (n + 1 < g.Viewports.Size)
{
float dx = viewport->GetNextX() - g.Viewports[viewport->Idx + 1]->Pos.x;
if (dx != 0.0f)
TranslateOrEraseViewports(viewport->Idx + 1, g.Viewports.Size, dx, 0, NULL);
}
// Apply Position and Size (from Platform Window to ImGui) if requested // Apply Position and Size (from Platform Window to ImGui) if requested
// We do it here early in the frame instead of UpdatePlatformWindows() to allow the platform back-end to set PlatformRequestResize early // We do it here early in the frame instead of UpdatePlatformWindows() to allow the platform back-end to set PlatformRequestResize early
// (e.g. in their own message handler before NewFrame) and not have a frame of lag. // (e.g. in their own message handler before NewFrame) and not have a frame of lag.
if (viewport->PlatformRequestMove) if (viewport->PlatformRequestMove)
viewport->PlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport); viewport->Pos = g.PlatformIO.Platform_GetWindowPos(viewport);
if (viewport->PlatformRequestResize) if (viewport->PlatformRequestResize)
viewport->Size = g.PlatformIO.Platform_GetWindowSize(viewport); viewport->Size = g.PlatformIO.Platform_GetWindowSize(viewport);
// Translate resized viewports
ImVec2 delta = viewport->Pos - viewport->LastPos;
if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (delta.x != 0.0f || delta.y != 0.0f))
for (int window_n = 0; window_n < g.Windows.Size; window_n++)
if (g.Windows[window_n]->Viewport == viewport)
TranslateWindow(g.Windows[window_n], delta);
// Update DPI Scale // Update DPI Scale
float new_dpi_scale; float new_dpi_scale;
if (g.PlatformIO.Platform_GetWindowDpiScale) if (g.PlatformIO.Platform_GetWindowDpiScale)
@ -3470,19 +3481,13 @@ static void ImGui::UpdateViewports()
viewport->DpiScale = new_dpi_scale; viewport->DpiScale = new_dpi_scale;
} }
// Update main viewport with current size (and OS window position, if known)
ImGuiViewportP* main_viewport = g.Viewports[0];
IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
ImVec2 main_viewport_platform_pos = ImVec2(0.0f, 0.0f);
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
main_viewport_platform_pos = g.PlatformIO.Platform_GetWindowPos(main_viewport);
AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, ImGuiViewportFlags_CanHostOtherWindows, main_viewport_platform_pos, g.IO.DisplaySize);
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
{ {
g.MouseRefViewport = g.MouseRefPrevViewport = main_viewport; g.MouseRefViewport = g.MouseRefPrevViewport = main_viewport;
g.MouseRefViewport->LastFrameAsRefViewport = g.FrameCount;
return; return;
} }
g.MouseRefViewport->LastFrameAsRefViewport = g.FrameCount;
// Mouse handling: decide on the actual mouse viewport for this frame between the active/focused viewport and the hovered viewport. // Mouse handling: decide on the actual mouse viewport for this frame between the active/focused viewport and the hovered viewport.
ImGuiViewportP* viewport_hovered = NULL; ImGuiViewportP* viewport_hovered = NULL;
@ -3493,7 +3498,7 @@ static void ImGui::UpdateViewports()
{ {
// Back-end failed at honoring its contract // Back-end failed at honoring its contract
IM_ASSERT(0); IM_ASSERT(0);
viewport_hovered = FindViewportHoveredFromPlatformWindowStack(mouse_platform_pos); viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
} }
} }
else else
@ -3501,22 +3506,11 @@ static void ImGui::UpdateViewports()
// If the back-end doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search: // If the back-end doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
// A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window. // A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
// B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO) // B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
viewport_hovered = FindViewportHoveredFromPlatformWindowStack(mouse_platform_pos); viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
} }
if (viewport_hovered != NULL) if (viewport_hovered != NULL)
g.MouseHoveredLastViewport = viewport_hovered; g.MouseHoveredLastViewport = viewport_hovered;
// If reference viewport just has been deleted, use a position relative to the main viewport
if (viewport_ref == NULL)
{
viewport_ref = main_viewport;
g.IO.MousePos = ConvertPlatformPosToViewportPos(mouse_platform_pos, viewport_ref);
}
g.MouseRefPrevViewport = g.MouseRefViewport;
g.MouseRefViewport = viewport_ref;
g.MouseRefViewport->LastFrameAsRefViewport = g.FrameCount;
// When dragging something, always refer to the last hovered viewport. // When dragging something, always refer to the last hovered viewport.
// (So when we are between viewports, our dragged preview will tend to show in the last viewport even if we don't have tooltips in viewports) // (So when we are between viewports, our dragged preview will tend to show in the last viewport even if we don't have tooltips in viewports)
// Also consider the case of holding on a menu item to browse child menus: even thought a mouse button is held, there's no active id because menu items only react on mouse release. // Also consider the case of holding on a menu item to browse child menus: even thought a mouse button is held, there's no active id because menu items only react on mouse release.
@ -3526,10 +3520,7 @@ static void ImGui::UpdateViewports()
if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL) if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
viewport_hovered = g.MouseHoveredLastViewport; viewport_hovered = g.MouseHoveredLastViewport;
if (viewport_hovered != NULL && viewport_hovered != g.MouseRefViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs)) if (viewport_hovered != NULL && viewport_hovered != g.MouseRefViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
{
g.IO.MousePos = ConvertViewportPosToViewportPos(g.IO.MousePos, g.MouseRefViewport, viewport_hovered);
g.MouseRefViewport = viewport_hovered; g.MouseRefViewport = viewport_hovered;
}
} }
IM_ASSERT(g.MouseRefViewport != NULL); IM_ASSERT(g.MouseRefViewport != NULL);
@ -3541,6 +3532,7 @@ void ImGui::UpdatePlatformWindows()
IM_ASSERT(g.FrameCountEnded == g.FrameCount && "Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?"); IM_ASSERT(g.FrameCountEnded == g.FrameCount && "Forgot to call Render() or EndFrame() before UpdatePlatformWindows()?");
IM_ASSERT(g.FrameCountPlatformEnded < g.FrameCount); IM_ASSERT(g.FrameCountPlatformEnded < g.FrameCount);
g.FrameCountPlatformEnded = g.FrameCount; g.FrameCountPlatformEnded = g.FrameCount;
g.Viewports[0]->LastPos = g.Viewports[0]->Pos;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
return; return;
@ -3549,6 +3541,7 @@ void ImGui::UpdatePlatformWindows()
for (int i = 1; i < g.Viewports.Size; i++) for (int i = 1; i < g.Viewports.Size; i++)
{ {
ImGuiViewportP* viewport = g.Viewports[i]; ImGuiViewportP* viewport = g.Viewports[i];
viewport->LastPos = viewport->Pos;
if (viewport->LastFrameActive < g.FrameCount) if (viewport->LastFrameActive < g.FrameCount)
{ {
if (viewport->LastFrameActive < g.FrameCount - 1) if (viewport->LastFrameActive < g.FrameCount - 1)
@ -3587,7 +3580,7 @@ void ImGui::UpdatePlatformWindows()
// Apply Position and Size (from ImGui to Platform Window) // Apply Position and Size (from ImGui to Platform Window)
if (!viewport->PlatformRequestMove) if (!viewport->PlatformRequestMove)
g.PlatformIO.Platform_SetWindowPos(viewport, viewport->PlatformPos); g.PlatformIO.Platform_SetWindowPos(viewport, viewport->Pos);
if (!viewport->PlatformRequestResize) if (!viewport->PlatformRequestResize)
g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size); g.PlatformIO.Platform_SetWindowSize(viewport, viewport->Size);
@ -3798,6 +3791,7 @@ void ImGui::NewFrame()
IM_ASSERT(g.FrameCount == 0 || g.FrameCountPlatformEnded == g.FrameCount && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?"); IM_ASSERT(g.FrameCount == 0 || g.FrameCountPlatformEnded == g.FrameCount && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?");
IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?");
IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?");
IM_ASSERT(g.PlatformIO.Platform_GetWindowPos != NULL && "Platform init didn't install handlers?");
IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) && "Platform init didn't setup main viewport."); IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) && "Platform init didn't setup main viewport.");
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function! IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function!
@ -4000,11 +3994,11 @@ static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
float x, y; float x, y;
int i; int i;
ImU32 u1; ImU32 u1;
if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) { settings->Pos = ImVec2(x, y); } if (sscanf(line, "Pos=%f,%f", &x, &y) == 2) { settings->Pos = ImVec2(x, y); }
else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) { settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); } else if (sscanf(line, "Size=%f,%f", &x, &y) == 2) { settings->Size = ImMax(ImVec2(x, y), GImGui->Style.WindowMinSize); }
else if (sscanf(line, "ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; } else if (sscanf(line, "ViewportId=0x%08X", &u1) == 1) { settings->ViewportId = u1; }
else if (sscanf(line, "ViewportPlatformPos=%f,%f", &x, &y)==2) { settings->ViewportPlatformPos = ImVec2(x, y); } else if (sscanf(line, "ViewportPos=%f,%f", &x, &y) == 2) { settings->ViewportPos = ImVec2(x, y); }
else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); } else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
} }
static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
@ -4019,10 +4013,10 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting
ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID); ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID);
if (!settings) if (!settings)
settings = AddWindowSettings(window->Name); settings = AddWindowSettings(window->Name);
settings->Pos = window->Pos;// - window->Viewport->Pos; settings->Pos = window->Pos - window->ViewportPos;
settings->Size = window->SizeFull; settings->Size = window->SizeFull;
settings->ViewportId = window->ViewportId; settings->ViewportId = window->ViewportId;
settings->ViewportPlatformPos = window->ViewportPlatformPos; settings->ViewportPos = window->ViewportPos;
settings->Collapsed = window->Collapsed; settings->Collapsed = window->Collapsed;
} }
@ -4032,20 +4026,18 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting
for (int i = 0; i != g.SettingsWindows.Size; i++) for (int i = 0; i != g.SettingsWindows.Size; i++)
{ {
const ImGuiWindowSettings* settings = &g.SettingsWindows[i]; const ImGuiWindowSettings* settings = &g.SettingsWindows[i];
if (settings->Pos.x == FLT_MAX)
continue;
const char* name = settings->Name; const char* name = settings->Name;
if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID()
name = p; name = p;
buf->appendf("[%s][%s]\n", handler->TypeName, name); buf->appendf("[%s][%s]\n", handler->TypeName, name);
buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID) if (settings->ViewportId != 0 && settings->ViewportId != ImGui::IMGUI_VIEWPORT_DEFAULT_ID)
{ {
buf->appendf("ViewportPos=%d,%d\n", (int)settings->ViewportPos.x, (int)settings->ViewportPos.y);
buf->appendf("ViewportId=0x%08X\n", settings->ViewportId); buf->appendf("ViewportId=0x%08X\n", settings->ViewportId);
if (settings->ViewportPlatformPos.x != FLT_MAX && settings->ViewportPlatformPos.y != FLT_MAX)
buf->appendf("ViewportPlatformPos=%d,%d\n", (int)settings->ViewportPlatformPos.x, (int)settings->ViewportPlatformPos.y);
} }
if (settings->Pos.x != 0.0f || settings->Pos.y != 0.0f || settings->ViewportId == ImGui::IMGUI_VIEWPORT_DEFAULT_ID)
buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y);
buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y);
buf->appendf("Collapsed=%d\n", settings->Collapsed); buf->appendf("Collapsed=%d\n", settings->Collapsed);
buf->appendf("\n"); buf->appendf("\n");
} }
@ -4573,13 +4565,12 @@ void ImGui::Render()
if (g.IO.MouseDrawCursor && g.IO.Fonts->GetMouseCursorTexData(g.MouseCursor, &offset, &size, &uv[0], &uv[2])) if (g.IO.MouseDrawCursor && g.IO.Fonts->GetMouseCursorTexData(g.MouseCursor, &offset, &size, &uv[0], &uv[2]))
{ {
// We need to account for the possibility of the mouse cursor straddling multiple viewports... // We need to account for the possibility of the mouse cursor straddling multiple viewports...
const ImVec2 main_pos = g.IO.MousePos - offset; const ImVec2 pos = g.IO.MousePos - offset;
const ImTextureID tex_id = g.IO.Fonts->TexID; const ImTextureID tex_id = g.IO.Fonts->TexID;
const float sc = g.Style.MouseCursorScale; const float sc = g.Style.MouseCursorScale;
for (int viewport_n = 0; viewport_n < g.Viewports.Size; viewport_n++) for (int viewport_n = 0; viewport_n < g.Viewports.Size; viewport_n++)
{ {
ImGuiViewportP* viewport = g.Viewports[viewport_n]; ImGuiViewportP* viewport = g.Viewports[viewport_n];
ImVec2 pos = (g.MouseRefViewport == viewport) ? main_pos : ConvertViewportPosToViewportPos(main_pos, g.MouseRefViewport, viewport);
if (viewport->GetRect().Overlaps(ImRect(pos, pos + ImVec2(2,2)*sc + size * sc))) if (viewport->GetRect().Overlaps(ImRect(pos, pos + ImVec2(2,2)*sc + size * sc)))
{ {
ImDrawList* draw_list = GetOverlayDrawList(viewport); ImDrawList* draw_list = GetOverlayDrawList(viewport);
@ -4637,55 +4628,6 @@ ImGuiViewport* ImGui::FindViewportByPlatformHandle(void* platform_handle)
return NULL; return NULL;
} }
static void TranslateWindowX(ImGuiWindow* window, float dx)
{
window->Pos.x += dx;
window->PosFloat.x += dx;
window->ClipRect.Translate(dx, 0.0f);
window->WindowRectClipped.Translate(dx, 0.0f);
window->InnerRect.Translate(dx, 0.0f);
window->DC.CursorPos.x += dx;
window->DC.CursorStartPos.x += dx;
window->DC.CursorMaxPos.x += dx;
window->DC.LastItemRect.Translate(dx, 0.0f);
window->DC.LastItemDisplayRect.Translate(dx, 0.0f);
}
static void ImGui::TranslateOrEraseViewports(int viewport_idx_min, int viewport_idx_max, float delta_x, int delta_idx, ImGuiViewport* viewport_to_erase)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(delta_x != 0.0f || delta_idx != 0);
IM_ASSERT(g.CurrentViewport == NULL); // We only resize at the beginning of the frame
for (int n = 0; n < g.Windows.Size; n++)
{
ImGuiWindow* window = g.Windows[n];
if (window->Viewport == viewport_to_erase)
window->Viewport = NULL; // Set to NULL, window->ViewportId becomes the master data
if (window->Viewport == NULL)
continue;
if (window->Viewport->Idx < viewport_idx_min || window->Viewport->Idx > viewport_idx_max)
continue;
TranslateWindowX(window, delta_x);
}
for (int n = viewport_idx_min; n < viewport_idx_max; n++)
{
ImGuiViewportP* viewport = g.Viewports[n];
viewport->Pos.x += delta_x;
viewport->Idx += delta_idx;
// Patch mouse positions immediately so mouse delta will not appears to jump around
ImGuiID viewport_id = viewport->ID;
if (viewport_id == g.IO.MousePosViewport) // We are early in NewFrame and g.MousePosViewport hasn't been set, patch the source.
g.IO.MousePos.x += delta_x;
if (viewport == g.MouseRefPrevViewport)
g.IO.MousePosPrev.x += delta_x;
for (int mouse_n = 0; mouse_n < IM_ARRAYSIZE(g.MouseClickedPosViewportId); mouse_n++)
if (g.MouseClickedPosViewportId[mouse_n] == viewport_id)
g.IO.MouseClickedPos[mouse_n].x += delta_x;
}
}
void ImGui::SetCurrentViewport(ImGuiViewportP* viewport) void ImGui::SetCurrentViewport(ImGuiViewportP* viewport)
{ {
// Notify platform layer of viewport changes // Notify platform layer of viewport changes
@ -4708,8 +4650,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, ImGuiV
ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id); ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id);
if (viewport) if (viewport)
{ {
// We defer translating windows to the beginning of the frame. viewport->Pos = platform_pos;
// Our viewport system already works with fully overlapped viewports, it's only certain user interactions that don't and they can't be performed while resizing.
viewport->Size = size; viewport->Size = size;
} }
else else
@ -4718,7 +4659,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, ImGuiV
viewport = IM_NEW(ImGuiViewportP)(); viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = id; viewport->ID = id;
viewport->Idx = g.Viewports.Size; viewport->Idx = g.Viewports.Size;
viewport->Pos = ImVec2(g.Viewports.back()->GetNextX(), 0.0f); viewport->Pos = viewport->LastPos = platform_pos;
viewport->Size = size; viewport->Size = size;
g.Viewports.push_back(viewport); g.Viewports.push_back(viewport);
@ -4728,10 +4669,8 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, ImGuiV
g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y); g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
} }
IM_ASSERT(viewport->Pos.y == 0.0f);
viewport->Window = window; viewport->Window = window;
viewport->Flags = flags; viewport->Flags = flags;
viewport->PlatformPos = platform_pos;
viewport->LastFrameActive = g.FrameCount; viewport->LastFrameActive = g.FrameCount;
if (window != NULL) if (window != NULL)
@ -5454,7 +5393,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenFrameCount = g.FrameCount;
popup_ref.OpenParentId = parent_window->IDStack.back(); popup_ref.OpenParentId = parent_window->IDStack.back();
popup_ref.OpenMousePos = g.IO.MousePos; popup_ref.OpenMousePos = g.IO.MousePos;
popup_ref.OpenPopupPos = NavCalcPreferredMousePos(NULL); popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
//printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id); //printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id);
if (g.OpenPopupStack.Size < current_stack_size + 1) if (g.OpenPopupStack.Size < current_stack_size + 1)
@ -5904,12 +5843,12 @@ static ImRect FindAllowedExtentRectForWindow(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImRect r_screen; ImRect r_screen;
if (window->ViewportPlatformAllowMonitorExtend != -1) if (window->ViewportAllowPlatformMonitorExtend != -1)
{ {
// Extent with be in the frame of reference of the given viewport (so Min is likely to be negative here) // Extent with be in the frame of reference of the given viewport (so Min is likely to be negative here)
const ImGuiPlatformMonitor& monitor = g.PlatformIO.Monitors[window->ViewportPlatformAllowMonitorExtend]; const ImGuiPlatformMonitor& monitor = g.PlatformIO.Monitors[window->ViewportAllowPlatformMonitorExtend];
r_screen.Min = ImGui::ConvertPlatformPosToViewportPos(monitor.Pos, window->Viewport); r_screen.Min = monitor.Pos;
r_screen.Max = ImGui::ConvertPlatformPosToViewportPos(monitor.Pos + monitor.Size, window->Viewport); r_screen.Max = monitor.Pos + monitor.Size;
} }
else else
{ {
@ -5948,7 +5887,7 @@ static ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window)
{ {
// Position tooltip (always follows mouse) // Position tooltip (always follows mouse)
float sc = g.Style.MouseCursorScale; float sc = g.Style.MouseCursorScale;
ImVec2 ref_pos = NavCalcPreferredMousePos(NULL); ImVec2 ref_pos = NavCalcPreferredRefPos();
ImRect r_outer = FindAllowedExtentRectForWindow(window); ImRect r_outer = FindAllowedExtentRectForWindow(window);
ImRect r_avoid; ImRect r_avoid;
if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos))
@ -5992,18 +5931,23 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl
{ {
// Retrieve settings from .ini file // Retrieve settings from .ini file
// Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window.
window->Pos = window->PosFloat = ImVec2(60, 60); ImGuiViewport* main_viewport = ImGui::GetMainViewport();
window->Pos = window->PosFloat = main_viewport->Pos + ImVec2(60, 60);
if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID)) if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID))
{ {
SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false);
window->PosFloat = settings->Pos;
window->Pos = ImFloor(window->PosFloat);
window->Collapsed = settings->Collapsed;
if (settings->ViewportId) if (settings->ViewportId)
{
window->ViewportId = settings->ViewportId; window->ViewportId = settings->ViewportId;
if (settings->ViewportPlatformPos.x != FLT_MAX && settings->ViewportPlatformPos.y != FLT_MAX) window->ViewportPos = settings->ViewportPos;
window->ViewportPlatformPos = settings->ViewportPlatformPos; }
else
{
window->ViewportPos = main_viewport->Pos;
}
window->Pos = window->PosFloat = ImFloor(settings->Pos + window->ViewportPos);
window->Collapsed = settings->Collapsed;
if (ImLengthSqr(settings->Size) > 0.00001f) if (ImLengthSqr(settings->Size) > 0.00001f)
size = settings->Size; size = settings->Size;
} }
@ -6081,7 +6025,7 @@ static ImVec2 CalcSizeAutoFit(ImGuiWindow* window, const ImVec2& size_contents)
else else
{ {
// Maximum window size is determined by the viewport size or monitor size // Maximum window size is determined by the viewport size or monitor size
const int monitor_idx = window->ViewportPlatformAllowMonitorExtend; const int monitor_idx = window->ViewportAllowPlatformMonitorExtend;
ImVec2 avail_size = window->Viewport->Size; ImVec2 avail_size = window->Viewport->Size;
if (window->ViewportOwned) if (window->ViewportOwned)
avail_size = (monitor_idx >= 0 && monitor_idx < g.PlatformIO.Monitors.Size) ? g.PlatformIO.Monitors[monitor_idx].Size : ImVec2(FLT_MAX, FLT_MAX); avail_size = (monitor_idx >= 0 && monitor_idx < g.PlatformIO.Monitors.Size) ? g.PlatformIO.Monitors[monitor_idx].Size : ImVec2(FLT_MAX, FLT_MAX);
@ -6149,26 +6093,7 @@ static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& co
*out_size = size_constrained; *out_size = size_constrained;
} }
static void ImGui::SetWindowViewportTranslateToPreservePlatformPos(ImGuiWindow* window, ImGuiViewportP* prev_viewport, ImGuiViewportP* curr_viewport) static int FindPlatformMonitorForPos(ImVec2 platform_pos)
{
if (prev_viewport == curr_viewport)
return;
ImVec2 new_pos = ConvertViewportPosToViewportPos(window->PosFloat, prev_viewport, curr_viewport);
if ((window->FlagsPreviousFrame ^ window->Flags) & ImGuiWindowFlags_NoTitleBar)
{
// As a convenience, automatically adjust for client rect difference for the common use case of toggling the imgui title-bar when we move our tools to a separate OS window
float title_bar_height = GetFrameHeight();
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
title_bar_height = -title_bar_height;
new_pos.y += title_bar_height;
window->SizeFull.y -= title_bar_height;
}
SetWindowPos(window, new_pos, ImGuiCond_Always);
window->Viewport = curr_viewport;
window->ViewportId = curr_viewport->ID;
}
static int FindPlatformMonitorForPlatformPos(ImVec2 platform_pos)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
for (int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size; monitor_n++) for (int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size; monitor_n++)
@ -6186,7 +6111,7 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags; ImGuiWindowFlags flags = window->Flags;
window->ViewportPlatformAllowMonitorExtend = -1; window->ViewportAllowPlatformMonitorExtend = -1;
// Restore main viewport if multi-viewport is not supported by the back-end // Restore main viewport if multi-viewport is not supported by the back-end
ImGuiViewportP* main_viewport = g.Viewports[0]; ImGuiViewportP* main_viewport = g.Viewports[0];
@ -6221,8 +6146,8 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
if (window->Viewport == NULL && window->ViewportId != 0) if (window->Viewport == NULL && window->ViewportId != 0)
{ {
window->Viewport = FindViewportByID(window->ViewportId); window->Viewport = FindViewportByID(window->ViewportId);
if (window->Viewport == NULL && window->ViewportPlatformPos.x != FLT_MAX && window->ViewportPlatformPos.y != FLT_MAX) if (window->Viewport == NULL && window->ViewportPos.x != FLT_MAX && window->ViewportPos.y != FLT_MAX)
window->Viewport = AddUpdateViewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportPlatformPos, window->Size); window->Viewport = AddUpdateViewport(window, window->ID, ImGuiViewportFlags_NoDecoration, window->ViewportPos, window->Size);
} }
if (g.NextWindowData.ViewportCond) if (g.NextWindowData.ViewportCond)
@ -6246,14 +6171,9 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
// already have displaced the window outside of its viewport boundaries. While this is currently working it is very smelly. // already have displaced the window outside of its viewport boundaries. While this is currently working it is very smelly.
if (window->Viewport == NULL || !window->Viewport->GetRect().Contains(window->Rect())) if (window->Viewport == NULL || !window->Viewport->GetRect().Contains(window->Rect()))
{ {
// Calculate mouse position in OS/platform coordinates, create a Viewport at this position. ImVec2 viewport_pos = g.IO.MousePos - g.ActiveIdClickOffset;
ImVec2 platform_pos = ConvertViewportPosToPlatformPos(g.IO.MousePos - g.ActiveIdClickOffset, g.MouseRefViewport);
ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs; ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoInputs;
window->Viewport = AddUpdateViewport(window, window->ID, viewport_flags, platform_pos, window->Size); window->Viewport = AddUpdateViewport(window, window->ID, viewport_flags, viewport_pos, window->Size);
}
else
{
window->Viewport = g.MouseRefViewport;
} }
} }
@ -6262,28 +6182,19 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
allow_protrude_on_whole_monitor |= (flags & ImGuiWindowFlags_Tooltip) != 0; allow_protrude_on_whole_monitor |= (flags & ImGuiWindowFlags_Tooltip) != 0;
allow_protrude_on_whole_monitor |= (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) != 0; allow_protrude_on_whole_monitor |= (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) != 0;
if (allow_protrude_on_whole_monitor) if (allow_protrude_on_whole_monitor)
{ window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos(NavCalcPreferredRefPos());
ImGuiViewportP* ref_viewport; if (window->ViewportTrySplit && window->ViewportAllowPlatformMonitorExtend == -1)
ImVec2 ref_pos = NavCalcPreferredMousePos(&ref_viewport); window->ViewportAllowPlatformMonitorExtend = FindPlatformMonitorForPos(window->Viewport->Pos);
window->ViewportPlatformAllowMonitorExtend = FindPlatformMonitorForPlatformPos(ConvertViewportPosToPlatformPos(ref_pos, ref_viewport));
}
if (window->ViewportTrySplit && window->ViewportPlatformAllowMonitorExtend == -1)
window->ViewportPlatformAllowMonitorExtend = FindPlatformMonitorForPlatformPos(window->Viewport->PlatformPos);
window->ViewportTrySplit = false; window->ViewportTrySplit = false;
// Fallback to default viewport // Fallback to default viewport
if (window->Viewport == NULL) if (window->Viewport == NULL)
window->Viewport = main_viewport; window->Viewport = main_viewport;
// When we own the viewport update its size/position // Update flags
if (window == window->Viewport->Window && window->Viewport->LastFrameActive != g.FrameCount) window->ViewportOwned = (window == window->Viewport->Window);
{ if (window->ViewportOwned)
window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration; window->Viewport->Flags |= ImGuiViewportFlags_NoDecoration;
if (!window->Viewport->PlatformRequestResize)
window->Viewport->Size = window->Size;
window->Viewport->PlatformPos = ConvertViewportPosToPlatformPos(window->Pos, window->Viewport);
window->ViewportOwned = true;
}
// If the OS window has a title bar, hide our imgui title bar // If the OS window has a title bar, hide our imgui title bar
if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration)) if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
@ -6359,7 +6270,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
{ {
// Resize from any of the four corners // Resize from any of the four corners
// We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
ImVec2 corner_target = ConvertViewportPosToViewportPos(g.IO.MousePos, g.MouseRefViewport, window->Viewport) - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip
CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target); CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target);
} }
if (resize_grip_n == 0 || held || hovered) if (resize_grip_n == 0 || held || hovered)
@ -6422,10 +6333,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au
} }
if (pos_target.x != FLT_MAX) if (pos_target.x != FLT_MAX)
{ {
if (window->ViewportOwned) window->Pos = window->PosFloat = ImFloor(pos_target);
window->Viewport->PlatformPos = ConvertViewportPosToPlatformPos(ImFloor(pos_target), window->Viewport);
else
window->Pos = window->PosFloat = ImFloor(pos_target);
MarkIniSettingsDirty(window); MarkIniSettingsDirty(window);
} }
@ -6716,16 +6624,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) else if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip)
window->PosFloat = FindBestWindowPosForPopup(window); window->PosFloat = FindBestWindowPosForPopup(window);
if (window->ViewportPlatformAllowMonitorExtend != -1 && !window->ViewportOwned) if (window->ViewportAllowPlatformMonitorExtend != -1 && !window->ViewportOwned)
{ {
if (!window->Viewport->GetRect().Contains(ImRect(window->PosFloat, window->PosFloat + window->Size))) if (!window->Viewport->GetRect().Contains(ImRect(window->PosFloat, window->PosFloat + window->Size)))
{ {
// Late create viewport, based on the assumption that with our calculations, the DPI will be known ahead (same as the DPI of the selection done in UpdateSelectWindowViewport) // Late create viewport, based on the assumption that with our calculations, the DPI will be known ahead (same as the DPI of the selection done in UpdateSelectWindowViewport)
//ImGuiViewport* old_viewport = window->Viewport; //ImGuiViewport* old_viewport = window->Viewport;
ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ((window->Flags & ImGuiWindowFlags_NoInputs) ? ImGuiViewportFlags_NoInputs : 0); ImGuiViewportFlags viewport_flags = ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoFocusOnAppearing | ((window->Flags & ImGuiWindowFlags_NoInputs) ? ImGuiViewportFlags_NoInputs : 0);
ImVec2 platform_pos = ConvertViewportPosToPlatformPos(window->PosFloat, window->Viewport); window->Viewport = AddUpdateViewport(window, window->ID, viewport_flags, window->PosFloat, window->Size);
window->Viewport = AddUpdateViewport(window, window->ID, viewport_flags, platform_pos, window->Size);
window->ViewportOwned = true;
// FIXME-DPI // FIXME-DPI
//IM_ASSERT(old_viewport->DpiScale == window->Viewport->DpiScale); // FIXME-DPI: Something went wrong //IM_ASSERT(old_viewport->DpiScale == window->Viewport->DpiScale); // FIXME-DPI: Something went wrong
@ -6735,14 +6641,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
} }
} }
// Position window to fit within viewport
// We can also tell the back-end that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha
if (window->ViewportOwned) if (window->ViewportOwned)
{ {
window->Viewport->Flags |= ImGuiViewportFlags_NoRendererClear; // Synchronize viewport --> window
window->PosFloat = window->Viewport->Pos; if (window->Viewport->PlatformRequestMove)
window->PosFloat = window->Viewport->Pos;
if (window->Viewport->PlatformRequestResize) if (window->Viewport->PlatformRequestResize)
window->Size = window->SizeFull = window->Viewport->Size; window->Size = window->SizeFull = window->Viewport->Size;
// We also tell the back-end that clearing the platform window won't be necessary, as our window is filling the viewport and we have disabled BgAlpha
window->Viewport->Flags |= ImGuiViewportFlags_NoRendererClear;
} }
// Clamp position so window stays visible within its viewport // Clamp position so window stays visible within its viewport
@ -6788,10 +6696,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]);
// When a window is marked as owning its viewport, we immediately update the viewport after a resize // When a window is marked as owning its viewport, we immediately update the viewport after a resize
window->ViewportPlatformPos = window->Viewport->PlatformPos; window->ViewportPos = window->Viewport->Pos;
if (window->ViewportOwned && !window->Viewport->PlatformRequestResize && (window->SizeFull.x != window->Viewport->Size.x || window->SizeFull.y != window->Viewport->Size.y))
// Synchronize window --> viewport
if (window->ViewportOwned)
{ {
window->Viewport->Size = window->SizeFull; if (!window->Viewport->PlatformRequestMove)
window->Viewport->Pos = window->PosFloat;
if (!window->Viewport->PlatformRequestResize)
window->Viewport->Size = window->Size;
viewport_rect = window->Viewport->GetRect(); viewport_rect = window->Viewport->GetRect();
} }
@ -12012,7 +11925,7 @@ bool ImGui::BeginMainMenuBar()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f)); g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
SetNextWindowPos(ImVec2(0.0f, 0.0f)); SetNextWindowPos(g.Viewports[0]->Pos);
SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y)); SetNextWindowSize(ImVec2(g.IO.DisplaySize.x, g.NextWindowData.MenuBarOffsetMinVal.y + g.FontBaseSize + g.Style.FramePadding.y));
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0)); PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0,0));
@ -12233,8 +12146,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
if (menu_is_open) if (menu_is_open)
{ {
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
//SetNextWindowPos(popup_pos, ImGuiCond_Always); SetNextWindowPos(popup_pos, ImGuiCond_Always);
SetNextWindowPos(popup_pos, ImGuiCond_Appearing); // FIXME-VIEWPORT: This needs to work with ImGuiCond_Always
ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu);
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
} }
@ -14077,38 +13989,6 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
// HELP // HELP
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void RenderViewportThumbnail(ImDrawList* draw_list, const ImRect& bb, const ImVec2& viewport_pos, const ImVec2& viewport_size)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImRect viewport_r(viewport_pos, viewport_pos + viewport_size);
ImVec2 scale = bb.GetSize() / viewport_size;
window->DrawList->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border));
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* thumb_window = g.Windows[i];
if (!thumb_window->WasActive || ((thumb_window->Flags & ImGuiWindowFlags_ChildWindow)))
continue;
if (thumb_window->SkipItems && (thumb_window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME-DOCK: Skip hidden docked windows. Identify those betters.
continue;
if (!viewport_r.Overlaps(thumb_window->WindowRectClipped))
continue;
ImRect thumb_r = thumb_window->Rect();
ImRect title_r = thumb_window->TitleBarRect();
ImRect thumb_r_scaled = ImRect(ImFloor(bb.Min + (thumb_r.Min - viewport_pos) * scale), ImFloor(bb.Min + (thumb_r.Max - viewport_pos) * scale));
ImRect title_r_scaled = ImRect(ImFloor(bb.Min + (title_r.Min - viewport_pos) * scale), ImFloor(bb.Min + (title_r.Max - viewport_pos) * scale));
thumb_r_scaled.ClipWithFull(bb);
title_r_scaled.ClipWithFull(bb);
const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight);
window->DrawList->AddRectFilled(thumb_r_scaled.Min, thumb_r_scaled.Max, ImGui::GetColorU32(ImGuiCol_WindowBg));
window->DrawList->AddRectFilled(title_r_scaled.Min, title_r_scaled.Max, ImGui::GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg));
window->DrawList->AddRect(thumb_r_scaled.Min, thumb_r_scaled.Max, ImGui::GetColorU32(ImGuiCol_Border));
}
draw_list->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border));
}
static void ScaleWindow(ImGuiWindow* window, float scale) static void ScaleWindow(ImGuiWindow* window, float scale)
{ {
ImVec2 origin = window->Viewport->Pos; ImVec2 origin = window->Viewport->Pos;
@ -14148,26 +14028,59 @@ void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale)
} }
} }
static void RenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 scale = bb.GetSize() / viewport->Size;
ImVec2 off = bb.Min - viewport->Pos * scale;
window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border, 0.40f));
for (int i = 0; i != g.Windows.Size; i++)
{
ImGuiWindow* thumb_window = g.Windows[i];
if (!thumb_window->WasActive || ((thumb_window->Flags & ImGuiWindowFlags_ChildWindow)))
continue;
if (thumb_window->SkipItems && (thumb_window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME-DOCK: Skip hidden docked windows. Identify those betters.
continue;
if (thumb_window->Viewport != viewport)
continue;
ImRect thumb_r = thumb_window->Rect();
ImRect title_r = thumb_window->TitleBarRect();
ImRect thumb_r_scaled = ImRect(ImFloor(off + thumb_r.Min * scale), ImFloor(off + thumb_r.Max * scale));
ImRect title_r_scaled = ImRect(ImFloor(off + title_r.Min * scale), ImFloor(off + ImVec2(title_r.Max.x, title_r.Min.y) * scale) + ImVec2(0,5)); // Exagerate title bar height
thumb_r_scaled.ClipWithFull(bb);
title_r_scaled.ClipWithFull(bb);
const bool window_is_focused = (g.NavWindow && thumb_window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight);
window->DrawList->AddRectFilled(thumb_r_scaled.Min, thumb_r_scaled.Max, ImGui::GetColorU32(ImGuiCol_WindowBg));
window->DrawList->AddRectFilled(title_r_scaled.Min, title_r_scaled.Max, ImGui::GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg));
window->DrawList->AddRect(thumb_r_scaled.Min, thumb_r_scaled.Max, ImGui::GetColorU32(ImGuiCol_Border));
window->DrawList->AddText(g.Font, g.FontSize * 1.0f, title_r_scaled.Min, ImGui::GetColorU32(ImGuiCol_Text), thumb_window->Name, ImGui::FindRenderedTextEnd(thumb_window->Name));
}
draw_list->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border));
}
void ImGui::ShowViewportThumbnails() void ImGui::ShowViewportThumbnails()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
float SCALE = 1.0f / 7.0f; // We don't display full monitor bounds (we could, but it often looks awkward), instead we display just enough to cover all of our viewports.
ImGui::NewLine(); // For labels float SCALE = 1.0f / 8.0f;
ImRect bb_full;
for (int n = 0; n < g.Viewports.Size; n++)
bb_full.Add(g.Viewports[n]->GetRect());
ImVec2 p = window->DC.CursorPos; ImVec2 p = window->DC.CursorPos;
ImVec2 off = p - bb_full.Min * SCALE;
for (int n = 0; n < g.Viewports.Size; n++) for (int n = 0; n < g.Viewports.Size; n++)
{ {
ImGuiViewportP* viewport = g.Viewports[n]; ImGuiViewportP* viewport = g.Viewports[n];
if (n > 0) ImRect viewport_draw_bb(off + (viewport->Pos) * SCALE, off + (viewport->Pos + viewport->Size) * SCALE);
ImGui::SameLine(); RenderViewportThumbnail(window->DrawList, viewport, viewport_draw_bb);
ImRect bb(p + (viewport->Pos) * SCALE, p + (viewport->Pos + viewport->Size) * SCALE);
RenderViewportThumbnail(window->DrawList, bb, viewport->Pos, viewport->Size);
char buf[64];
ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f", viewport->Pos.x);
ImGui::RenderText(bb.Min + ImVec2(1, -g.FontSize), buf, NULL, false);
ImGui::Dummy(bb.GetSize());
} }
ImGui::Dummy(bb_full.GetSize() * SCALE);
} }
void ImGui::ShowMetricsWindow(bool* p_open) void ImGui::ShowMetricsWindow(bool* p_open)
@ -14282,7 +14195,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
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); 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);
else else
ImGui::BulletText("NavRectRel[0]: <None>"); ImGui::BulletText("NavRectRel[0]: <None>");
ImGui::BulletText("Viewport: %d, ViewportId: 0x%08X, ViewportPlatformPos: (%.1f,%.1f)", window->Viewport ? window->Viewport->Idx : -1, window->ViewportId, window->ViewportPlatformPos.x, window->ViewportPlatformPos.y); ImGui::BulletText("Viewport: %d, ViewportId: 0x%08X, ViewportPlatformPos: (%.1f,%.1f)", window->Viewport ? window->Viewport->Idx : -1, window->ViewportId, window->ViewportPos.x, window->ViewportPos.y);
if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow");
if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows");
if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size))
@ -14310,8 +14223,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->Window ? viewport->Window->Name : "N/A")) if (ImGui::TreeNode((void*)(intptr_t)viewport->ID, "Viewport #%d, ID: 0x%08X, Window: \"%s\"", viewport->Idx, viewport->ID, viewport->Window ? viewport->Window->Name : "N/A"))
{ {
ImGuiWindowFlags flags = viewport->Flags; ImGuiWindowFlags flags = viewport->Flags;
ImGui::BulletText("Pos: (%.0f,%.0f), PlatformPos: (%.0f,%.0f)", viewport->Pos.x, viewport->Pos.y, viewport->PlatformPos.x, viewport->PlatformPos.y); ImGui::BulletText("Pos: (%.0f,%.0f)", viewport->Pos.x, viewport->Pos.y);
if (viewport->Idx > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Reset")) viewport->PlatformPos = ImVec2(0, 0); } if (viewport->Idx > 0) { ImGui::SameLine(); if (ImGui::SmallButton("Reset")) { viewport->Pos = ImVec2(200,200); if (viewport->Window) viewport->Window->Pos = viewport->Window->PosFloat = ImVec2(200,200); } }
ImGui::BulletText("Size: (%0.f,%.0f), DpiScale: %.0f%%", viewport->Size.x, viewport->Size.y, viewport->DpiScale * 100.0f); ImGui::BulletText("Size: (%0.f,%.0f), DpiScale: %.0f%%", viewport->Size.x, viewport->Size.y, viewport->DpiScale * 100.0f);
ImGui::BulletText("Flags: 0x%04X =%s%s%s%s%s", viewport->Flags, ImGui::BulletText("Flags: 0x%04X =%s%s%s%s%s", viewport->Flags,
(flags & ImGuiViewportFlags_CanHostOtherWindows) ? " CanHostOtherWindows" : "", (flags & ImGuiViewportFlags_NoDecoration) ? " NoDecoration" : "", (flags & ImGuiViewportFlags_CanHostOtherWindows) ? " CanHostOtherWindows" : "", (flags & ImGuiViewportFlags_NoDecoration) ? " NoDecoration" : "",
@ -14372,8 +14285,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId);
ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize);
ImVec2 mouse_platform_pos = ConvertViewportPosToPlatformPos(g.IO.MousePos, g.MouseRefViewport);
ImGui::Text("MousePlatformPos: (%.1f,%.1f)", mouse_platform_pos.x, mouse_platform_pos.y);
ImGui::Text("MousePosViewport: 0x%08X, Hovered: 0x%08X -> Ref 0x%08X", g.IO.MousePosViewport, g.IO.MouseHoveredViewport, g.MouseRefViewport->ID); ImGui::Text("MousePosViewport: 0x%08X, Hovered: 0x%08X -> Ref 0x%08X", g.IO.MousePosViewport, g.IO.MouseHoveredViewport, g.MouseRefViewport->ID);
ImGui::TreePop(); ImGui::TreePop();
} }

View File

@ -1152,7 +1152,7 @@ namespace ImGui
bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead.
static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); }
static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); }
static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } // FIXME-VIEWPORT: Select viewport based on mouse position static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } // FIXME-VIEWPORT-ABS: Select viewport based on mouse position
// OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017)
static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); }
static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead. static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead.
@ -1947,12 +1947,11 @@ struct ImGuiViewport
{ {
ImGuiID ID; ImGuiID ID;
ImGuiViewportFlags Flags; ImGuiViewportFlags Flags;
ImVec2 Pos; // Position of viewport in imgui virtual space (all viewports Pos.y == 0.0f, main viewport Pos.x == 0.0f) ImVec2 Pos; // Position of viewport both in imgui space and in OS desktop/native space
ImVec2 Size; // Size of viewport in pixel ImVec2 Size; // Size of viewport in pixel
float DpiScale; // 1.0f = 96 DPI = No extra scale float DpiScale; // 1.0f = 96 DPI = No extra scale
ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame(). ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame().
ImVec2 PlatformPos; // Position in OS desktop/native space
void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context) void* PlatformUserData; // void* to hold custom data structure for the platform (e.g. windowing info, render context)
void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. HWND, GlfwWindow*, SDL_Window*) void* PlatformHandle; // void* for FindViewportByPlatformHandle(). (e.g. HWND, GlfwWindow*, SDL_Window*)
bool PlatformRequestClose; // Platform window requested closure bool PlatformRequestClose; // Platform window requested closure
@ -1960,8 +1959,8 @@ struct ImGuiViewport
bool PlatformRequestResize; // Platform window requested resize (e.g. window was resize using OS windowing facility) bool PlatformRequestResize; // Platform window requested resize (e.g. window was resize using OS windowing facility)
void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.) void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. swap chain, frame-buffers etc.)
ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; RendererUserData = NULL; } ImGuiViewport() { ID = 0; Flags = 0; DpiScale = 0.0f; DrawData = NULL; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestMove = PlatformRequestResize = false; RendererUserData = NULL; }
~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); }
}; };
#if defined(__clang__) #if defined(__clang__)

View File

@ -2474,11 +2474,11 @@ static void ShowExampleAppConstrainedResize(bool* p_open)
// Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use. // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
static void ShowExampleAppFixedOverlay(bool* p_open) static void ShowExampleAppFixedOverlay(bool* p_open)
{ {
// FIXME-VIEWPORT: Select a default viewport // FIXME-VIEWPORT-ABS: Select a default viewport
const float DISTANCE = 10.0f; const float DISTANCE = 10.0f;
static int corner = 0; static int corner = 0;
ImGuiIO& io = ImGui::GetIO(); ImGuiViewport* viewport = ImGui::GetMainViewport();
ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE); ImVec2 window_pos = ImVec2((corner & 1) ? (viewport->Pos.x + viewport->Size.x - DISTANCE) : (viewport->Pos.x + DISTANCE), (corner & 2) ? (viewport->Pos.y + viewport->Size.y - DISTANCE) : (viewport->Pos.y + DISTANCE));
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background

View File

@ -405,13 +405,13 @@ struct ImGuiWindowSettings
{ {
char* Name; char* Name;
ImGuiID Id; ImGuiID Id;
ImVec2 Pos; ImVec2 Pos; // NB: Settings position are stored RELATIVE to the viewport! Whereas runtime ones are absolute positions.
ImVec2 Size; ImVec2 Size;
ImVec2 ViewportPlatformPos; ImVec2 ViewportPos;
ImGuiID ViewportId; ImGuiID ViewportId;
bool Collapsed; bool Collapsed;
ImGuiWindowSettings() { Name = NULL; Id = ViewportId = 0; Pos = Size = ImVec2(0,0); ViewportPlatformPos = ImVec2(FLT_MAX, FLT_MAX); Collapsed = false; } ImGuiWindowSettings() { Name = NULL; Id = ViewportId = 0; Pos = Size = ViewportPos = ImVec2(0, 0); Collapsed = false; }
}; };
struct ImGuiSettingsHandler struct ImGuiSettingsHandler
@ -518,6 +518,7 @@ struct ImGuiViewportP : public ImGuiViewport
int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef
int LastFrameOverlayDrawList; int LastFrameOverlayDrawList;
ImGuiID LastNameHash; ImGuiID LastNameHash;
ImVec2 LastPos;
float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent) float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent)
float LastAlpha; float LastAlpha;
ImGuiWindow* Window; ImGuiWindow* Window;
@ -530,7 +531,6 @@ struct ImGuiViewportP : public ImGuiViewport
~ImGuiViewportP() { if (OverlayDrawList) IM_DELETE(OverlayDrawList); } ~ImGuiViewportP() { if (OverlayDrawList) IM_DELETE(OverlayDrawList); }
ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
ImVec2 GetCenter() const{ return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); } ImVec2 GetCenter() const{ return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }
float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; }
}; };
struct ImGuiNavMoveResult struct ImGuiNavMoveResult
@ -940,9 +940,9 @@ struct IMGUI_API ImGuiWindow
ImGuiID ID; // == ImHash(Name) ImGuiID ID; // == ImHash(Name)
ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_ ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_
ImGuiViewportP* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here ImGuiViewportP* Viewport; // Always set in Begin(), only inactive windows may have a NULL value here
ImGuiID ViewportId; // Inactive windows preserve their last viewport id (since the viewport may disappear with the window inactivity) ImGuiID ViewportId; // We backup the viewport id (since the viewport may disappear or never be created if the window is inactive)
int ViewportPlatformAllowMonitorExtend; // Reset to -1 every frame (index is guaranteed to be valid between NewFrame..EndFrame), only used in the Appearing frame of a tooltip/popup to enforce clamping to a given monitor ImVec2 ViewportPos; // We backup the viewport position (since the viewport may disappear or never be created if the window is inactive)
ImVec2 ViewportPlatformPos; int ViewportAllowPlatformMonitorExtend; // Reset to -1 every frame (index is guaranteed to be valid between NewFrame..EndFrame), only used in the Appearing frame of a tooltip/popup to enforce clamping to a given monitor
ImVec2 PosFloat; ImVec2 PosFloat;
ImVec2 Pos; // Position rounded-up to nearest pixel ImVec2 Pos; // Position rounded-up to nearest pixel
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)