IO: added io.WantCaptureMouseAllowPopupClose (#4480) + comments

This commit is contained in:
ocornut 2021-08-30 14:55:26 +02:00
parent 66102880a3
commit 4aea1c5adb
4 changed files with 43 additions and 23 deletions

View File

@ -47,6 +47,9 @@ Other Changes:
the whole widget is clipped. the whole widget is clipped.
- TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform - TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform
to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615)
- IO: Added 'io.WantCaptureMouseUnlessPopupClose' alternative to `io.WantCaptureMouse'. (#4480)
This allows apps to receive the click on void when that click is used to close popup (by default,
clicking on a void when a popup is open will close the popup but not release io.WantCaptureMouse).
- Fonts: imgui_freetype: Fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL - Fonts: imgui_freetype: Fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL
(which apparently happens with Freetype 2.11). (#4394, #4145?). (which apparently happens with Freetype 2.11). (#4394, #4145?).
- Fonts: Fixed ImFontAtlas::ClearInputData() marking atlas as not built. (#4455, #3487) - Fonts: Fixed ImFontAtlas::ClearInputData() marking atlas as not built. (#4455, #3487)

View File

@ -3872,6 +3872,7 @@ void ImGui::UpdateTabFocus()
void ImGui::UpdateHoveredWindowAndCaptureFlags() void ImGui::UpdateHoveredWindowAndCaptureFlags()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING)); g.WindowsHoverPadding = ImMax(g.Style.TouchExtraPadding, ImVec2(WINDOWS_HOVER_PADDING, WINDOWS_HOVER_PADDING));
// Find the window hovered by mouse: // Find the window hovered by mouse:
@ -3887,48 +3888,61 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
clear_hovered_windows = true; clear_hovered_windows = true;
// Disabled mouse? // Disabled mouse?
if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
clear_hovered_windows = true; clear_hovered_windows = true;
// We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. // We track click ownership. When clicked outside of a window the click is owned by the application and
int mouse_earliest_button_down = -1; // won't report hovering nor request capture even while dragging over our windows afterward.
const bool has_open_popup = (g.OpenPopupStack.Size > 0);
const bool has_open_modal = (modal_window != NULL);
int mouse_earliest_down = -1;
bool mouse_any_down = false; bool mouse_any_down = false;
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
{ {
if (g.IO.MouseClicked[i]) if (io.MouseClicked[i])
g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (g.OpenPopupStack.Size > 0); {
mouse_any_down |= g.IO.MouseDown[i]; io.MouseDownOwned[i] = (g.HoveredWindow != NULL) || has_open_popup;
if (g.IO.MouseDown[i]) io.MouseDownOwnedUnlessPopupClose[i] = (g.HoveredWindow != NULL) || has_open_modal;
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) }
mouse_earliest_button_down = i; mouse_any_down |= io.MouseDown[i];
if (io.MouseDown[i])
if (mouse_earliest_down == -1 || io.MouseClickedTime[i] < io.MouseClickedTime[mouse_earliest_down])
mouse_earliest_down = i;
} }
const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; const bool mouse_avail = (mouse_earliest_down == -1) || io.MouseDownOwned[mouse_earliest_down];
const bool mouse_avail_unless_popup_close = (mouse_earliest_down == -1) || io.MouseDownOwnedUnlessPopupClose[mouse_earliest_down];
// If mouse was first clicked outside of ImGui bounds we also cancel out hovering. // If mouse was first clicked outside of ImGui bounds we also cancel out hovering.
// FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02)
const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) if (!mouse_avail && !mouse_dragging_extern_payload)
clear_hovered_windows = true; clear_hovered_windows = true;
if (clear_hovered_windows) if (clear_hovered_windows)
g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL; g.HoveredWindow = g.HoveredWindowUnderMovingWindow = NULL;
// Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app) // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to Dear ImGui only, false = dispatch mouse to Dear ImGui + underlying app)
// Update io.WantCaptureMouseAllowPopupClose (experimental) to give a chance for app to react to popup closure with a drag
if (g.WantCaptureMouseNextFrame != -1) if (g.WantCaptureMouseNextFrame != -1)
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); {
io.WantCaptureMouse = io.WantCaptureMouseUnlessPopupClose = (g.WantCaptureMouseNextFrame != 0);
}
else else
g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.OpenPopupStack.Size > 0); {
io.WantCaptureMouse = (mouse_avail && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_popup;
io.WantCaptureMouseUnlessPopupClose = (mouse_avail_unless_popup_close && (g.HoveredWindow != NULL || mouse_any_down)) || has_open_modal;
}
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app) // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to Dear ImGui only, false = dispatch keyboard info to Dear ImGui + underlying app)
if (g.WantCaptureKeyboardNextFrame != -1) if (g.WantCaptureKeyboardNextFrame != -1)
g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); io.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
else else
g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); io.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) if (io.NavActive && (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
g.IO.WantCaptureKeyboard = true; io.WantCaptureKeyboard = true;
// Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible
g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false; io.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : false;
} }
ImGuiKeyModFlags ImGui::GetMergedKeyModFlags() ImGuiKeyModFlags ImGui::GetMergedKeyModFlags()

View File

@ -64,7 +64,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.85 WIP" #define IMGUI_VERSION "1.85 WIP"
#define IMGUI_VERSION_NUM 18409 #define IMGUI_VERSION_NUM 18410
#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
@ -1918,6 +1918,7 @@ struct ImGuiIO
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed! // [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------ //------------------------------------------------------------------
bool WantCaptureMouseUnlessPopupClose;// Alternative to WantCaptureMouse: (WantCaptureMouse == true && WantCaptureMouseUnlessPopupClose == false) when a click over void is expected to close a popup.
ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame() ImGuiKeyModFlags KeyMods; // Key mods flags (same as io.KeyCtrl/KeyShift/KeyAlt/KeySuper but merged into flags), updated by NewFrame()
ImGuiKeyModFlags KeyModsPrev; // Previous key mods ImGuiKeyModFlags KeyModsPrev; // Previous key mods
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid) ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
@ -1926,7 +1927,8 @@ struct ImGuiIO
bool MouseClicked[5]; // Mouse button went from !Down to Down bool MouseClicked[5]; // Mouse button went from !Down to Down
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? bool MouseDoubleClicked[5]; // Has mouse button been double-clicked?
bool MouseReleased[5]; // Mouse button went from Down to !Down bool MouseReleased[5]; // Mouse button went from Down to !Down
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window. We don't request mouse capture from the application if click started outside ImGui bounds. bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
bool MouseDownOwnedUnlessPopupClose[5];//Track if button was clicked inside a dear imgui window.
bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked) float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down float MouseDownDurationPrev[5]; // Previous time the mouse button has been down

View File

@ -5481,6 +5481,7 @@ static void ShowDemoWindowMisc()
// Display ImGuiIO output flags // Display ImGuiIO output flags
ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
ImGui::Text("WantTextInput: %d", io.WantTextInput); ImGui::Text("WantTextInput: %d", io.WantTextInput);
ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);