When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() If the item has an identifier: - This assume/require the item to be activated (typically via ButtonBehavior). - Therefore if you want to use this with a mouse button other than left mouse button, it is up to the item itself to activate with an
| 14715 | // If the item has no identifier: |
| 14716 | // - Currently always assume left mouse button. |
| 14717 | bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) |
| 14718 | { |
| 14719 | ImGuiContext& g = *GImGui; |
| 14720 | ImGuiWindow* window = g.CurrentWindow; |
| 14721 | |
| 14722 | // FIXME-DRAGDROP: While in the common-most "drag from non-zero active id" case we can tell the mouse button, |
| 14723 | // in both SourceExtern and id==0 cases we may requires something else (explicit flags or some heuristic). |
| 14724 | ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; |
| 14725 | |
| 14726 | bool source_drag_active = false; |
| 14727 | ImGuiID source_id = 0; |
| 14728 | ImGuiID source_parent_id = 0; |
| 14729 | if ((flags & ImGuiDragDropFlags_SourceExtern) == 0) |
| 14730 | { |
| 14731 | source_id = g.LastItemData.ID; |
| 14732 | if (source_id != 0) |
| 14733 | { |
| 14734 | // Common path: items with ID |
| 14735 | if (g.ActiveId != source_id) |
| 14736 | return false; |
| 14737 | if (g.ActiveIdMouseButton != -1) |
| 14738 | mouse_button = g.ActiveIdMouseButton; |
| 14739 | if (g.IO.MouseDown[mouse_button] == false || window->SkipItems) |
| 14740 | return false; |
| 14741 | g.ActiveIdAllowOverlap = false; |
| 14742 | } |
| 14743 | else |
| 14744 | { |
| 14745 | // Uncommon path: items without ID |
| 14746 | if (g.IO.MouseDown[mouse_button] == false || window->SkipItems) |
| 14747 | return false; |
| 14748 | if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredRect) == 0 && (g.ActiveId == 0 || g.ActiveIdWindow != window)) |
| 14749 | return false; |
| 14750 | |
| 14751 | // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: |
| 14752 | // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag. |
| 14753 | if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) |
| 14754 | { |
| 14755 | IM_ASSERT(0); |
| 14756 | return false; |
| 14757 | } |
| 14758 | |
| 14759 | // Magic fallback to handle items with no assigned ID, e.g. Text(), Image() |
| 14760 | // We build a throwaway ID based on current ID stack + relative AABB of items in window. |
| 14761 | // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZINGG OF THE WIDGET, so if your widget moves your dragging operation will be canceled. |
| 14762 | // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. |
| 14763 | // Rely on keeping other window->LastItemXXX fields intact. |
| 14764 | source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect); |
| 14765 | KeepAliveID(source_id); |
| 14766 | bool is_hovered = ItemHoverable(g.LastItemData.Rect, source_id, g.LastItemData.ItemFlags); |
| 14767 | if (is_hovered && g.IO.MouseClicked[mouse_button]) |
| 14768 | { |
| 14769 | SetActiveID(source_id, window); |
| 14770 | FocusWindow(window); |
| 14771 | } |
| 14772 | if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. |
| 14773 | g.ActiveIdAllowOverlap = is_hovered; |
| 14774 | } |
nothing calls this directly
no test coverage detected