Skip to content

Multi-Viewport#

  • https://greich.com/2019/03/02/imgui-multiple-viewports/

  • https://github.com/ocornut/imgui/issues/1542#issuecomment-595852032

  • Viewports Added ImGui::GetMainViewport() as a way to get the bounds and work area of the host display. (#3789, #1542)

  • In master branch or without multi-viewports feature enabled:

    • GetMainViewport()->Pos is always == (0,0)
    • GetMainViewport()->Size is always == io.DisplaySize
  • In docking branch and with the multi-viewports feature enabled:
    • GetMainViewport() will return information from your host Platform Window.
    • In the future, we will support a “no main viewport” mode and this may return bounds of your main monitor.
  • For forward compatibility with multi-viewports/multi-monitors:
    • Code using (0,0) as a way to signify “upper-left of the host window” should use GetMainViewport()->Pos.
    • Code using io.DisplaySize as a way to signify “size of the host window” should use GetMainViewport()->Size.
  • We are also exposing a work area in ImGuiViewport (WorkPos, WorkSize vs Pos, Size for full area):
    • For a Platform Window, the work area is generally the full area minus space used by menu-bars.
    • For a Platform Monitor, the work area is generally the full area minus space used by task-bars.
  • All of this has been the case in ‘docking’ branch for a long time. What we’ve done is merely merging
    a small chunk of the multi-viewport logic into ‘master’ to standardize some concepts ahead of time.

Upgrade notes#

Steps to use multi-viewports in your application, when using a custom back-end:

  • Important: THIS IS NOT EASY TO DO and comes with many subtleties not described here! It’s also an experimental feature, so some of the requirements may evolve. Consider using default back-ends if you can. Either way, carefully follow and refer to examples/ back-ends for details. [x] Application: Enable feature with ‘io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable’. [x] Back-end: Hook ImGuiPlatformIO’s Platform_* and Renderer_* callbacks (see below). [x] Set ‘io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports’ and ‘io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports’. [x] Update ImGuiPlatformIO’s Monitors list every frame. [x] Update MousePos every frame, in absolute coordinates. [x] Application: In your main loop, call ImGui::UpdatePlatformWindows(), ImGui::RenderPlatformWindowsDefault() after EndFrame() or Render(). [x] You may skip calling RenderPlatformWindowsDefault() if its API is not convenient for your needs. Read comments below. [x] Application: Fix absolute coordinates used in ImGui::SetWindowPos() or ImGui::SetNextWindowPos() calls.

About ImGui::RenderPlatformWindowsDefault(): [x] This function is a mostly a helper for the common-most cases, and to facilitate using default back-ends. [x] You can check its simple source code to understand what it does. - It basically iterates secondary viewports and call 4 functions that are setup in ImGuiPlatformIO, if available: - Platform_RenderWindow(), Renderer_RenderWindow(), Platform_SwapBuffers(), Renderer_SwapBuffers() - Those functions pointers exists only for the benefit of RenderPlatformWindowsDefault(). - If you have very specific rendering needs (e.g. flipping multiple swap-chain simultaneously, unusual sync/threading issues, etc.), you may be tempted to ignore RenderPlatformWindowsDefault() and write customized code to perform your renderingg. - You may decide to setup the platform_io’s *RenderWindow and *SwapBuffers pointers and call your functions through those pointers, or you may decide to never setup those pointers and call your code directly. They are a convenience, not an obligatory interface.

  • IMPORTANT: When multi-viewports are enabled (with io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable), all coordinates/positions will be in your natural OS coordinates space. It means that:
  • Reference to hard-coded positions such as in SetNextWindowPos(ImVec2(0,0)) are probably not what you want anymore. Use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos).
  • Likewise io.MousePos and GetMousePos() will use OS coordinates. If you query mouse positions to interact with non-imgui coordinates you will need to offset them. e.g. subtract GetWindowViewport()->Pos.
  • Render function: the ImDrawData structure now contains ‘DisplayPos’ and ‘DisplaySize’ fields. To support multi-viewport, you need to use those values when creating your orthographic projection matrix. Use ‘draw_data->DisplaySize’ instead of ‘io.DisplaySize’, and ‘draw_data->DisplayPos’ instead of (0,0) as the upper-left point. You need to subtract ‘draw_data->DisplayPos’ from your scissor rectangles to convert them from global coordinates to frame-buffer coordinates.
  • IO: Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
  • IO: Removed io.DisplayVisibleMin, io.DisplayVisibleMax settings (they were marked obsoleted, used to clip within the (0,0)..(DisplaySize) range).

Last update: April 29, 2021