-
-
Notifications
You must be signed in to change notification settings - Fork 11.5k
Description
Version/Branch of Dear ImGui:
imgui branch: docking, version: 1.92.2b (19222)
Back-ends:
imgui_impl_opengl3 + imgui_impl_sdl2 (2.30.9, 2.30.9)
Compiler, OS:
Linux - GNU 13.3.0
Full config/build information:
Dear ImGui 1.92.2b (19222)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 4, sizeof(ImDrawVert): 20
define: __cplusplus=202002
define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS
define: __linux__
define: __GNUC__=13
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_sdl2 (2.30.9, 2.30.9)
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000481
NavEnableKeyboard
DockingEnable
ViewportsEnable
io.ConfigDpiScaleFonts
io.ConfigDpiScaleViewports
io.ConfigViewportsNoAutoMerge
io.ConfigViewportsNoDefaultParent
io.ConfigDockingWithShift
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001416
HasMouseCursors
HasSetMousePos
PlatformHasViewports
RendererHasTextures
RendererHasViewports
--------------------------------
io.Fonts: 5 fonts, Flags: 0x00000004, TexSize: 512,256
io.Fonts->FontLoaderName: stb_truetype
io.DisplaySize: 1920.00,1080.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 1.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,2.00Details:
When using io.ConfigViewportsNoDecoration = true; everything works correctly, but when io.ConfigViewportsNoDecoration = false; (using native OS window decorations) there is an issue.
The issue is that ImGui seems to record the window position from where the ImGui canvas starts, but when it set the position, it will set the SDL top/left.
This means, when I simply open/close/open a window, it "drifts" down (and/or right) by the size of the title (and/or border).
Same happens when I use ImGui persistence and restart my application.
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
To replicate, simple use:
io.ConfigViewportsNoDecoration = false;
And open/close a window on Linux/SDL2.
--
For now I'm fixing this by detecting OS decoration sizes, and adjusting the values in these platform IO hooks:
static void CustomRenderWindow(ImGuiViewport* vp, void* render_arg)
{
// Since ImGui creates windows as hidden, SDL cannot detect the OS border size until the window is rendered,
// So we (try) to read here since the window is likely to be rendered at this point.
if (OSBorderSize.top == 0 && OSBorderSize.right == 0 && OSBorderSize.bottom == 0 && OSBorderSize.left == 0)
{
SDL_Window* Window = SDL_GetWindowFromID(static_cast<Uint32>(reinterpret_cast<intptr_t>(vp->PlatformHandle)));
Uint32 window_flags = SDL_GetWindowFlags(Window);
bool window_borderless = window_flags & SDL_WINDOW_BORDERLESS;
if (!window_borderless)
{
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
SDL_GetWindowBordersSize(Window, &top, &left, &bottom, &right);
if (top > 0 || right > 0 || bottom > 0 || left > 0)
{
OSBorderSize = RectPadding(static_cast<float>(top), static_cast<float>(right), static_cast<float>(bottom), static_cast<float>(left));
Log(LL_VERBOSE, "Detected OSBorderSize: {:.0f}, {:.0f}, {:.0f}, {:.0f} (from window {})",
OSBorderSize.top,
OSBorderSize.right,
OSBorderSize.bottom,
OSBorderSize.left,
SDL_GetWindowTitle(Window));
}
}
}
origPlatformIO.Platform_RenderWindow(vp, render_arg);
}
static void CustomSetWindowPos(ImGuiViewport* vp, ImVec2 pos)
{
SDL_Window* Window = SDL_GetWindowFromID(static_cast<Uint32>(reinterpret_cast<intptr_t>(vp->PlatformHandle)));
Uint32 window_flags = SDL_GetWindowFlags(Window);
bool window_borderless = window_flags & SDL_WINDOW_BORDERLESS;
bool window_is_visible = window_flags & SDL_WINDOW_SHOWN;
// When ImGui first creates the window, it is still hidden when this position is set.
// This is when we can fix up the "drift" from using OS decorations instead of ImGui decorations.
if (!window_borderless && !window_is_visible)
{
pos.x -= OSBorderSize.left;
pos.y -= OSBorderSize.top;
}
origPlatformIO.Platform_SetWindowPos(vp, pos);
}This works (without desync) for the following cases:
- Programmatic SetPos (keeping in mind that the window contents is now at the given position, not the SDL window)
- Opening closing windows
- Moving windows (with either the SDL title, or via ImGui content)
- Restarting the application (Imgui persistence config works)
Resizing is not affected (as expected).
The biggest issue was detecting the OS window decorations since SDL will not return those values unless the window:
- Has already been rendered
- Actually has decorations/borders
For now this works 100% for me, and I hope may help others. However @ocornut or SDL(2) experts may need to look this over, and possibly fix this (correctly) in the SDL2 backend (keeping in mind the Catch-22 of determining the decoration sizes)