mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-11 11:29:02 +08:00
Viewport, Platform: Using Platform_GetWindowFocus to provide a much stronger heuristic of platform z-order, in replacement for when the back-end cannot provide io.MouseHoveredViewport. The pressure for it to work well increased with the use of viewports by popups/menus. (#1542)
This commit is contained in:
parent
d9cd494eaf
commit
f1ae07e532
1
TODO.txt
1
TODO.txt
@ -262,7 +262,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
|||||||
- viewport: platform: introduce getfocus/setfocus api, so e.g. focus flags can be honored, imgui-side ctrl-tab can focus os window, OS alt-tab can focus imgui window etc.
|
- viewport: platform: introduce getfocus/setfocus api, so e.g. focus flags can be honored, imgui-side ctrl-tab can focus os window, OS alt-tab can focus imgui window etc.
|
||||||
- viewport: store per-viewport/monitor DPI in .ini file so an application reload or main window changing DPI on reload can be properly patched for.
|
- viewport: store per-viewport/monitor DPI in .ini file so an application reload or main window changing DPI on reload can be properly patched for.
|
||||||
- viewport: vulkan renderer implementation.
|
- viewport: vulkan renderer implementation.
|
||||||
- viewport: fallback calculation of hovered window is very currently wrong without ImGuiBackendFlags_HasMouseHoveredViewport. typically affect half-overlapping viewported menus.
|
|
||||||
- viewport: need to clarify how to use GetMousePos() from a user point of view.
|
- viewport: need to clarify how to use GetMousePos() from a user point of view.
|
||||||
|
|
||||||
- inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors.
|
- inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors.
|
||||||
|
29
imgui.cpp
29
imgui.cpp
@ -3392,8 +3392,8 @@ static void ImGui::UpdateMovingWindow()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
// A) It 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.
|
// B) It requires Platform_GetWindowFocus to be implemented by back-end.
|
||||||
static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos)
|
static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -3402,7 +3402,7 @@ static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 m
|
|||||||
{
|
{
|
||||||
ImGuiViewportP* viewport = g.Viewports[n];
|
ImGuiViewportP* viewport = g.Viewports[n];
|
||||||
if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && viewport->GetRect().Contains(mouse_platform_pos))
|
if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && viewport->GetRect().Contains(mouse_platform_pos))
|
||||||
if (best_candidate == NULL || best_candidate->LastFrameAsRefViewport < viewport->LastFrameAsRefViewport)
|
if (best_candidate == NULL || best_candidate->LastFrontMostStampCount < viewport->LastFrontMostStampCount)
|
||||||
best_candidate = viewport;
|
best_candidate = viewport;
|
||||||
}
|
}
|
||||||
return best_candidate;
|
return best_candidate;
|
||||||
@ -3532,10 +3532,8 @@ static void ImGui::UpdateViewports()
|
|||||||
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;
|
||||||
@ -3584,6 +3582,21 @@ void ImGui::UpdatePlatformWindows()
|
|||||||
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
|
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Update our implicit z-order knowledge of platform windows, which is used when the back-end cannot provide io.MouseHoveredViewport.
|
||||||
|
if (g.PlatformIO.Platform_GetWindowFocus)
|
||||||
|
{
|
||||||
|
ImGuiViewportP* focused_viewport = NULL;
|
||||||
|
for (int i = 0; i < g.Viewports.Size && focused_viewport == NULL; i++)
|
||||||
|
if (g.PlatformIO.Platform_GetWindowFocus(g.Viewports[i]))
|
||||||
|
focused_viewport = g.Viewports[i];
|
||||||
|
if (focused_viewport && g.PlatformLastFocusedViewport != focused_viewport->ID)
|
||||||
|
{
|
||||||
|
if (focused_viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
|
||||||
|
focused_viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
|
||||||
|
g.PlatformLastFocusedViewport = focused_viewport->ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create/resize/destroy platform windows to match each active viewport.
|
// Create/resize/destroy platform windows to match each active viewport.
|
||||||
// Skip the main viewport (index 0), which is always fully handled by the application!
|
// Skip the main viewport (index 0), which is always fully handled by the application!
|
||||||
for (int i = 1; i < g.Viewports.Size; i++)
|
for (int i = 1; i < g.Viewports.Size; i++)
|
||||||
@ -3656,7 +3669,7 @@ void ImGui::UpdatePlatformWindows()
|
|||||||
g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
|
g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
|
||||||
viewport->LastAlpha = viewport->Alpha;
|
viewport->LastAlpha = viewport->Alpha;
|
||||||
|
|
||||||
// Show window. On startup ensure platform window don't get focus.
|
// Show window. On startup ensure platform window don't get focus
|
||||||
if (is_new_window)
|
if (is_new_window)
|
||||||
{
|
{
|
||||||
if (g.FrameCount < 2)
|
if (g.FrameCount < 2)
|
||||||
@ -3664,6 +3677,10 @@ void ImGui::UpdatePlatformWindows()
|
|||||||
g.PlatformIO.Platform_ShowWindow(viewport);
|
g.PlatformIO.Platform_ShowWindow(viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Even without focus, we assume the window becomes front-most. This is used by our platform z-order heuristic when io.MouseHoveredViewport is not available.
|
||||||
|
if (is_new_window && viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
|
||||||
|
viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
|
||||||
|
|
||||||
// Clear request flags
|
// Clear request flags
|
||||||
viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false;
|
viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false;
|
||||||
}
|
}
|
||||||
|
2
imgui.h
2
imgui.h
@ -1073,7 +1073,7 @@ struct ImGuiIO
|
|||||||
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
|
float MouseWheel; // Mouse wheel Vertical: 1 unit scrolls about 5 lines text.
|
||||||
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends.
|
float MouseWheelH; // Mouse wheel Horizontal. Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends.
|
||||||
ImGuiID MousePosViewport; // (Optional) When using multiple viewports: viewport from which io.MousePos is based from (when dragging this is generally the captured/focused viewport, even though we can drag outside of it and then it's not hovered anymore). (0 == default viewport)
|
ImGuiID MousePosViewport; // (Optional) When using multiple viewports: viewport from which io.MousePos is based from (when dragging this is generally the captured/focused viewport, even though we can drag outside of it and then it's not hovered anymore). (0 == default viewport)
|
||||||
ImGuiID MouseHoveredViewport; // (Optional) When using multiple viewports: viewport the OS mouse cursor is hovering. (0 == default viewport) _IGNORING_ viewports with the ImGuiBackendFlags_HasMouseHoveredViewport flag, and _REGARDLESS_ of whether another viewport is focused. Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this information.
|
ImGuiID MouseHoveredViewport; // (Optional) When using multiple viewports: viewport the OS mouse cursor is hovering _IGNORING_ viewports with the ImGuiViewportFlags_NoInputs flag, and _REGARDLESS_ of whether another viewport is focused. Set io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport if you can provide this info. If you don't imgui will use a decent heuristic instead.
|
||||||
bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
|
bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor).
|
||||||
bool KeyCtrl; // Keyboard modifier pressed: Control
|
bool KeyCtrl; // Keyboard modifier pressed: Control
|
||||||
bool KeyShift; // Keyboard modifier pressed: Shift
|
bool KeyShift; // Keyboard modifier pressed: Shift
|
||||||
|
@ -511,8 +511,8 @@ struct ImGuiViewportP : public ImGuiViewport
|
|||||||
{
|
{
|
||||||
int Idx;
|
int Idx;
|
||||||
int LastFrameActive; // Last frame number this viewport was activated by a window
|
int LastFrameActive; // Last frame number this viewport was activated by a window
|
||||||
int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef
|
|
||||||
int LastFrameOverlayDrawList;
|
int LastFrameOverlayDrawList;
|
||||||
|
int LastFrontMostStampCount; // Last stamp number from when a window hosted by this viewport was made front-most (by comparing this value between two viewport we have an implicit viewport z-order
|
||||||
ImGuiID LastNameHash;
|
ImGuiID LastNameHash;
|
||||||
ImVec2 LastPos;
|
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)
|
||||||
@ -524,7 +524,7 @@ struct ImGuiViewportP : public ImGuiViewport
|
|||||||
ImDrawDataBuilder DrawDataBuilder;
|
ImDrawDataBuilder DrawDataBuilder;
|
||||||
ImVec2 RendererLastSize;
|
ImVec2 RendererLastSize;
|
||||||
|
|
||||||
ImGuiViewportP() { Idx = 1; LastFrameActive = LastFrameAsRefViewport = LastFrameOverlayDrawList = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; PlatformMonitor = INT_MIN; Window = NULL; OverlayDrawList = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); }
|
ImGuiViewportP() { Idx = 1; LastFrameActive = LastFrameOverlayDrawList = LastFrontMostStampCount = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; PlatformMonitor = INT_MIN; Window = NULL; OverlayDrawList = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); }
|
||||||
~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); }
|
||||||
@ -610,6 +610,7 @@ struct ImGuiContext
|
|||||||
ImVector<ImGuiWindow*> CurrentWindowStack;
|
ImVector<ImGuiWindow*> CurrentWindowStack;
|
||||||
ImGuiStorage WindowsById;
|
ImGuiStorage WindowsById;
|
||||||
int WindowsActiveCount;
|
int WindowsActiveCount;
|
||||||
|
int WindowsFrontMostStampCount; // Every time the front-most window changes, we stamp its viewport with an incrementing counter
|
||||||
ImGuiWindow* CurrentWindow; // Being drawn into
|
ImGuiWindow* CurrentWindow; // Being drawn into
|
||||||
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
|
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
|
||||||
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
|
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
|
||||||
@ -644,6 +645,7 @@ struct ImGuiContext
|
|||||||
ImGuiViewportP* MouseRefPrevViewport;
|
ImGuiViewportP* MouseRefPrevViewport;
|
||||||
ImGuiViewportP* MouseHoveredLastViewport; // Last viewport that was hovered by mouse (even if we are not hovering any viewport any more)
|
ImGuiViewportP* MouseHoveredLastViewport; // Last viewport that was hovered by mouse (even if we are not hovering any viewport any more)
|
||||||
ImGuiID MouseClickedPosViewportId[5]; // For rarely used fields we only compare to, store viewport ID only so we don't have to clean dangling pointers
|
ImGuiID MouseClickedPosViewportId[5]; // For rarely used fields we only compare to, store viewport ID only so we don't have to clean dangling pointers
|
||||||
|
ImGuiID PlatformLastFocusedViewport; // Record of last focused platform window/viewport, when this changes we stamp the viewport as front-most
|
||||||
|
|
||||||
// Navigation data (for gamepad/keyboard)
|
// Navigation data (for gamepad/keyboard)
|
||||||
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow'
|
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow'
|
||||||
@ -751,6 +753,7 @@ struct ImGuiContext
|
|||||||
FrameCount = 0;
|
FrameCount = 0;
|
||||||
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
|
FrameCountEnded = FrameCountPlatformEnded = FrameCountRendered = -1;
|
||||||
WindowsActiveCount = 0;
|
WindowsActiveCount = 0;
|
||||||
|
WindowsFrontMostStampCount = 0;
|
||||||
CurrentWindow = NULL;
|
CurrentWindow = NULL;
|
||||||
HoveredWindow = NULL;
|
HoveredWindow = NULL;
|
||||||
HoveredRootWindow = NULL;
|
HoveredRootWindow = NULL;
|
||||||
@ -776,6 +779,7 @@ struct ImGuiContext
|
|||||||
MouseRefViewport = NULL;
|
MouseRefViewport = NULL;
|
||||||
MouseRefPrevViewport = MouseHoveredLastViewport = NULL;
|
MouseRefPrevViewport = MouseHoveredLastViewport = NULL;
|
||||||
memset(MouseClickedPosViewportId, 0, sizeof(MouseClickedPosViewportId));
|
memset(MouseClickedPosViewportId, 0, sizeof(MouseClickedPosViewportId));
|
||||||
|
PlatformLastFocusedViewport = 0;
|
||||||
|
|
||||||
NavWindow = NULL;
|
NavWindow = NULL;
|
||||||
NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0;
|
NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user