Distinguish between Drag,Click,Double-Click after mouse release

Hi,

I want to implement a behavior in which a node of graph-editor reacts differently if its dragged or just clicked (I.e. the drag distance never exceeded a drag threshold). I experimented with some combinations, but it seems like…

IsMouseDragging() and IsMouseClicked() only respond while the mouse IS down.

After IsItemReleased() GetMouseDragDelta() returns 0,0 so I have not means to distinguish between a drag and click.

I guess there must be a pattern for implementing this kind of interactions with Imgui.

Two side notes:

  • I personally stumbled of the wording “Clicked”, because I expected this to be called after release.
  • I was also looking for a method to distinguish between single- and double clicks without hitting the first click.

thanks a lot,
tom

This was fixed in master on March 14, see Opening a popup only when the mouse hasn't dragged · Issue #2419 · ocornut/imgui · GitHub.

Regardless of the name, it would be incorrect to implement a solely “mouse” API that does what you are suggesting. The common UI pattern for button press does indeed requires a mouse down followed by a mouse up (this is what we do) BUT it relies on the mouse coordinates AND buttons/widgets coordinates as for press and release needs to be within the bound of the same item. An hypothetical IsMouseXXX() function that did what you are suggesting wouldn’t be able to be a low-level mouse state/function any more. Also see for answer to a similar question IsMouseClicked has a misleading name · Issue #2385 · ocornut/imgui · GitHub

I am not sure how that would be possible unless you delay reaction to the first click.

Hi ocornut,

Thanks a lot for for this quick and thorough reply. I’m always amazed by your precise thinking and clear and understandable arguments. I’m looking forward to the next release of imgui.

Regarding mouse handling events: I’m personally not quite convinced about this decision. Of course you are right, that there can’t be a distinction between single and double mouse-clicks without delaying the response to the single click. That’s what html/javascript is doing and causes a lot of headache.
However I personally think that low-level mouse handling (press, hold/drag, release) can go nicely together with slightly higher and potentially delayed mouse-gesture interpretations (clicked, dragged, double clicked within an item). Both have their purpose. Since storing the mouse-down-position already makes the mouse-handling stateful, adding a single click interpretation might not be out of question. Until then, I will need to get used to a single-click signal that also fires on double-clicks.

If you have a few minutes to spare, can you point me to more advanced public code examples with best practices to such mouse gestures? Although I get things working with DearImgui most of the time, I have the gutt feeling that my code could be simpler and easier to read.

In imgui.net a recent code fragment of mine looks like this:

        public static void DrawOnNodeCanvas(SymbolChildUi childUi, GraphCanvasWindow canvas)
        {
            ImGui.PushID(childUi.SymbolChild.Id.GetHashCode());
            {
                var posInWindow = canvas.ChildPosFromCanvas(childUi.Position);
                var posInApp = canvas.ScreenPosFromCanvas(childUi.Position);

                // Interaction
                ImGui.SetCursorPos(posInWindow);
                ImGui.InvisibleButton("node", childUi.Size * canvas._scale);
                if (ImGui.IsItemHovered())
                {
                    ImGui.SetMouseCursor(ImGuiMouseCursor.Hand);
                }

                if (ImGui.IsItemHovered())
                    T3UI.AddHoveredId(childUi.SymbolChild.Id);

                if (ImGui.IsItemActive())
                {
                    if (ImGui.IsItemClicked(0))
                    {
                        if (!canvas.SelectionHandler.SelectedElements.Contains(childUi))
                        {
                            canvas.SelectionHandler.SetElement(childUi);
                        }
                    }
                    if (ImGui.IsMouseDragging(0))
                    {
                        foreach (var e in canvas.SelectionHandler.SelectedElements)
                        {
                            e.Position += ImGui.GetIO().MouseDelta;
                        }
                    }
                }


                // Rendering
...
         }
         ImGui.PopID();
}