NewFrame: Extract some code into a NewFrameUpdateHoveredWindowAndCaptureFlags() which can be of use with touch-based inputs systems.

This commit is contained in:
omar 2018-04-06 19:29:00 +02:00
parent c1bdab6d5b
commit e88fb10d7c
2 changed files with 61 additions and 49 deletions

108
imgui.cpp
View File

@ -3344,6 +3344,62 @@ static void ImGui::NewFrameUpdateMouseInputs()
} }
} }
// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app)
void ImGui::NewFrameUpdateHoveredWindowAndCaptureFlags()
{
ImGuiContext& g = *GImGui;
// Find the window hovered by mouse:
// - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow.
// - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame.
// - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow();
g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
// Modal windows prevents cursor from hovering behind them.
ImGuiWindow* modal_window = GetFrontMostModalRootWindow();
if (modal_window)
if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
g.HoveredRootWindow = g.HoveredWindow = NULL;
// 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.
int mouse_earliest_button_down = -1;
bool mouse_any_down = false;
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
{
if (g.IO.MouseClicked[i])
g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
mouse_any_down |= g.IO.MouseDown[i];
if (g.IO.MouseDown[i])
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
mouse_earliest_button_down = i;
}
const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
// 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)
const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
g.HoveredWindow = g.HoveredRootWindow = NULL;
// Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app)
if (g.WantCaptureMouseNextFrame != -1)
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
else
g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app)
if (g.WantCaptureKeyboardNextFrame != -1)
g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
else
g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
g.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
g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0;
}
void ImGui::NewFrame() void ImGui::NewFrame()
{ {
IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?");
@ -3446,63 +3502,17 @@ void ImGui::NewFrame()
// Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering)
NewFrameUpdateMovingWindow(); NewFrameUpdateMovingWindow();
NewFrameUpdateHoveredWindowAndCaptureFlags();
// Find the window we are hovering
// - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow())
// - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point.
// - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms.
g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow();
g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
ImGuiWindow* modal_window = GetFrontMostModalRootWindow();
if (modal_window != NULL)
{
g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f);
if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
g.HoveredRootWindow = g.HoveredWindow = NULL;
}
else else
{
g.ModalWindowDarkeningRatio = 0.0f; g.ModalWindowDarkeningRatio = 0.0f;
}
// Update the WantCaptureMouse/WantCaptureKeyboard flags, so user can capture/discard the inputs away from the rest of their application.
// When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership.
int mouse_earliest_button_down = -1;
bool mouse_any_down = false;
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
{
if (g.IO.MouseClicked[i])
g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
mouse_any_down |= g.IO.MouseDown[i];
if (g.IO.MouseDown[i])
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
mouse_earliest_button_down = i;
}
bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down];
if (g.WantCaptureMouseNextFrame != -1)
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
else
g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
if (g.WantCaptureKeyboardNextFrame != -1)
g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0);
else
g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL);
if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard))
g.IO.WantCaptureKeyboard = true;
g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0;
g.MouseCursor = ImGuiMouseCursor_Arrow; g.MouseCursor = ImGuiMouseCursor_Arrow;
g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
// 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)
bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0;
if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload)
g.HoveredWindow = g.HoveredRootWindow = NULL;
// Mouse wheel scrolling, scale // Mouse wheel scrolling, scale
if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f)) if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f))
{ {

View File

@ -1017,6 +1017,8 @@ namespace ImGui
IMGUI_API void Initialize(ImGuiContext* context); IMGUI_API void Initialize(ImGuiContext* context);
IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext().
IMGUI_API void NewFrameUpdateHoveredWindowAndCaptureFlags();
IMGUI_API void MarkIniSettingsDirty(); IMGUI_API void MarkIniSettingsDirty();
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id);