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 2eb31eac..bb23088e 100644 --- a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp +++ b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp @@ -1,9 +1,10 @@ #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" @@ -504,6 +505,13 @@ void AbstractRunner::RenderGui() if (params.imGuiWindowParams.showMenuBar) Menu_StatusBar::ShowMenu(params); + if (params.appWindowParams.borderless) // Need to add params.appWindowParams.borderlessResizable + HandleBorderlessMovable(mWindow, + mBackendWindowHelper.get(), + params.appWindowParams.borderlessMovable, + params.appWindowParams.borderlessResizable, + params.appWindowParams.borderlessHighlightColor); + if (params.callbacks.ShowGui) { bool wantAutoSize = WantAutoSize(); 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..1478731c --- /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::IsMouseDown(ImGuiMouseButton_Left)) + { + isDragging = true; + } + if (!ImGui::IsMouseDown(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::IsMouseDown(ImGuiMouseButton_Left)) + isDragging = true; + if (!ImGui::IsMouseDown(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_movable.h b/src/hello_imgui/internal/borderless_movable.h new file mode 100644 index 00000000..34ae695b --- /dev/null +++ b/src/hello_imgui/internal/borderless_movable.h @@ -0,0 +1,14 @@ +#pragma once +#include "hello_imgui/runner_params.h" +#include "hello_imgui/internal/backend_impls/backend_window_helper/backend_window_helper.h" + +namespace HelloImGui +{ + void HandleBorderlessMovable( + BackendApi::WindowPointer window, + BackendApi::IBackendWindowHelper * backendWindowHelper, + bool borderlessMovable, + bool borderlessResizable, + ImVec4 borderlessHighlightColor + ); +} \ 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..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,6 +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;