From 5bb04213ec65927c61c70e0df6201ea5e776662a Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Mon, 1 Jan 2024 15:11:03 +0100 Subject: [PATCH 1/3] Wip / borderless resizable --- .../backend_impls/abstract_runner.cpp | 4 + .../internal/borderless_resizable.cpp | 88 +++++++++++++++++++ .../internal/borderless_resizable.h | 10 +++ .../hello_imgui_demodocking.main.cpp | 1 + 4 files changed, 103 insertions(+) create mode 100644 src/hello_imgui/internal/borderless_resizable.cpp create mode 100644 src/hello_imgui/internal/borderless_resizable.h diff --git a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp index 2eb31eac..3108a5fb 100644 --- a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp +++ b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp @@ -6,6 +6,7 @@ #include "hello_imgui/internal/clock_seconds.h" #include "hello_imgui/internal/platform/ini_folder_locations.h" #include "imgui.h" +#include "hello_imgui/internal/borderless_resizable.h" #include "hello_imgui/internal/imgui_global_context.h" // must be included before imgui_internal.h #include "imgui_internal.h" @@ -504,6 +505,9 @@ void AbstractRunner::RenderGui() if (params.imGuiWindowParams.showMenuBar) Menu_StatusBar::ShowMenu(params); + if (params.appWindowParams.borderless) // Need to add params.appWindowParams.borderlessResizable + HandleBorderlessResizable(mWindow, mBackendWindowHelper.get()); + if (params.callbacks.ShowGui) { bool wantAutoSize = WantAutoSize(); diff --git a/src/hello_imgui/internal/borderless_resizable.cpp b/src/hello_imgui/internal/borderless_resizable.cpp new file mode 100644 index 00000000..07be6035 --- /dev/null +++ b/src/hello_imgui/internal/borderless_resizable.cpp @@ -0,0 +1,88 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "hello_imgui/internal/borderless_resizable.h" +#include "hello_imgui/hello_imgui.h" +#include "imgui_internal.h" + + +namespace HelloImGui +{ + void HandleBorderlessResizable( + BackendApi::WindowPointer window, + BackendApi::IBackendWindowHelper * backendWindowHelper) + { + ImVec2 winSize = ImGui::GetWindowSize(); + auto highlightColor = ImGui::GetColorU32(ImGuiCol_FrameBgHovered, 0.8f); + + // Drag zone at the top of the window + { + ImVec2 topLeftCorner = ImGui::GetMainViewport()->Pos; + ImVec2 bottomRightCorner = topLeftCorner + ImVec2(winSize.x, HelloImGui::EmSize(1.5f)); + ImRect dragRect = ImRect(topLeftCorner, bottomRightCorner); + + ImVec2 mousePos = ImGui::GetIO().MousePos; + bool isMouseInDragZone = dragRect.Contains(mousePos); + + // highlight drag zone if hovering + if (isMouseInDragZone) + { + ImGui::GetForegroundDrawList()->AddRectFilled( + dragRect.Min, + dragRect.Max, + highlightColor + ); + } + + static bool isDragging = false; + if (ImGui::IsMouseDragging(0) && isMouseInDragZone) + isDragging = true; + if (ImGui::IsMouseReleased(0)) + isDragging = false; + + if (isDragging) + { + ImVec2 dragDelta = ImGui::GetMouseDragDelta(0); + ImGui::ResetMouseDragDelta(0); + + // move window + { + auto windowBounds = backendWindowHelper->GetWindowBounds(window); + windowBounds.position[0] += (int)dragDelta.x; + windowBounds.position[1] += (int)dragDelta.y; + backendWindowHelper->SetWindowBounds(window, windowBounds); + } + } + } + + // Drag zone at the bottom-right of the window + // This is still a draft, which needs to be completed + // and probably refactored: there is too much repetition between the two blocks of code + { + ImVec2 bottomRightCorner = ImGui::GetMainViewport()->Pos + ImGui::GetMainViewport()->Size; + ImVec2 topLeftCorner = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 1.5f); + + // Small triangle in the bottom-right corner + ImVec2 t1 = bottomRightCorner; + ImVec2 t2 = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 0.f); + ImVec2 t3 = bottomRightCorner - HelloImGui::EmToVec2(0.f, 1.5f); + + ImRect dragRect = ImRect(topLeftCorner, bottomRightCorner); + + ImVec2 mousePos = ImGui::GetIO().MousePos; + bool isMouseInDragZone = dragRect.Contains(mousePos); + + // highlight drag zone if hovering + if (isMouseInDragZone) + { + ImGui::GetForegroundDrawList()->AddTriangleFilled( + t1, t2, t3, + highlightColor + ); + } + + // To be completed... + + } + } +} + + diff --git a/src/hello_imgui/internal/borderless_resizable.h b/src/hello_imgui/internal/borderless_resizable.h new file mode 100644 index 00000000..08865369 --- /dev/null +++ b/src/hello_imgui/internal/borderless_resizable.h @@ -0,0 +1,10 @@ +#pragma once +#include "hello_imgui/runner_params.h" +#include "hello_imgui/internal/backend_impls/backend_window_helper/backend_window_helper.h" + +namespace HelloImGui +{ + void HandleBorderlessResizable( + BackendApi::WindowPointer window, + BackendApi::IBackendWindowHelper * backendWindowHelper); +} \ No newline at end of file diff --git a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp index 9b7937ff..71a79bab 100644 --- a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp +++ b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp @@ -498,6 +498,7 @@ int main(int, char**) runnerParams.imGuiWindowParams.menuAppTitle = "Docking Demo"; runnerParams.appWindowParams.windowGeometry.size = {1000, 900}; runnerParams.appWindowParams.restorePreviousGeometry = true; + runnerParams.appWindowParams.borderless = true; // Load additional font runnerParams.callbacks.LoadAdditionalFonts = LoadFonts; From a889c25963a0e045f46117fb3e692a8ad6c4e2cb Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Mon, 1 Jan 2024 15:57:36 +0100 Subject: [PATCH 2/3] Work on bordeless_movable --- src/hello_imgui/app_window_params.h | 26 ++++- .../backend_impls/abstract_runner.cpp | 14 ++- .../glfw_window_helper.cpp | 6 + .../internal/borderless_movable.cpp | 110 ++++++++++++++++++ ...rless_resizable.h => borderless_movable.h} | 8 +- .../internal/borderless_resizable.cpp | 88 -------------- 6 files changed, 151 insertions(+), 101 deletions(-) create mode 100644 src/hello_imgui/internal/borderless_movable.cpp rename src/hello_imgui/internal/{borderless_resizable.h => borderless_movable.h} (50%) delete mode 100644 src/hello_imgui/internal/borderless_resizable.cpp diff --git a/src/hello_imgui/app_window_params.h b/src/hello_imgui/app_window_params.h index 526b7219..ea8dcdb2 100644 --- a/src/hello_imgui/app_window_params.h +++ b/src/hello_imgui/app_window_params.h @@ -164,18 +164,28 @@ for details. _Note: on a mobile device, the application will always be full screen._ * `restorePreviousGeometry`: _bool, default=false_. If true, then save & restore windowGeometry from last run (the geometry will be written in imgui_app_window.ini) -* `borderless`: _bool, default = false_. Should the window have borders. This is taken into account at -creation. -* `resizable`: _bool, default = false_. Should the window have borders. This is taken into account at -creation. +* `resizable`: _bool, default = false_. Should the window be resizable. This is taken into account at + creation. * `hidden`: _bool, default = false_. Should the window be hidden. This is taken into account dynamically (you -can show/hide the window with this). Full screen windows cannot be hidden.@@md + can show/hide the window with this). Full screen windows cannot be hidden. + +* `borderless`: _bool, default = false_. Should the window have borders. This is taken into account at creation. +* `borderlessMovable`: _bool, default = true_. If the window is borderless, should it be movable. + If so, a drag zone is displayed at the top of the window when the mouse is over it. +* `borderlessResizable`: _bool, default = true_. If the window is borderless, should it be resizable. + If so, a drag zone is displayed at the bottom-right of the window when the mouse is over it. +* `borderlessHighlightColor`: _ImVec4, default = ImVec4(0.2f, 0.4f, 1.f, 0.f)_. + Color of the highlight displayed on resize/move zones. If borderlessHighlightColor.w==0, + then the highlightColor will be automatically set to ImGui::GetColorU32(ImGuiCol_TitleBgActive, 0.6f) + * `edgeInsets`: _EdgeInsets_. iOS only, out values filled by HelloImGui: if there is a notch on the iPhone, you should not display inside these insets. HelloImGui handles this automatically, if handleEdgeInsets is true and if runnerParams.imGuiWindowParams.defaultImGuiWindowType is not NoDefaultWindow. (warning, these values are updated only after a few frames, they are typically 0 for the first 4 frames) * `handleEdgeInsets`: _bool, default = true_. iOS only, if true, HelloImGui will handle the edgeInsets. + +@@md **/ struct AppWindowParams { @@ -186,10 +196,14 @@ struct AppWindowParams // if true, then save & restore from last run bool restorePreviousGeometry = false; - bool borderless = false; bool resizable = true; bool hidden = false; + bool borderless = false; + bool borderlessMovable = true; + bool borderlessResizable = true; + ImVec4 borderlessHighlightColor = ImVec4(0.2f, 0.4f, 1.f, 0.3f); + EdgeInsets edgeInsets; bool handleEdgeInsets = true; }; diff --git a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp index 3108a5fb..bb23088e 100644 --- a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp +++ b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp @@ -1,12 +1,12 @@ #include "hello_imgui/internal/backend_impls/abstract_runner.h" -#include "hello_imgui/internal/hello_imgui_ini_settings.h" -#include "hello_imgui/internal/docking_details.h" -#include "hello_imgui/internal/menu_statusbar.h" #include "hello_imgui/hello_imgui_theme.h" +#include "hello_imgui/internal/borderless_movable.h" #include "hello_imgui/internal/clock_seconds.h" +#include "hello_imgui/internal/docking_details.h" +#include "hello_imgui/internal/hello_imgui_ini_settings.h" +#include "hello_imgui/internal/menu_statusbar.h" #include "hello_imgui/internal/platform/ini_folder_locations.h" #include "imgui.h" -#include "hello_imgui/internal/borderless_resizable.h" #include "hello_imgui/internal/imgui_global_context.h" // must be included before imgui_internal.h #include "imgui_internal.h" @@ -506,7 +506,11 @@ void AbstractRunner::RenderGui() Menu_StatusBar::ShowMenu(params); if (params.appWindowParams.borderless) // Need to add params.appWindowParams.borderlessResizable - HandleBorderlessResizable(mWindow, mBackendWindowHelper.get()); + HandleBorderlessMovable(mWindow, + mBackendWindowHelper.get(), + params.appWindowParams.borderlessMovable, + params.appWindowParams.borderlessResizable, + params.appWindowParams.borderlessHighlightColor); if (params.callbacks.ShowGui) { diff --git a/src/hello_imgui/internal/backend_impls/backend_window_helper/glfw_window_helper.cpp b/src/hello_imgui/internal/backend_impls/backend_window_helper/glfw_window_helper.cpp index 59604810..6d7d8914 100644 --- a/src/hello_imgui/internal/backend_impls/backend_window_helper/glfw_window_helper.cpp +++ b/src/hello_imgui/internal/backend_impls/backend_window_helper/glfw_window_helper.cpp @@ -216,5 +216,11 @@ namespace HelloImGui { namespace BackendApi return (visible == 0); } +// void truc(WindowPointer window) +// { +// glfwCur +// +// } + }} // namespace HelloImGui { namespace BackendApi #endif // #ifdef HELLOIMGUI_USE_GLFW \ No newline at end of file diff --git a/src/hello_imgui/internal/borderless_movable.cpp b/src/hello_imgui/internal/borderless_movable.cpp new file mode 100644 index 00000000..f918159c --- /dev/null +++ b/src/hello_imgui/internal/borderless_movable.cpp @@ -0,0 +1,110 @@ +#define IMGUI_DEFINE_MATH_OPERATORS +#include "hello_imgui/internal/borderless_movable.h" +#include "hello_imgui/hello_imgui.h" +#include "imgui_internal.h" + + +namespace HelloImGui +{ + void HandleBorderlessMovable( + BackendApi::WindowPointer window, + BackendApi::IBackendWindowHelper * backendWindowHelper, + bool borderlessMovable, + bool borderlessResizable, + ImVec4 borderlessHighlightColor) + { + ImU32 highlightColorU32 = ImGui::GetColorU32(borderlessHighlightColor); + if (borderlessHighlightColor.w == 0.f) + highlightColorU32 = ImGui::GetColorU32(ImGuiCol_TitleBg, 0.6f); + + // Drag zone at the top of the window + if (borderlessMovable) + { + ImVec2 dragSize(ImGui::GetMainViewport()->Size.x, ImGui::GetFontSize() * 1.5f); + ImRect dragArea(ImGui::GetMainViewport()->Pos, ImGui::GetMainViewport()->Pos + dragSize); + + // Update dragging state + ImVec2 mousePos = ImGui::GetMousePos(); + static bool isDragging = false; + if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + { + isDragging = true; + } + if (!ImGui::IsMouseDragging(ImGuiMouseButton_Left) && isDragging) + isDragging = false; + + // Draw drag zone + if (dragArea.Contains(mousePos) || isDragging) + { + ImGui::GetForegroundDrawList()->AddRectFilled( + dragArea.Min, + dragArea.Max, + highlightColorU32 + ); + } + + // Move window if dragging + if (isDragging) + { + ImVec2 dragDelta = ImGui::GetMouseDragDelta(0); + ImGui::ResetMouseDragDelta(0); + auto windowBounds = backendWindowHelper->GetWindowBounds(window); + windowBounds.position[0] += (int)dragDelta.x; + windowBounds.position[1] += (int)dragDelta.y; + backendWindowHelper->SetWindowBounds(window, windowBounds); + ImGui::ResetMouseDragDelta(ImGuiMouseButton_Left); + } + + // Set mouse cursor: probably not visible for moving (the cursor will be the classic arrow) + if (dragArea.Contains(mousePos) || isDragging) + ImGui::SetMouseCursor(ImGuiMouseCursor_Arrow); + } + + // Drag zone at the bottom-right of the window + if (borderlessResizable) + { + ImVec2 bottomRightCorner = ImGui::GetMainViewport()->Pos + ImGui::GetMainViewport()->Size; + ImVec2 topLeftCorner = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 1.5f); + ImRect dragArea = ImRect(topLeftCorner, bottomRightCorner); + + // Update dragging state + static bool isDragging = false; + ImVec2 mousePos = ImGui::GetIO().MousePos; + if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + isDragging = true; + if (!ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + isDragging = false; + + // Draw drag zone + if (dragArea.Contains(mousePos) || isDragging) + { + // Small triangle in the bottom-right corner + ImVec2 t1 = bottomRightCorner; + ImVec2 t2 = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 0.f); + ImVec2 t3 = bottomRightCorner - HelloImGui::EmToVec2(0.f, 1.5f); + ImGui::GetForegroundDrawList()->AddTriangleFilled( + t1, t2, t3, + highlightColorU32 + ); + } + + // Resize window if dragging + if (isDragging) + { + ImVec2 dragDelta = ImGui::GetMouseDragDelta(0); + ImGui::ResetMouseDragDelta(0); + auto windowBounds = backendWindowHelper->GetWindowBounds(window); + windowBounds.size[0] += (int)dragDelta.x; + windowBounds.size[1] += (int)dragDelta.y; + backendWindowHelper->SetWindowBounds(window, windowBounds); + ImGui::ResetMouseDragDelta(ImGuiMouseButton_Left); + } + + // Set mouse cursor: (not visible under glfw < 3.4, which does not implement this cursor) + if (dragArea.Contains(mousePos) || isDragging) + ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNWSE); + } + } +} + + diff --git a/src/hello_imgui/internal/borderless_resizable.h b/src/hello_imgui/internal/borderless_movable.h similarity index 50% rename from src/hello_imgui/internal/borderless_resizable.h rename to src/hello_imgui/internal/borderless_movable.h index 08865369..34ae695b 100644 --- a/src/hello_imgui/internal/borderless_resizable.h +++ b/src/hello_imgui/internal/borderless_movable.h @@ -4,7 +4,11 @@ namespace HelloImGui { - void HandleBorderlessResizable( + void HandleBorderlessMovable( BackendApi::WindowPointer window, - BackendApi::IBackendWindowHelper * backendWindowHelper); + BackendApi::IBackendWindowHelper * backendWindowHelper, + bool borderlessMovable, + bool borderlessResizable, + ImVec4 borderlessHighlightColor + ); } \ No newline at end of file diff --git a/src/hello_imgui/internal/borderless_resizable.cpp b/src/hello_imgui/internal/borderless_resizable.cpp deleted file mode 100644 index 07be6035..00000000 --- a/src/hello_imgui/internal/borderless_resizable.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#define IMGUI_DEFINE_MATH_OPERATORS -#include "hello_imgui/internal/borderless_resizable.h" -#include "hello_imgui/hello_imgui.h" -#include "imgui_internal.h" - - -namespace HelloImGui -{ - void HandleBorderlessResizable( - BackendApi::WindowPointer window, - BackendApi::IBackendWindowHelper * backendWindowHelper) - { - ImVec2 winSize = ImGui::GetWindowSize(); - auto highlightColor = ImGui::GetColorU32(ImGuiCol_FrameBgHovered, 0.8f); - - // Drag zone at the top of the window - { - ImVec2 topLeftCorner = ImGui::GetMainViewport()->Pos; - ImVec2 bottomRightCorner = topLeftCorner + ImVec2(winSize.x, HelloImGui::EmSize(1.5f)); - ImRect dragRect = ImRect(topLeftCorner, bottomRightCorner); - - ImVec2 mousePos = ImGui::GetIO().MousePos; - bool isMouseInDragZone = dragRect.Contains(mousePos); - - // highlight drag zone if hovering - if (isMouseInDragZone) - { - ImGui::GetForegroundDrawList()->AddRectFilled( - dragRect.Min, - dragRect.Max, - highlightColor - ); - } - - static bool isDragging = false; - if (ImGui::IsMouseDragging(0) && isMouseInDragZone) - isDragging = true; - if (ImGui::IsMouseReleased(0)) - isDragging = false; - - if (isDragging) - { - ImVec2 dragDelta = ImGui::GetMouseDragDelta(0); - ImGui::ResetMouseDragDelta(0); - - // move window - { - auto windowBounds = backendWindowHelper->GetWindowBounds(window); - windowBounds.position[0] += (int)dragDelta.x; - windowBounds.position[1] += (int)dragDelta.y; - backendWindowHelper->SetWindowBounds(window, windowBounds); - } - } - } - - // Drag zone at the bottom-right of the window - // This is still a draft, which needs to be completed - // and probably refactored: there is too much repetition between the two blocks of code - { - ImVec2 bottomRightCorner = ImGui::GetMainViewport()->Pos + ImGui::GetMainViewport()->Size; - ImVec2 topLeftCorner = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 1.5f); - - // Small triangle in the bottom-right corner - ImVec2 t1 = bottomRightCorner; - ImVec2 t2 = bottomRightCorner - HelloImGui::EmToVec2(1.5f, 0.f); - ImVec2 t3 = bottomRightCorner - HelloImGui::EmToVec2(0.f, 1.5f); - - ImRect dragRect = ImRect(topLeftCorner, bottomRightCorner); - - ImVec2 mousePos = ImGui::GetIO().MousePos; - bool isMouseInDragZone = dragRect.Contains(mousePos); - - // highlight drag zone if hovering - if (isMouseInDragZone) - { - ImGui::GetForegroundDrawList()->AddTriangleFilled( - t1, t2, t3, - highlightColor - ); - } - - // To be completed... - - } - } -} - - From 4e77dc870547670b44828fc263ed24ad1c63321e Mon Sep 17 00:00:00 2001 From: Pascal Thomet Date: Mon, 1 Jan 2024 17:03:59 +0100 Subject: [PATCH 3/3] Finish work on bordeless_movable --- src/hello_imgui/internal/borderless_movable.cpp | 8 ++++---- .../hello_imgui_demodocking.main.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hello_imgui/internal/borderless_movable.cpp b/src/hello_imgui/internal/borderless_movable.cpp index f918159c..1478731c 100644 --- a/src/hello_imgui/internal/borderless_movable.cpp +++ b/src/hello_imgui/internal/borderless_movable.cpp @@ -26,11 +26,11 @@ namespace HelloImGui // Update dragging state ImVec2 mousePos = ImGui::GetMousePos(); static bool isDragging = false; - if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDown(ImGuiMouseButton_Left)) { isDragging = true; } - if (!ImGui::IsMouseDragging(ImGuiMouseButton_Left) && isDragging) + if (!ImGui::IsMouseDown(ImGuiMouseButton_Left) && isDragging) isDragging = false; // Draw drag zone @@ -70,9 +70,9 @@ namespace HelloImGui // Update dragging state static bool isDragging = false; ImVec2 mousePos = ImGui::GetIO().MousePos; - if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + if (dragArea.Contains(mousePos) && !isDragging && ImGui::IsMouseDown(ImGuiMouseButton_Left)) isDragging = true; - if (!ImGui::IsMouseDragging(ImGuiMouseButton_Left)) + if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) isDragging = false; // Draw drag zone diff --git a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp index 71a79bab..d911b976 100644 --- a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp +++ b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp @@ -498,7 +498,11 @@ int main(int, char**) runnerParams.imGuiWindowParams.menuAppTitle = "Docking Demo"; runnerParams.appWindowParams.windowGeometry.size = {1000, 900}; runnerParams.appWindowParams.restorePreviousGeometry = true; + + // Our application uses a borderless window, but is movable/resizable runnerParams.appWindowParams.borderless = true; + runnerParams.appWindowParams.borderlessMovable = true; + runnerParams.appWindowParams.borderlessResizable = true; // Load additional font runnerParams.callbacks.LoadAdditionalFonts = LoadFonts;