Problem with drag and drop from a ListBox

I have a listbox which uses drag and drop. If I have multiple instances of my plugin, it is possible to drag from one instance to the other. There are two problems.

  1. If instance A is covering instance B, and instance A is top most, juce will pick instance B as the drop destination depending on the order of windows. It should pick the instance that is on top, but it starts from the back of the list, apparently. See findDesktopComponentBelow() in juce_DragAndDropContainer.cpp

  2. There is no way to turn off external drag and drop in the listbox, as it defaults to true. See line 129 of juce_Listbox.cpp.

  3. There does not appear to be a way to add this functionality in a sub-class, so for now, I have just edited the Juce code with an optional flag to allow external dragging from list boxes.


I’ve just pushed a fix for 1.

Will have a look at the others tomorrow.

Awesome. Thank you t0m. (=

In your DragAndDropTarget can you just do

bool isInterestedInDragSource (const SourceDetails& details) override
    return details.sourceComponent.get() == &yourListBox;


That was the first thing I tried. Unfortunately, in that case, if they are overlapping, then it won’t allow you to drop on the area where the two instances intersect.

If the plug-in windows are overlapping? I can’t reproduce that in a simple test case.

I wasn’t able to at first too. My plugin window has a component that covers the entire plugin window and is a draganddroptarget and also a draganddropcontainer. The listbox is inside this window.

I was using this code to see if its the same instance.

bool isInterestedInDragSource(const SourceDetails &dragSourceDetails)
Component *topForSource = dragSourceDetails.sourceComponent->getTopLevelComponent();
Component *topForCur = getTopLevelComponent();
if ( topForCur == topForSource )
return true;

  1. I place the first instance on the top left and then the second instance on the bottom right (overlapping)
  2. Drag from the 1st instance on the left and drag to the right to the intersecting area and attempt to drop

I can shoot a video if you still can’t repro. Thanks again!

A video would be helpful and/or some source code. I’m using the following which must be pretty similar to what you’re describing:

#pragma once

#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginProcessor.h"

class DragAndDropTestAudioProcessorEditor  : public AudioProcessorEditor,
                                             public DragAndDropContainer,
                                             public DragAndDropTarget
    DragAndDropTestAudioProcessorEditor (DragAndDropTestAudioProcessor& p)
        : AudioProcessorEditor (&p), processor (p)
        lb.setRowHeight (30);
        addAndMakeVisible (lb);
        addChildComponent (&text);

        setSize (400, 300);

    ~DragAndDropTestAudioProcessorEditor() {}

    bool isInterestedInDragSource (const SourceDetails& dragSourceDetails) override
        if (auto* source = dragSourceDetails.sourceComponent.get())
            return getTopLevelComponent() == source->getTopLevelComponent();

        return false;

    void itemDropped (const SourceDetails& dragSourceDetails) override
        text.setVisible (true);

    void paint (Graphics& g) override
        g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));

    void resized() override
        text.setBounds (0, 0, 200, 200);
        lb.centreWithSize (90, 90);

    struct MyListBoxModel : public ListBoxModel
        int getNumRows() override { return 3; }

        void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, bool) override
            g.setColour (Colours::cyan);
            Rectangle<int> bounds (0, 0, width, height);
            g.fillRect (bounds.reduced (1));

        var getDragSourceDescription (const SparseSet<int>& rowsToDescribe) override
            return var ("LisBox rows");

    MyListBoxModel model;
    ListBox lb { "Listbox", &model };
    Label text { "Dropped", "Dropped" };

    DragAndDropTestAudioProcessor& processor;



And here’s it working as expected in REAPER (it also successfully prevents a drag to the other window).

1 Like