From 72899318e6cca13b88b88bcfa8ef78c4ac9a8354 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Apr 2018 17:06:23 +0200 Subject: [PATCH] Viewport, Platform, Examples: Added support for transparent window via PlatformIO Platform_SetWindowAlpha (#1542) + fixes for GLFW 3.3 --- examples/imgui_impl_glfw.cpp | 16 ++++++++++++++-- examples/imgui_impl_win32.cpp | 19 +++++++++++++++++++ imgui.cpp | 5 +++++ imgui_internal.h | 4 +++- 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 11025fe6a..6d65eef6f 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -39,6 +39,7 @@ #else #define GLFW_HAS_GLFW_HOVERED 0 #endif +#define GLFW_HAS_WINDOW_ALPHA (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3300) // 3.3+ #define GLFW_HAS_VULKAN (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ // Data @@ -235,8 +236,8 @@ static void ImGui_ImplGlfw_UpdateMouse() } #if GLFW_HAS_GLFW_HOVERED - io.ConfigFlags |= ImGuiConfigFlags_PlatformHasMouseHoveredViewport; - if (glfwGetWindowAttrib(data->Window, GLFW_HOVERED) && !(viewport->Flags & ImGuiViewportFlags_NoInputs)) + io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; + if (glfwGetWindowAttrib(window, GLFW_HOVERED) && !(viewport->Flags & ImGuiViewportFlags_NoInputs)) io.MouseHoveredViewport = viewport->ID; #endif } @@ -469,6 +470,14 @@ static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* t glfwSetWindowTitle(data->Window, title); } +#if GLFW_HAS_WINDOW_ALPHA +static void ImGui_ImplGlfw_SetWindowAlpha(ImGuiViewport* viewport, float alpha) +{ + ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData; + glfwSetWindowOpacity(data->Window, alpha); +} +#endif + static void ImGui_ImplGlfw_RenderWindow(ImGuiViewport* viewport, void*) { ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData; @@ -522,6 +531,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface() platform_io.Platform_SetWindowTitle = ImGui_ImplGlfw_SetWindowTitle; platform_io.Platform_RenderWindow = ImGui_ImplGlfw_RenderWindow; platform_io.Platform_SwapBuffers = ImGui_ImplGlfw_SwapBuffers; +#if GLFW_HAS_WINDOW_ALPHA + platform_io.Platform_SetWindowAlpha = ImGui_ImplGlfw_SetWindowAlpha; +#endif #if GLFW_HAS_VULKAN platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index e34583b18..01493b9d0 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -472,6 +472,24 @@ static void ImGui_ImplWin32_SetWindowTitle(ImGuiViewport* viewport, const char* ::SetWindowTextA(data->Hwnd, title); } +static void ImGui_ImplWin32_SetWindowAlpha(ImGuiViewport* viewport, float alpha) +{ + ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData; + IM_ASSERT(data->Hwnd != 0); + IM_ASSERT(alpha >= 0.0f && alpha <= 1.0f); + if (alpha < 1.0f) + { + DWORD style = ::GetWindowLongW(data->Hwnd, GWL_EXSTYLE) | WS_EX_LAYERED; + ::SetWindowLongW(data->Hwnd, GWL_EXSTYLE, style); + ::SetLayeredWindowAttributes(data->Hwnd, 0, (BYTE)(255 * alpha), LWA_ALPHA); + } + else + { + DWORD style = ::GetWindowLongW(data->Hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED; + ::SetWindowLongW(data->Hwnd, GWL_EXSTYLE, style); + } +} + static float ImGui_ImplWin32_GetWindowDpiScale(ImGuiViewport* viewport) { ImGuiViewportDataWin32* data = (ImGuiViewportDataWin32*)viewport->PlatformUserData; @@ -543,6 +561,7 @@ static void ImGui_ImplWin32_InitPlatformInterface() platform_io.Platform_SetWindowSize = ImGui_ImplWin32_SetWindowSize; platform_io.Platform_GetWindowSize = ImGui_ImplWin32_GetWindowSize; platform_io.Platform_SetWindowTitle = ImGui_ImplWin32_SetWindowTitle; + platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // Register main window handle diff --git a/imgui.cpp b/imgui.cpp index 0f38c9f00..26df72cec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3578,6 +3578,11 @@ void ImGui::UpdatePlatformWindows() ImGui::MemFree(title_displayed); } + // Update alpha + if (viewport->LastAlpha != viewport->Alpha && g.PlatformIO.Platform_SetWindowAlpha) + g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha); + viewport->LastAlpha = viewport->Alpha; + // Show window. On startup ensure platform window don't get focus. if (is_new_window) { diff --git a/imgui_internal.h b/imgui_internal.h index 62aa8337b..06b6bbd40 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -517,13 +517,15 @@ struct ImGuiViewportP : public ImGuiViewport int LastFrameActive; // Last frame number this viewport was activated by a window int LastFrameAsRefViewport; // Last frame number this viewport was io.MouseViewportRef ImGuiID LastNameHash; + float Alpha; // Window opacity (when dragging dockable windows/viewports we make them transparent) + float LastAlpha; ImGuiWindow* Window; ImDrawList* OverlayDrawList; // For convenience, a draw list we can render to that's always rendered last (we use it to draw software mouse cursor when io.MouseDrawCursor is set) ImDrawData DrawDataP; ImDrawDataBuilder DrawDataBuilder; ImVec2 RendererLastSize; - ImGuiViewportP(ImDrawListSharedData* draw_list_shared_data) { Idx = 1; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; OverlayDrawList = IM_NEW(ImDrawList)(draw_list_shared_data); OverlayDrawList->_OwnerName = "##Overlay"; RendererLastSize = ImVec2(-1.0f,-1.0f); } + ImGuiViewportP(ImDrawListSharedData* draw_list_shared_data) { Idx = 1; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Alpha = LastAlpha = 1.0f; Window = NULL; OverlayDrawList = IM_NEW(ImDrawList)(draw_list_shared_data); OverlayDrawList->_OwnerName = "##Overlay"; RendererLastSize = ImVec2(-1.0f,-1.0f); } ~ImGuiViewportP() { IM_DELETE(OverlayDrawList); } ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; }