Skip to content

Commit

Permalink
Viewport, Platform: Refresh monitor list (win32, glfw) + avoid callin…
Browse files Browse the repository at this point in the history
…g GetWindowFocus before platform window creation to not require of backend to null-check things inconsistently. (#1542)
  • Loading branch information
ocornut committed Apr 26, 2018
1 parent da70c83 commit cd51f37
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 27 deletions.
3 changes: 3 additions & 0 deletions TODO.txt
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- 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: need to clarify how to use GetMousePos() from a user point of view.
- platform: glfw: no support for ImGuiBackendFlags_HasMouseHoveredViewport.
- 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
- platform: sdl: no refresh of monitor/display (SDL doesn't seem to have an event for it).

- 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: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71)
Expand Down
13 changes: 12 additions & 1 deletion examples/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ static GlfwClientApi g_ClientApi = GlfwClientApi_Unknown;
static double g_Time = 0.0f;
static bool g_MouseJustPressed[5] = { false, false, false, false, false };
static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 };
static bool g_WantUpdateMonitors = true;

// Forward Declarations
static void ImGui_ImplGlfw_InitPlatformInterface();
static void ImGui_ImplGlfw_ShutdownPlatformInterface();
static void ImGui_ImplGlfw_UpdateMonitors();

static const char* ImGui_ImplGlfw_GetClipboardText(void* user_data)
{
Expand Down Expand Up @@ -271,6 +273,8 @@ void ImGui_ImplGlfw_NewFrame()
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
if (g_WantUpdateMonitors)
ImGui_ImplGlfw_UpdateMonitors();

// Setup time step
double current_time = glfwGetTime();
Expand Down Expand Up @@ -562,7 +566,6 @@ static int ImGui_ImplGlfw_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
}
#endif // GLFW_HAS_VULKAN

// FIXME-PLATFORM: Update monitor list when changed (using glfwSetMonitorCallback?)
// FIXME-PLATFORM: GLFW doesn't export monitor work area (see https://github.com/glfw/glfw/pull/989)
static void ImGui_ImplGlfw_UpdateMonitors()
{
Expand All @@ -586,6 +589,12 @@ static void ImGui_ImplGlfw_UpdateMonitors()
#endif
platform_io.Monitors.push_back(monitor);
}
g_WantUpdateMonitors = false;
}

static void ImGui_ImplGlfw_MonitorCallback(GLFWmonitor*, int)
{
g_WantUpdateMonitors = true;
}

static void ImGui_ImplGlfw_InitPlatformInterface()
Expand Down Expand Up @@ -614,7 +623,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
#endif

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

// Register main window handle (which is owned by the main application, not by us)
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
Expand Down
5 changes: 2 additions & 3 deletions examples/imgui_impl_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,7 @@ static void ImGui_ImplSDL2_SetWindowFocus(ImGuiViewport* viewport)
static bool ImGui_ImplSDL2_GetWindowFocus(ImGuiViewport* viewport)
{
ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData;
bool focus = (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
return focus;
return (SDL_GetWindowFlags(data->Window) & SDL_WINDOW_INPUT_FOCUS) != 0;
}

static void ImGui_ImplSDL2_RenderWindow(ImGuiViewport* viewport, void*)
Expand Down Expand Up @@ -452,7 +451,7 @@ static int ImGui_ImplSDL2_CreateVkSurface(ImGuiViewport* viewport, ImU64 vk_inst
}
#endif // SDL_HAS_VULKAN

// FIXME-PLATFORM: Update monitor list when changed?
// FIXME-PLATFORM: SDL doesn't have an event to notify the application of display/monitor changes
static void ImGui_ImplSDL2_UpdateMonitors()
{
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
Expand Down
12 changes: 10 additions & 2 deletions examples/imgui_impl_win32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <tchar.h>

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

// Forward Declarations
static void ImGui_ImplWin32_InitPlatformInterface();
static void ImGui_ImplWin32_ShutdownPlatformInterface();
static void ImGui_ImplWin32_UpdateMonitors();

// Functions
bool ImGui_ImplWin32_Init(void* hwnd)
Expand Down Expand Up @@ -159,6 +162,8 @@ void ImGui_ImplWin32_NewFrame()
RECT rect;
::GetClientRect(g_hWnd, &rect);
io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top));
if (g_WantUpdateMonitors)
ImGui_ImplWin32_UpdateMonitors();

// Setup time step
INT64 current_time;
Expand Down Expand Up @@ -251,7 +256,7 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f;
return 0;
case WM_MOUSEMOVE:
io.MousePos.x = (signed short)(lParam);
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.
io.MousePos.y = (signed short)(lParam >> 16);
return 0;
case WM_KEYDOWN:
Expand All @@ -273,6 +278,9 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor())
return 1;
return 0;
case WM_DISPLAYCHANGE:
g_WantUpdateMonitors = true;
return 0;
}
return 0;
}
Expand Down Expand Up @@ -623,11 +631,11 @@ static BOOL CALLBACK ImGui_ImplWin32_UpdateMonitors_EnumFunc(HMONITOR monitor, H
return TRUE;
}

// FIXME-PLATFORM: Update monitor list when changed (WM_DISPLAYCHANGE?)
static void ImGui_ImplWin32_UpdateMonitors()
{
ImGui::GetPlatformIO().Monitors.resize(0);
::EnumDisplayMonitors(NULL, NULL, ImGui_ImplWin32_UpdateMonitors_EnumFunc, NULL);
g_WantUpdateMonitors = false;
}

static void ImGui_ImplWin32_InitPlatformInterface()
Expand Down
42 changes: 22 additions & 20 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3580,21 +3580,6 @@ void ImGui::UpdatePlatformWindows()
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
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.
// Skip the main viewport (index 0), which is always fully handled by the application!
for (int i = 1; i < g.Viewports.Size; i++)
Expand Down Expand Up @@ -3631,13 +3616,14 @@ void ImGui::UpdatePlatformWindows()
}

// Create window
bool is_new_window = (viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL && viewport->RendererUserData == NULL);
if (is_new_window && viewport->PlatformHandle == NULL && viewport->PlatformUserData == NULL)
g.PlatformIO.Platform_CreateWindow(viewport);
if (is_new_window && viewport->RendererUserData == NULL && g.PlatformIO.Renderer_CreateWindow != NULL)
bool is_new_window = (viewport->CreatedPlatformWindow == false);
if (is_new_window)
{
g.PlatformIO.Renderer_CreateWindow(viewport);
g.PlatformIO.Platform_CreateWindow(viewport);
if (g.PlatformIO.Renderer_CreateWindow != NULL)
g.PlatformIO.Renderer_CreateWindow(viewport);
viewport->RendererLastSize = viewport->Size;
viewport->CreatedPlatformWindow = true;
}

// Apply Position and Size (from ImGui to Platform/Renderer back-ends)
Expand Down Expand Up @@ -3682,6 +3668,22 @@ void ImGui::UpdatePlatformWindows()
// Clear request flags
viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false;
}

// 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 != NULL)
{
ImGuiViewportP* focused_viewport = NULL;
for (int i = 0; i < g.Viewports.Size && focused_viewport == NULL; i++)
if (g.Viewports[i]->PlatformUserData != NULL || g.Viewports[i]->PlatformHandle != NULL || g.Viewports[i]->CreatedPlatformWindow)
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;
}
}
}

// This is a default/basic function for performing the rendering/swap of multiple platform windows.
Expand Down
3 changes: 2 additions & 1 deletion imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ struct ImGuiViewportP : public ImGuiViewport
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;
ImVec2 LastPos;
bool CreatedPlatformWindow;
float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent)
float LastAlpha;
int PlatformMonitor;
Expand All @@ -524,7 +525,7 @@ struct ImGuiViewportP : public ImGuiViewport
ImDrawDataBuilder DrawDataBuilder;
ImVec2 RendererLastSize;

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() { 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); }
~ImGuiViewportP() { if (OverlayDrawList) IM_DELETE(OverlayDrawList); }
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); }
Expand Down

0 comments on commit cd51f37

Please sign in to comment.