Skip to content

Commit cd51f37

Browse files
committed
Viewport, Platform: Refresh monitor list (win32, glfw) + avoid calling GetWindowFocus before platform window creation to not require of backend to null-check things inconsistently. (#1542)
1 parent da70c83 commit cd51f37

File tree

6 files changed

+51
-27
lines changed

6 files changed

+51
-27
lines changed

TODO.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
262262
- 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.
263263
- viewport: vulkan renderer implementation.
264264
- viewport: need to clarify how to use GetMousePos() from a user point of view.
265+
- platform: glfw: no support for ImGuiBackendFlags_HasMouseHoveredViewport.
266+
- platform: sdl: no support for ImGuiBackendFlags_HasMouseHoveredViewport. maybe we could use SDL_GetMouseFocus() / SDL_WINDOW_MOUSE_FOCUS if imgui could fallback on its heuristic when NoInputs is set
267+
- platform: sdl: no refresh of monitor/display (SDL doesn't seem to have an event for it).
265268

266269
- 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.
267270
- inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)

examples/imgui_impl_glfw.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@ static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
5353
static double g_Time = 0.0f;
5454
static bool g_MouseJustPressed[5] = { false, false, false, false, false };
5555
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 };
56+
static bool g_WantUpdateMonitors = true;
5657

5758
// Forward Declarations
5859
static void ImGui_ImplGlfw_InitPlatformInterface();
5960
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
61+
static void ImGui_ImplGlfw_UpdateMonitors();
6062

6163
static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
6264
{
@@ -271,6 +273,8 @@ void ImGui_ImplGlfw_NewFrame()
271273
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
272274
io.DisplaySize = ImVec2((float)w, (float)h);
273275
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
276+
if (g_WantUpdateMonitors)
277+
ImGui_ImplGlfw_UpdateMonitors();
274278

275279
// Setup time step
276280
double current_time = glfwGetTime();
@@ -562,7 +566,6 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
562566
}
563567
#endif // GLFW_HAS_VULKAN
564568

565-
// FIXME-PLATFORM: Update monitor list when changed (using glfwSetMonitorCallback?)
566569
// FIXME-PLATFORM: GLFW doesn't export monitor work area (see https://github.com/glfw/glfw/pull/989)
567570
static void ImGui_ImplGlfw_UpdateMonitors()
568571
{
@@ -586,6 +589,12 @@ static void ImGui_ImplGlfw_UpdateMonitors()
586589
#endif
587590
platform_io.Monitors.push_back(monitor);
588591
}
592+
g_WantUpdateMonitors = false;
593+
}
594+
595+
static void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
596+
{
597+
g_WantUpdateMonitors = true;
589598
}
590599

591600
static void ImGui_ImplGlfw_InitPlatformInterface()
@@ -614,7 +623,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
614623
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
615624
#endif
616625

626+
// Note: monitor callback are broken GLFW 3.2 and earlier (see github.com/glfw/glfw/issues/784)
617627
ImGui_ImplGlfw_UpdateMonitors();
628+
glfwSetMonitorCallback(ImGui_ImplGlfw_MonitorCallback);
618629

619630
// Register main window handle (which is owned by the main application, not by us)
620631
ImGuiViewport* main_viewport = ImGui::GetMainViewport();

examples/imgui_impl_sdl2.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,7 @@ static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport)
418418
static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport)
419419
{
420420
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
421-
bool focus = (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
422-
return focus;
421+
return (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
423422
}
424423

425424
static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*)
@@ -452,7 +451,7 @@ static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
452451
}
453452
#endif // SDL_HAS_VULKAN
454453

455-
// FIXME-PLATFORM: Update monitor list when changed?
454+
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
456455
static void ImGui_ImplSDL2_UpdateMonitors()
457456
{
458457
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();

examples/imgui_impl_win32.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <tchar.h>
99

1010
// CHANGELOG
11+
// (minor and older changes stripped away, please see git history for details)
1112
// 2018-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
1213
// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag.
1314
// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling).
@@ -26,10 +27,12 @@ static HWND g_hWnd = 0;
2627
static INT64 g_Time = 0;
2728
static INT64 g_TicksPerSecond = 0;
2829
static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_;
30+
static bool g_WantUpdateMonitors = true;
2931

3032
// Forward Declarations
3133
static void ImGui_ImplWin32_InitPlatformInterface();
3234
static void ImGui_ImplWin32_ShutdownPlatformInterface();
35+
static void ImGui_ImplWin32_UpdateMonitors();
3336

3437
// Functions
3538
bool ImGui_ImplWin32_Init(void* hwnd)
@@ -159,6 +162,8 @@ void ImGui_ImplWin32_NewFrame()
159162
RECT rect;
160163
::GetClientRect(g_hWnd, &rect);
161164
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
165+
if (g_WantUpdateMonitors)
166+
ImGui_ImplWin32_UpdateMonitors();
162167

163168
// Setup time step
164169
INT64 current_time;
@@ -251,7 +256,7 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
251256
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
252257
return 0;
253258
case WM_MOUSEMOVE:
254-
io.MousePos.x = (signed short)(lParam);
259+
io.MousePos.x = (signed short)(lParam); // Note: this is used for single-viewport support, but in reality the code in ImGui_ImplWin32_UpdateMousePos() overwrite this.
255260
io.MousePos.y = (signed short)(lParam >> 16);
256261
return 0;
257262
case WM_KEYDOWN:
@@ -273,6 +278,9 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
273278
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
274279
return 1;
275280
return 0;
281+
case WM_DISPLAYCHANGE:
282+
g_WantUpdateMonitors = true;
283+
return 0;
276284
}
277285
return 0;
278286
}
@@ -623,11 +631,11 @@ static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, H
623631
return TRUE;
624632
}
625633

626-
// FIXME-PLATFORM: Update monitor list when changed (WM_DISPLAYCHANGE?)
627634
static void ImGui_ImplWin32_UpdateMonitors()
628635
{
629636
ImGui::GetPlatformIO().Monitors.resize(0);
630637
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL);
638+
g_WantUpdateMonitors = false;
631639
}
632640

633641
static void ImGui_ImplWin32_InitPlatformInterface()

imgui.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,21 +3580,6 @@ void ImGui::UpdatePlatformWindows()
35803580
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
35813581
return;
35823582

3583-
// Update our implicit z-order knowledge of platform windows, which is used when the back-end cannot provide io.MouseHoveredViewport.
3584-
if (g.PlatformIO.Platform_GetWindowFocus)
3585-
{
3586-
ImGuiViewportP* focused_viewport = NULL;
3587-
for (int i = 0; i < g.Viewports.Size && focused_viewport == NULL; i++)
3588-
if (g.PlatformIO.Platform_GetWindowFocus(g.Viewports[i]))
3589-
focused_viewport = g.Viewports[i];
3590-
if (focused_viewport && g.PlatformLastFocusedViewport != focused_viewport->ID)
3591-
{
3592-
if (focused_viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
3593-
focused_viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
3594-
g.PlatformLastFocusedViewport = focused_viewport->ID;
3595-
}
3596-
}
3597-
35983583
// Create/resize/destroy platform windows to match each active viewport.
35993584
// Skip the main viewport (index 0), which is always fully handled by the application!
36003585
for (int i = 1; i < g.Viewports.Size; i++)
@@ -3631,13 +3616,14 @@ void ImGui::UpdatePlatformWindows()
36313616
}
36323617

36333618
// Create window
3634-
bool is_new_window = (viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL && viewport->RendererUserData == NULL);
3635-
if (is_new_window && viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL)
3636-
g.PlatformIO.Platform_CreateWindow(viewport);
3637-
if (is_new_window && viewport->RendererUserData == NULL && g.PlatformIO.Renderer_CreateWindow != NULL)
3619+
bool is_new_window = (viewport->CreatedPlatformWindow == false);
3620+
if (is_new_window)
36383621
{
3639-
g.PlatformIO.Renderer_CreateWindow(viewport);
3622+
g.PlatformIO.Platform_CreateWindow(viewport);
3623+
if (g.PlatformIO.Renderer_CreateWindow != NULL)
3624+
g.PlatformIO.Renderer_CreateWindow(viewport);
36403625
viewport->RendererLastSize = viewport->Size;
3626+
viewport->CreatedPlatformWindow = true;
36413627
}
36423628

36433629
// Apply Position and Size (from ImGui to Platform/Renderer back-ends)
@@ -3682,6 +3668,22 @@ void ImGui::UpdatePlatformWindows()
36823668
// Clear request flags
36833669
viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false;
36843670
}
3671+
3672+
// Update our implicit z-order knowledge of platform windows, which is used when the back-end cannot provide io.MouseHoveredViewport.
3673+
if (g.PlatformIO.Platform_GetWindowFocus != NULL)
3674+
{
3675+
ImGuiViewportP* focused_viewport = NULL;
3676+
for (int i = 0; i < g.Viewports.Size && focused_viewport == NULL; i++)
3677+
if (g.Viewports[i]->PlatformUserData != NULL || g.Viewports[i]->PlatformHandle != NULL || g.Viewports[i]->CreatedPlatformWindow)
3678+
if (g.PlatformIO.Platform_GetWindowFocus(g.Viewports[i]))
3679+
focused_viewport = g.Viewports[i];
3680+
if (focused_viewport && g.PlatformLastFocusedViewport != focused_viewport->ID)
3681+
{
3682+
if (focused_viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
3683+
focused_viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
3684+
g.PlatformLastFocusedViewport = focused_viewport->ID;
3685+
}
3686+
}
36853687
}
36863688

36873689
// This is a default/basic function for performing the rendering/swap of multiple platform windows.

imgui_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ struct ImGuiViewportP : public ImGuiViewport
515515
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
516516
ImGuiID LastNameHash;
517517
ImVec2 LastPos;
518+
bool CreatedPlatformWindow;
518519
float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent)
519520
float LastAlpha;
520521
int PlatformMonitor;
@@ -524,7 +525,7 @@ struct ImGuiViewportP : public ImGuiViewport
524525
ImDrawDataBuilder DrawDataBuilder;
525526
ImVec2 RendererLastSize;
526527

527-
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); }
528+
ImGuiViewportP() { Idx = 1; LastFrameActive = LastFrameOverlayDrawList = LastFrontMostStampCount = -1; LastNameHash = 0; CreatedPlatformWindow = false; Alpha = LastAlpha = 1.0f; PlatformMonitor = INT_MIN; Window = NULL; OverlayDrawList = NULL; RendererLastSize = ImVec2(-1.0f,-1.0f); }
528529
~ImGuiViewportP() { if (OverlayDrawList) IM_DELETE(OverlayDrawList); }
529530
ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
530531
ImVec2 GetCenter() const{ return ImVec2(Pos.x + Size.x * 0.5f, Pos.y + Size.y * 0.5f); }

0 commit comments

Comments
 (0)