Skip to content

Commit

Permalink
Movable / Resizable borderless windows (Merge branch 'borderless_resi…
Browse files Browse the repository at this point in the history
…zable2')
  • Loading branch information
pthom committed Jan 1, 2024
2 parents 440ae7e + 4e77dc8 commit 9315d94
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 9 deletions.
26 changes: 20 additions & 6 deletions src/hello_imgui/app_window_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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;
};
Expand Down
14 changes: 11 additions & 3 deletions src/hello_imgui/internal/backend_impls/abstract_runner.cpp
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
110 changes: 110 additions & 0 deletions src/hello_imgui/internal/borderless_movable.cpp
Original file line number Diff line number Diff line change
@@ -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);
}
}
}


14 changes: 14 additions & 0 deletions src/hello_imgui/internal/borderless_movable.h
Original file line number Diff line number Diff line change
@@ -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
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 9315d94

Please sign in to comment.