@ -716,6 +716,7 @@ namespace ImGui
static void NavUpdate ( ) ;
static void NavUpdateWindowing ( ) ;
static void NavProcessItem ( ImGuiWindow * window , const ImRect & nav_bb , const ImGuiID id ) ;
static void UpdateManualResize ( ImGuiWindow * window , const ImVec2 & size_auto_fit , int * border_held , ImU32 resize_grip_col [ 4 ] ) ;
static void FocusFrontMostActiveWindow ( ImGuiWindow * ignore_window ) ;
}
@ -5236,6 +5237,112 @@ static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_paddin
return ImRect ( ) ;
}
// Handle resize for: Resize Grips, Borders, Gamepad
static void ImGui : : UpdateManualResize ( ImGuiWindow * window , const ImVec2 & size_auto_fit , int * border_held , ImU32 resize_grip_col [ 4 ] )
{
ImGuiContext & g = * GImGui ;
ImGuiWindowFlags flags = window - > Flags ;
if ( ( flags & ImGuiWindowFlags_NoResize ) | | ( flags & ImGuiWindowFlags_AlwaysAutoResize ) | | window - > AutoFitFramesX > 0 | | window - > AutoFitFramesY > 0 )
return ;
const int resize_grip_count = ( flags & ImGuiWindowFlags_ResizeFromAnySide ) ? 2 : 1 ; // 4
const int resize_border_count = ( flags & ImGuiWindowFlags_ResizeFromAnySide ) ? 4 : 0 ;
const float grip_draw_size = ( float ) ( int ) ImMax ( g . FontSize * 1.35f , window - > WindowRounding + 1.0f + g . FontSize * 0.2f ) ;
const float grip_hover_size = ( float ) ( int ) ( grip_draw_size * 0.75f ) ;
ImVec2 pos_target ( FLT_MAX , FLT_MAX ) ;
ImVec2 size_target ( FLT_MAX , FLT_MAX ) ;
// Manual resize grips
PushID ( " #RESIZE " ) ;
for ( int resize_grip_n = 0 ; resize_grip_n < resize_grip_count ; resize_grip_n + + )
{
const ImGuiResizeGripDef & grip = resize_grip_def [ resize_grip_n ] ;
const ImVec2 corner = ImLerp ( window - > Pos , window - > Pos + window - > Size , grip . CornerPos ) ;
// Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
ImRect resize_rect ( corner , corner + grip . InnerDir * grip_hover_size ) ;
resize_rect . FixInverted ( ) ;
bool hovered , held ;
ButtonBehavior ( resize_rect , window - > GetID ( ( void * ) ( intptr_t ) resize_grip_n ) , & hovered , & held , ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus ) ;
if ( hovered | | held )
g . MouseCursor = ( resize_grip_n & 1 ) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE ;
if ( g . HoveredWindow = = window & & held & & g . IO . MouseDoubleClicked [ 0 ] & & resize_grip_n = = 0 )
{
// Manual auto-fit when double-clicking
size_target = CalcSizeAfterConstraint ( window , size_auto_fit ) ;
ClearActiveID ( ) ;
}
else if ( held )
{
// Resize from any of the four corners
// We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
ImVec2 corner_target = g . IO . MousePos - g . ActiveIdClickOffset + resize_rect . GetSize ( ) * grip . CornerPos ; // Corner of the window corresponding to our corner grip
CalcResizePosSizeFromAnyCorner ( window , corner_target , grip . CornerPos , & pos_target , & size_target ) ;
}
if ( resize_grip_n = = 0 | | held | | hovered )
resize_grip_col [ resize_grip_n ] = GetColorU32 ( held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip ) ;
}
for ( int border_n = 0 ; border_n < resize_border_count ; border_n + + )
{
const float BORDER_SIZE = 5.0f ; // FIXME: Only works _inside_ window because of HoveredWindow check.
const float BORDER_APPEAR_TIMER = 0.05f ; // Reduce visual noise
bool hovered , held ;
ImRect border_rect = GetBorderRect ( window , border_n , grip_hover_size , BORDER_SIZE ) ;
ButtonBehavior ( border_rect , window - > GetID ( ( void * ) ( intptr_t ) ( border_n + 4 ) ) , & hovered , & held , ImGuiButtonFlags_FlattenChildren ) ;
if ( ( hovered & & g . HoveredIdTimer > BORDER_APPEAR_TIMER ) | | held )
{
g . MouseCursor = ( border_n & 1 ) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS ;
if ( held ) * border_held = border_n ;
}
if ( held )
{
ImVec2 border_target = window - > Pos ;
ImVec2 border_posn ;
if ( border_n = = 0 ) { border_posn = ImVec2 ( 0 , 0 ) ; border_target . y = ( g . IO . MousePos . y - g . ActiveIdClickOffset . y ) ; }
if ( border_n = = 1 ) { border_posn = ImVec2 ( 1 , 0 ) ; border_target . x = ( g . IO . MousePos . x - g . ActiveIdClickOffset . x + BORDER_SIZE ) ; }
if ( border_n = = 2 ) { border_posn = ImVec2 ( 0 , 1 ) ; border_target . y = ( g . IO . MousePos . y - g . ActiveIdClickOffset . y + BORDER_SIZE ) ; }
if ( border_n = = 3 ) { border_posn = ImVec2 ( 0 , 0 ) ; border_target . x = ( g . IO . MousePos . x - g . ActiveIdClickOffset . x ) ; }
CalcResizePosSizeFromAnyCorner ( window , border_target , border_posn , & pos_target , & size_target ) ;
}
}
PopID ( ) ;
// Navigation/gamepad resize
if ( g . NavWindowingTarget = = window )
{
ImVec2 nav_resize_delta = GetNavInputAmount2d ( 0 , ImGuiNavReadMode_Down ) ;
if ( nav_resize_delta . x ! = 0.0f | | nav_resize_delta . y ! = 0.0f )
{
const float GAMEPAD_RESIZE_SPEED = 600.0f ;
nav_resize_delta * = ImFloor ( GAMEPAD_RESIZE_SPEED * g . IO . DeltaTime * ImMin ( g . IO . DisplayFramebufferScale . x , g . IO . DisplayFramebufferScale . y ) ) ;
g . NavDisableMouseHover = true ;
resize_grip_col [ 0 ] = GetColorU32 ( ImGuiCol_ResizeGripActive ) ;
if ( nav_resize_delta . x ! = 0.0f | | nav_resize_delta . y ! = 0.0f )
{
// FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
g . NavWindowingToggleLayer = false ;
size_target = CalcSizeAfterConstraint ( window , window - > SizeFull + nav_resize_delta ) ;
}
}
}
// Apply back modified position/size to window
if ( size_target . x ! = FLT_MAX )
{
window - > SizeFull = size_target ;
MarkIniSettingsDirty ( window ) ;
}
if ( pos_target . x ! = FLT_MAX )
{
window - > Pos = window - > PosFloat = ImFloor ( pos_target ) ;
MarkIniSettingsDirty ( window ) ;
}
window - > Size = window - > SizeFull ;
}
// Push a new ImGui window to add widgets to.
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
// - Begin/End can be called multiple times during the frame with the same window name to append content.
@ -5386,16 +5493,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if ( ( flags & ImGuiWindowFlags_ChildWindow ) & & ! ( flags & ( ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup ) ) & & window - > WindowBorderSize = = 0.0f )
window - > WindowPadding = ImVec2 ( 0.0f , ( flags & ImGuiWindowFlags_MenuBar ) ? style . WindowPadding . y : 0.0f ) ;
// Setup draw list and outer clipping rectangle
window - > DrawList - > Clear ( ) ;
window - > DrawList - > Flags = ( g . Style . AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0 ) | ( g . Style . AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0 ) ;
window - > DrawList - > PushTextureID ( g . Font - > ContainerAtlas - > TexID ) ;
ImRect fullscreen_rect ( GetVisibleRect ( ) ) ;
if ( ( flags & ImGuiWindowFlags_ChildWindow ) & & ! ( flags & ImGuiWindowFlags_Popup ) )
PushClipRect ( parent_window - > ClipRect . Min , parent_window - > ClipRect . Max , true ) ;
else
PushClipRect ( fullscreen_rect . Min , fullscreen_rect . Max , true ) ;
if ( window_just_activated_by_user )
{
// Popup first latch mouse position, will position itself when it appears next frame
@ -5571,6 +5668,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if ( ! ( flags & ( ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip ) ) | | ( flags & ImGuiWindowFlags_Popup ) )
want_focus = true ;
// DRAWING
// Setup draw list and outer clipping rectangle
window - > DrawList - > Clear ( ) ;
window - > DrawList - > Flags = ( g . Style . AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0 ) | ( g . Style . AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0 ) ;
window - > DrawList - > PushTextureID ( g . Font - > ContainerAtlas - > TexID ) ;
ImRect fullscreen_rect ( GetVisibleRect ( ) ) ;
if ( ( flags & ImGuiWindowFlags_ChildWindow ) & & ! ( flags & ImGuiWindowFlags_Popup ) )
PushClipRect ( parent_window - > ClipRect . Min , parent_window - > ClipRect . Max , true ) ;
else
PushClipRect ( fullscreen_rect . Min , fullscreen_rect . Max , true ) ;
// Draw modal window background (darkens what is behind them)
if ( ( flags & ImGuiWindowFlags_Modal ) ! = 0 & & window = = GetFrontMostModalRootWindow ( ) )
window - > DrawList - > AddRectFilled ( fullscreen_rect . Min , fullscreen_rect . Max , GetColorU32 ( ImGuiCol_ModalWindowDarkening , g . ModalWindowDarkeningRatio ) ) ;
// Draw navigation windowing rectangle (via ImGuiKey_NavWindowing key), shows whole window selected
if ( g . NavWindowingTarget = = window )
{
@ -5580,10 +5693,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
window - > DrawList - > AddRect ( bb . Min , bb . Max , GetColorU32 ( ImGuiCol_HeaderHovered , g . NavWindowingDisplayAlpha ) , g . Style . WindowRounding ) ;
}
// Draw modal window background (darkens what is behind them)
if ( ( flags & ImGuiWindowFlags_Modal ) ! = 0 & & window = = GetFrontMostModalRootWindow ( ) )
window - > DrawList - > AddRectFilled ( fullscreen_rect . Min , fullscreen_rect . Max , GetColorU32 ( ImGuiCol_ModalWindowDarkening , g . ModalWindowDarkeningRatio ) ) ;
// Draw window + handle manual resize
const float window_rounding = window - > WindowRounding ;
const float window_border_size = window - > WindowBorderSize ;
@ -5603,105 +5712,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
int border_held = - 1 ;
ImU32 resize_grip_col [ 4 ] = { 0 } ;
const int resize_grip_count = ( flags & ImGuiWindowFlags_ResizeFromAnySide ) ? 2 : 1 ; // 4
const int resize_border_count = ( flags & ImGuiWindowFlags_ResizeFromAnySide ) ? 4 : 0 ;
const float grip_draw_size = ( float ) ( int ) ImMax ( g . FontSize * 1.35f , window_rounding + 1.0f + g . FontSize * 0.2f ) ;
const float grip_hover_size = ( float ) ( int ) ( grip_draw_size * 0.75f ) ;
if ( ! ( flags & ImGuiWindowFlags_AlwaysAutoResize ) & & window - > AutoFitFramesX < = 0 & & window - > AutoFitFramesY < = 0 & & ! ( flags & ImGuiWindowFlags_NoResize ) )
{
ImVec2 pos_target ( FLT_MAX , FLT_MAX ) ;
ImVec2 size_target ( FLT_MAX , FLT_MAX ) ;
// Manual resize grips
PushID ( " #RESIZE " ) ;
for ( int resize_grip_n = 0 ; resize_grip_n < resize_grip_count ; resize_grip_n + + )
{
const ImGuiResizeGripDef & grip = resize_grip_def [ resize_grip_n ] ;
const ImVec2 corner = ImLerp ( window - > Pos , window - > Pos + window - > Size , grip . CornerPos ) ;
// Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window
ImRect resize_rect ( corner , corner + grip . InnerDir * grip_hover_size ) ;
resize_rect . FixInverted ( ) ;
bool hovered , held ;
ButtonBehavior ( resize_rect , window - > GetID ( ( void * ) ( intptr_t ) resize_grip_n ) , & hovered , & held , ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus ) ;
if ( hovered | | held )
g . MouseCursor = ( resize_grip_n & 1 ) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE ;
if ( g . HoveredWindow = = window & & held & & g . IO . MouseDoubleClicked [ 0 ] & & resize_grip_n = = 0 )
{
// Manual auto-fit when double-clicking
size_target = CalcSizeAfterConstraint ( window , size_auto_fit ) ;
ClearActiveID ( ) ;
}
else if ( held )
{
// Resize from any of the four corners
// We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position
ImVec2 corner_target = g . IO . MousePos - g . ActiveIdClickOffset + resize_rect . GetSize ( ) * grip . CornerPos ; // Corner of the window corresponding to our corner grip
CalcResizePosSizeFromAnyCorner ( window , corner_target , grip . CornerPos , & pos_target , & size_target ) ;
}
if ( resize_grip_n = = 0 | | held | | hovered )
resize_grip_col [ resize_grip_n ] = GetColorU32 ( held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip ) ;
}
for ( int border_n = 0 ; border_n < resize_border_count ; border_n + + )
{
const float BORDER_SIZE = 5.0f ; // FIXME: Only works _inside_ window because of HoveredWindow check.
const float BORDER_APPEAR_TIMER = 0.05f ; // Reduce visual noise
bool hovered , held ;
ImRect border_rect = GetBorderRect ( window , border_n , grip_hover_size , BORDER_SIZE ) ;
ButtonBehavior ( border_rect , window - > GetID ( ( void * ) ( intptr_t ) ( border_n + 4 ) ) , & hovered , & held , ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_NoNavFocus ) ;
if ( ( hovered & & g . HoveredIdTimer > BORDER_APPEAR_TIMER ) | | held )
{
g . MouseCursor = ( border_n & 1 ) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS ;
if ( held ) border_held = border_n ;
}
if ( held )
{
ImVec2 border_target = window - > Pos ;
ImVec2 border_posn ;
if ( border_n = = 0 ) { border_posn = ImVec2 ( 0 , 0 ) ; border_target . y = ( g . IO . MousePos . y - g . ActiveIdClickOffset . y ) ; }
if ( border_n = = 1 ) { border_posn = ImVec2 ( 1 , 0 ) ; border_target . x = ( g . IO . MousePos . x - g . ActiveIdClickOffset . x + BORDER_SIZE ) ; }
if ( border_n = = 2 ) { border_posn = ImVec2 ( 0 , 1 ) ; border_target . y = ( g . IO . MousePos . y - g . ActiveIdClickOffset . y + BORDER_SIZE ) ; }
if ( border_n = = 3 ) { border_posn = ImVec2 ( 0 , 0 ) ; border_target . x = ( g . IO . MousePos . x - g . ActiveIdClickOffset . x ) ; }
CalcResizePosSizeFromAnyCorner ( window , border_target , border_posn , & pos_target , & size_target ) ;
}
}
PopID ( ) ;
// Navigation/gamepad resize
if ( g . NavWindowingTarget = = window )
{
ImVec2 nav_resize_delta = GetNavInputAmount2d ( 0 , ImGuiNavReadMode_Down ) ;
if ( nav_resize_delta . x ! = 0.0f | | nav_resize_delta . y ! = 0.0f )
{
const float GAMEPAD_RESIZE_SPEED = 600.0f ;
nav_resize_delta * = ImFloor ( GAMEPAD_RESIZE_SPEED * g . IO . DeltaTime * ImMin ( g . IO . DisplayFramebufferScale . x , g . IO . DisplayFramebufferScale . y ) ) ;
g . NavDisableMouseHover = true ;
resize_grip_col [ 0 ] = GetColorU32 ( ImGuiCol_ResizeGripActive ) ;
if ( nav_resize_delta . x ! = 0.0f | | nav_resize_delta . y ! = 0.0f )
{
// FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck.
g . NavWindowingToggleLayer = false ;
size_target = CalcSizeAfterConstraint ( window , window - > SizeFull + nav_resize_delta ) ;
}
}
}
// Apply back modified position/size to window
if ( size_target . x ! = FLT_MAX )
{
window - > SizeFull = size_target ;
MarkIniSettingsDirty ( window ) ;
}
if ( pos_target . x ! = FLT_MAX )
{
window - > Pos = window - > PosFloat = ImFloor ( pos_target ) ;
MarkIniSettingsDirty ( window ) ;
}
window - > Size = window - > SizeFull ;
const float grip_draw_size = ( float ) ( int ) ImMax ( g . FontSize * 1.35f , window - > WindowRounding + 1.0f + g . FontSize * 0.2f ) ;
UpdateManualResize ( window , size_auto_fit , & border_held , & resize_grip_col [ 0 ] ) ;
title_bar_rect = window - > TitleBarRect ( ) ;
}
// Window background, Default Alpha
ImU32 bg_col = GetColorU32 ( GetWindowBgColorIdxFromFlags ( flags ) ) ;