Skip to content

ui::DragDrop

Header: winui/ui/DragDrop.hpp.

The drag in progress, one per process: how a control starts an in-process drag and drop.

A source calls start() from its own pointer handling, usually once a pressed pointer has moved a few DIPs. The Window the event was dispatched in then takes the drag over: - pointer input drives the drag instead of reaching the tree - the recorded visual follows the pointer at 0.8 opacity - drop targets (Element::allow_drop()) get drag_enter(), drag_over(), drag_leave() and drop() - Escape cancels the drag

The source learns the outcome through Element::drag_completed(). Only one drag runs at a time, and start() while one is running is ignored. ListView, TileView and TreeView use this for their item dragging, and an app's own control can too.

Example:

class Chip final : public ui::Element
{
public:
    explicit Chip(std::string label) : label_(std::move(label)) {}

    void drag_completed(ui::DataPackageOperation result) override
    {
        dropped_ = result != ui::DataPackageOperation::None;
    }

protected:
    ui::Size measure_override(ui::Size, const ui::MeasureContext& context) const override
    {
        return context.measurer.measure(label_, context.theme.text_style);
    }
    void render_override(ui::Renderer& r, const ui::RenderContext& context) const override
    {
        r.draw_text(label_, bounds(), context.theme.colors().text, context.theme.text_style);
    }
    bool pointer_override(const ui::PointerEvent& e) override
    {
        if (e.action != ui::PointerAction::Down || ui::DragDrop::active())
        {
            return false;
        }
        ui::DataPackage package;
        package.text = label_;
        ui::RenderRecording visual; // what follows the pointer
        render(visual);
        ui::DragDrop::start(*this, std::move(package), std::move(visual), bounds(), e.position);
        return true;
    }

private:
    std::string label_;
    bool        dropped_ = false;
};

start

static void start(Element& source, DataPackage data, RenderRecording visual, Rect visual_bounds, Point pointer)

Start carrying data from source. visual is drawn under the pointer. It is recorded in the same coordinates as visual_bounds, the dragged thing's rect, and pointer is where the pointer is now, so the visual keeps that offset to the pointer as it moves. Sets data.source to &source. Ignored while another drag is running.

active

static bool active()

Whether a drag is in progress (or about to be taken over by its window).

pending

static bool pending()

Whether a drag has been started but no window has taken it over yet.

cancel

static void cancel()

End the drag in progress without a drop. The source's drag_completed() gets None. A pending drag is discarded.