Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
This commit is contained in:
ocornut 2021-04-19 20:05:59 +02:00
commit 33cdbe97b8
7 changed files with 101 additions and 42 deletions

View File

@ -19,6 +19,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application.
// 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down. // 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down.
// 2020-10-28: Inputs: Added a fix for handling keypad-enter key. // 2020-10-28: Inputs: Added a fix for handling keypad-enter key.
// 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap". // 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap".
@ -31,12 +32,15 @@
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window. // 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
// 2018-07-07: Initial version. // 2018-07-07: Initial version.
@class ImFocusObserver;
// Data // Data
static CFAbsoluteTime g_Time = 0.0; static CFAbsoluteTime g_Time = 0.0;
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {}; static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
static bool g_MouseCursorHidden = false; static bool g_MouseCursorHidden = false;
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {}; static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {}; static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
static ImFocusObserver* g_FocusObserver = NULL;
// Undocumented methods for creating cursors. // Undocumented methods for creating cursors.
@interface NSCursor() @interface NSCursor()
@ -46,6 +50,31 @@ static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
+ (id)_windowResizeEastWestCursor; + (id)_windowResizeEastWestCursor;
@end @end
static void resetKeys()
{
ImGuiIO& io = ImGui::GetIO();
memset(io.KeysDown, 0, sizeof(io.KeysDown));
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
}
@interface ImFocusObserver : NSObject
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification;
@end
@implementation ImFocusObserver
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification
{
// Unfocused applications do not receive input events, therefore we must manually
// release any pressed keys when application loses focus, otherwise they would remain
// stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832
resetKeys();
}
@end
// Functions // Functions
bool ImGui_ImplOSX_Init() bool ImGui_ImplOSX_Init()
{ {
@ -124,11 +153,18 @@ bool ImGui_ImplOSX_Init()
return s_clipboard.Data; return s_clipboard.Data;
}; };
g_FocusObserver = [[ImFocusObserver alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
selector:@selector(onApplicationBecomeInactive:)
name:NSApplicationDidResignActiveNotification
object:nil];
return true; return true;
} }
void ImGui_ImplOSX_Shutdown() void ImGui_ImplOSX_Shutdown()
{ {
g_FocusObserver = NULL;
} }
static void ImGui_ImplOSX_UpdateMouseCursorAndButtons() static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
@ -201,13 +237,6 @@ static int mapCharacterToKey(int c)
return -1; return -1;
} }
static void resetKeys()
{
ImGuiIO& io = ImGui::GetIO();
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++)
io.KeysDown[n] = false;
}
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
{ {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();

View File

@ -112,6 +112,7 @@ Other Changes:
- Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010) - Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010)
- Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061) - Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061)
- Tables: Expose TableSetColumnEnabled() in public api. (#3935) - Tables: Expose TableSetColumnEnabled() in public api. (#3935)
- Tables: Better preserve widths when columns count changes. (#4046)
- TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single - TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single
frame and then immediately standling still (would only affect automation/bots). [@rokups] frame and then immediately standling still (would only affect automation/bots). [@rokups]
- Drags, Sliders, Inputs: Specifying a NULL format to Float functions default them to "%.3f" to be - Drags, Sliders, Inputs: Specifying a NULL format to Float functions default them to "%.3f" to be
@ -122,12 +123,16 @@ Other Changes:
- LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004) - LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004)
- LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004) - LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004)
- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash] - Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash]
- ImDrawList: Fixed/improved thickness of thick strokes with sharp angles. (#4053, #3366, #2964, #2868, #2518, #2183)
Effectively introduced a regression in 1.67 (Jan 2019), and a fix in 1.70 (Apr 2019) but the fix wasn't actually on
par with original version. Now incorporating the correct revert.
- ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd] - ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd]
- Demo: Improved popups demo and comments. - Demo: Improved popups demo and comments.
- Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly, - Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly,
effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx] effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx]
- Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961) - Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961)
[@1025798851] [@1025798851]
- Backends: OSX: Fix keys remaining stuck when CMD-tabbing to a different application. (#3832) [@rokups]
- Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to - Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to
workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857) workaround/fix state restoring issues. Unknown exactly why so, but bit of a cargo-cult fix. (#3857)
- Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when - Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when

View File

@ -4169,7 +4169,7 @@ void ImGui::NewFrame()
UpdateTabFocus(); UpdateTabFocus();
// Mark all windows as not visible and compact unused memory. // Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (int i = 0; i != g.Windows.Size; i++) for (int i = 0; i != g.Windows.Size; i++)
{ {
@ -5419,7 +5419,12 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags)
window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0);
} }
g.WindowsFocusOrder.push_back(window); if (!(flags & ImGuiWindowFlags_ChildWindow))
{
g.WindowsFocusOrder.push_back(window);
window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
}
if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus)
g.Windows.push_front(window); // Quite slow but rare and only once g.Windows.push_front(window); // Quite slow but rare and only once
else else
@ -6948,15 +6953,22 @@ void ImGui::End()
void ImGui::BringWindowToFocusFront(ImGuiWindow* window) void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(window == window->RootWindow);
const int cur_order = window->FocusOrder;
IM_ASSERT(g.WindowsFocusOrder[cur_order] == window);
if (g.WindowsFocusOrder.back() == window) if (g.WindowsFocusOrder.back() == window)
return; return;
for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the top-most window
if (g.WindowsFocusOrder[i] == window) const int new_order = g.WindowsFocusOrder.Size - 1;
{ for (int n = cur_order; n < new_order; n++)
memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*)); {
g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window; g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1];
break; g.WindowsFocusOrder[n]->FocusOrder--;
} IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n);
}
g.WindowsFocusOrder[new_order] = window;
window->FocusOrder = (short)new_order;
} }
void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
@ -7044,18 +7056,13 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
int start_idx = g.WindowsFocusOrder.Size - 1; const int start_idx = ((under_this_window != NULL) ? FindWindowFocusIndex(under_this_window) : g.WindowsFocusOrder.Size) - 1;
if (under_this_window != NULL)
{
int under_this_window_idx = FindWindowFocusIndex(under_this_window);
if (under_this_window_idx != -1)
start_idx = under_this_window_idx - 1;
}
for (int i = start_idx; i >= 0; i--) for (int i = start_idx; i >= 0; i--)
{ {
// We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
ImGuiWindow* window = g.WindowsFocusOrder[i]; ImGuiWindow* window = g.WindowsFocusOrder[i];
if (window != ignore_window && window->WasActive && window->RootWindow == window) IM_ASSERT(window == window->RootWindow);
if (window != ignore_window && window->WasActive)
if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
{ {
// FIXME-DOCK: This is failing (lagging by one frame) for docked windows. // FIXME-DOCK: This is failing (lagging by one frame) for docked windows.
@ -10164,13 +10171,12 @@ static void ImGui::NavEndFrame()
} }
} }
static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N) static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--) int order = window->FocusOrder;
if (g.WindowsFocusOrder[i] == window) IM_ASSERT(g.WindowsFocusOrder[order] == window);
return i; return order;
return -1;
} }
static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)

View File

@ -62,7 +62,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.83 WIP" #define IMGUI_VERSION "1.83 WIP"
#define IMGUI_VERSION_NUM 18203 #define IMGUI_VERSION_NUM 18204
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch

View File

@ -695,7 +695,8 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds. // On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.
// Those macros expects l-values. // Those macros expects l-values.
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0) #define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 < 0.5f) d2 = 0.5f; float inv_lensq = 1.0f / d2; VX *= inv_lensq; VY *= inv_lensq; } while (0) #define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } while (0)
// TODO: Thickness anti-aliased lines cap are missing their AA fringe. // TODO: Thickness anti-aliased lines cap are missing their AA fringe.
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds. // We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.

View File

@ -1491,7 +1491,7 @@ struct ImGuiContext
// Windows state // Windows state
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here!) ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child
ImVector<ImGuiWindow*> CurrentWindowStack; ImVector<ImGuiWindow*> CurrentWindowStack;
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow* ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
@ -1983,8 +1983,9 @@ struct IMGUI_API ImGuiWindow
bool HasCloseButton; // Set when the window has a close button (p_open != NULL) bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3) signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
short BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
short BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
ImS8 AutoFitFramesX, AutoFitFramesY; ImS8 AutoFitFramesX, AutoFitFramesY;
ImS8 AutoFitChildAxises; ImS8 AutoFitChildAxises;

View File

@ -465,10 +465,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->MemoryCompacted = false; table->MemoryCompacted = false;
// Setup memory buffer (clear data if columns count changed) // Setup memory buffer (clear data if columns count changed)
const int stored_size = table->Columns.size(); ImGuiTableColumn* old_columns_to_preserve = NULL;
if (stored_size != 0 && stored_size != columns_count) void* old_columns_raw_data = NULL;
const int old_columns_count = table->Columns.size();
if (old_columns_count != 0 && old_columns_count != columns_count)
{ {
IM_FREE(table->RawData); // Attempt to preserve width on column count change (#4046)
old_columns_to_preserve = table->Columns.Data;
old_columns_raw_data = table->RawData;
table->RawData = NULL; table->RawData = NULL;
} }
if (table->RawData == NULL) if (table->RawData == NULL)
@ -491,14 +495,24 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
for (int n = 0; n < columns_count; n++) for (int n = 0; n < columns_count; n++)
{ {
ImGuiTableColumn* column = &table->Columns[n]; ImGuiTableColumn* column = &table->Columns[n];
float width_auto = column->WidthAuto; if (old_columns_to_preserve && n < old_columns_count)
*column = ImGuiTableColumn(); {
column->WidthAuto = width_auto; // FIXME: We don't attempt to preserve column order in this path.
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker *column = old_columns_to_preserve[n];
}
else
{
float width_auto = column->WidthAuto;
*column = ImGuiTableColumn();
column->WidthAuto = width_auto;
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
column->IsEnabled = column->IsEnabledNextFrame = true;
}
column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n; column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
column->IsEnabled = column->IsEnabledNextFrame = true;
} }
} }
if (old_columns_raw_data)
IM_FREE(old_columns_raw_data);
// Load settings // Load settings
if (table->IsSettingsRequestLoad) if (table->IsSettingsRequestLoad)
@ -3345,6 +3359,9 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++) for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
{ {
// "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v" // "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
bool save_column = column->UserID != 0 || save_size || save_visible || save_order || (save_sort && column->SortOrder != -1);
if (!save_column)
continue;
buf->appendf("Column %-2d", column_n); buf->appendf("Column %-2d", column_n);
if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID); if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID);
if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight); if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight);