Browse Source

Introjucer: ability to drag files from the project tree into external apps. Added more drag-and-drop functionality for linux.

tags/2021-05-28
jules 13 years ago
parent
commit
565cb189ea
6 changed files with 439 additions and 56 deletions
  1. +30
    -0
      extras/Introjucer/Source/Application/jucer_MainWindow.cpp
  2. +2
    -0
      extras/Introjucer/Source/Application/jucer_MainWindow.h
  3. +2
    -0
      extras/Introjucer/Source/Project/jucer_ProjectTreeViewBase.h
  4. +2
    -1
      extras/Introjucer/Source/Utility/jucer_JucerTreeViewBase.h
  5. +38
    -24
      modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp
  6. +365
    -31
      modules/juce_gui_basics/native/juce_linux_Windowing.cpp

+ 30
- 0
extras/Introjucer/Source/Application/jucer_MainWindow.cpp View File

@@ -29,6 +29,7 @@
#include "jucer_OpenDocumentManager.h"
#include "../Code Editor/jucer_SourceCodeEditor.h"
#include "../Project/jucer_NewProjectWizard.h"
#include "../Utility/jucer_JucerTreeViewBase.h"
ScopedPointer<ApplicationCommandManager> commandManager;
@@ -228,6 +229,35 @@ void MainWindow::filesDropped (const StringArray& filenames, int mouseX, int mou
}
}
bool MainWindow::shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
StringArray& files, bool& canMoveFiles)
{
if (TreeView* tv = dynamic_cast <TreeView*> (sourceDetails.sourceComponent.get()))
{
Array<JucerTreeViewBase*> selected;
for (int i = tv->getNumSelectedItems(); --i >= 0;)
if (JucerTreeViewBase* b = dynamic_cast <JucerTreeViewBase*> (tv->getSelectedItem(i)))
selected.add (b);
if (selected.size() > 0)
{
for (int i = selected.size(); --i >= 0;)
{
const File f (selected.getUnchecked(i)->getDraggableFile());
if (f.existsAsFile())
files.add (f.getFullPathName());
}
canMoveFiles = false;
return files.size() > 0;
}
}
return false;
}
void MainWindow::activeWindowStatusChanged()
{
DocumentWindow::activeWindowStatusChanged();


+ 2
- 0
extras/Introjucer/Source/Application/jucer_MainWindow.h View File

@@ -74,6 +74,8 @@ public:
void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result);
bool perform (const InvocationInfo& info);
bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails,
StringArray& files, bool& canMoveFiles);
private:
ScopedPointer <Project> currentProject;


+ 2
- 0
extras/Introjucer/Source/Project/jucer_ProjectTreeViewBase.h View File

@@ -92,6 +92,8 @@ public:
static void getAllSelectedNodesInTree (Component* componentInTree, OwnedArray <Project::Item>& selectedNodes);
File getDraggableFile() const { return getFile(); }
//==============================================================================
Project::Item item;


+ 2
- 1
extras/Introjucer/Source/Utility/jucer_JucerTreeViewBase.h View File

@@ -58,7 +58,8 @@ public:
virtual Icon getIcon() const = 0;
virtual float getIconSize() const;
virtual void paintContent (Graphics& g, const Rectangle<int>& area);
virtual int getMillisecsAllowedForDragGesture() { return 120; };
virtual int getMillisecsAllowedForDragGesture() { return 120; };
virtual File getDraggableFile() const { return File::nonexistent; }
void refreshSubItems();
virtual void deleteItem();


+ 38
- 24
modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp View File

@@ -43,8 +43,7 @@ public:
owner (owner_),
mouseDragSource (mouseDragSource_),
imageOffset (imageOffset_),
hasCheckedForExternalDrag (false),
isDoingExternalDrag (false)
hasCheckedForExternalDrag (false)
{
setSize (im.getWidth(), im.getHeight());
@@ -96,16 +95,13 @@ public:
DragAndDropTarget::SourceDetails details (sourceDetails);
DragAndDropTarget* finalTarget = nullptr;
if (! isDoingExternalDrag)
{
const bool wasVisible = isVisible();
setVisible (false);
Component* unused;
finalTarget = findTarget (e.getScreenPosition(), details.localPosition, unused);
const bool wasVisible = isVisible();
setVisible (false);
Component* unused;
finalTarget = findTarget (e.getScreenPosition(), details.localPosition, unused);
if (wasVisible) // fade the component and remove it - it'll be deleted later by the timer callback
dismissWithAnimation (finalTarget == nullptr);
}
if (wasVisible) // fade the component and remove it - it'll be deleted later by the timer callback
dismissWithAnimation (finalTarget == nullptr);
if (getParentComponent() != nullptr)
getParentComponent()->removeChildComponent (this);
@@ -154,8 +150,15 @@ public:
sendDragMove (details);
if (canDoExternalDrag && getCurrentlyOver() == nullptr)
checkForExternalDrag (details, screenPos);
if (canDoExternalDrag)
{
const Time now (Time::getCurrentTime());
if (getCurrentlyOver() != nullptr)
lastTimeOverTarget = now;
else if (now > lastTimeOverTarget + RelativeTime::milliseconds (700))
checkForExternalDrag (details, screenPos);
}
}
void timerCallback()
@@ -179,7 +182,8 @@ private:
DragAndDropContainer& owner;
WeakReference<Component> mouseDragSource, currentlyOverComp;
const Point<int> imageOffset;
bool hasCheckedForExternalDrag, isDoingExternalDrag;
bool hasCheckedForExternalDrag;
Time lastTimeOverTarget;
DragAndDropTarget* getCurrentlyOver() const noexcept
{
@@ -236,6 +240,22 @@ private:
target->itemDragMove (details);
}
struct ExternalDragAndDropMessage : public CallbackMessage
{
ExternalDragAndDropMessage (const StringArray& f, bool canMove)
: files (f), canMoveFiles (canMove)
{}
void messageCallback()
{
DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles);
}
private:
StringArray files;
bool canMoveFiles;
};
void checkForExternalDrag (DragAndDropTarget::SourceDetails& details, const Point<int>& screenPos)
{
if (! hasCheckedForExternalDrag)
@@ -247,17 +267,11 @@ private:
bool canMoveFiles = false;
if (owner.shouldDropFilesWhenDraggedExternally (details, files, canMoveFiles)
&& files.size() > 0)
&& files.size() > 0
&& ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
{
WeakReference<Component> thisWeakRef (this);
setVisible (false);
isDoingExternalDrag = true;
if (ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown())
DragAndDropContainer::performExternalDragDropOfFiles (files, canMoveFiles);
delete thisWeakRef.get();
return;
(new ExternalDragAndDropMessage (files, canMoveFiles))->post();
delete this;
}
}
}


+ 365
- 31
modules/juce_gui_basics/native/juce_linux_Windowing.cpp View File

@@ -58,6 +58,7 @@ struct Atoms
XdndTypeList = getCreating ("XdndTypeList");
XdndActionList = getCreating ("XdndActionList");
XdndActionCopy = getCreating ("XdndActionCopy");
XdndActionPrivate = getCreating ("XdndActionPrivate");
XdndActionDescription = getCreating ("XdndActionDescription");
allowedMimeTypes[0] = getCreating ("UTF8_STRING");
@@ -65,11 +66,14 @@ struct Atoms
allowedMimeTypes[2] = getCreating ("text/plain");
allowedMimeTypes[3] = getCreating ("text/uri-list");
externalAllowedFileMimeTypes[0] = getCreating ("text/uri-list");
externalAllowedTextMimeTypes[0] = getCreating ("text/plain");
allowedActions[0] = getCreating ("XdndActionMove");
allowedActions[1] = XdndActionCopy;
allowedActions[2] = getCreating ("XdndActionLink");
allowedActions[3] = getCreating ("XdndActionAsk");
allowedActions[4] = getCreating ("XdndActionPrivate");
allowedActions[4] = XdndActionPrivate;
}
static const Atoms& get()
@@ -89,9 +93,11 @@ struct Atoms
ActiveWin, Pid, WindowType, WindowState,
XdndAware, XdndEnter, XdndLeave, XdndPosition, XdndStatus,
XdndDrop, XdndFinished, XdndSelection, XdndTypeList, XdndActionList,
XdndActionDescription, XdndActionCopy,
XdndActionDescription, XdndActionCopy, XdndActionPrivate,
allowedActions[5],
allowedMimeTypes[4];
allowedMimeTypes[4],
externalAllowedFileMimeTypes[1],
externalAllowedTextMimeTypes[1];
static const unsigned long DndVersion;
@@ -774,6 +780,15 @@ namespace PixmapHelpers
}
}
static void* createDraggingHandCursor()
{
static unsigned char dragHandData[] = { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,
0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,
132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 };
const int dragHandDataSize = 99;
return CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7).create();
}
//==============================================================================
class LinuxComponentPeer : public ComponentPeer
@@ -1270,6 +1285,8 @@ public:
case ConfigureNotify: handleConfigureNotifyEvent (event.xconfigure); break;
case ReparentNotify: handleReparentNotifyEvent(); break;
case GravityNotify: handleGravityNotify(); break;
case SelectionClear: handleExternalSelectionClear(); break;
case SelectionRequest: handleExternalSelectionRequest (event); break;
case CirculateNotify:
case CreateNotify:
@@ -1286,10 +1303,6 @@ public:
mapped = false;
break;
case SelectionClear:
case SelectionRequest:
break;
default:
#if JUCE_USE_XSHM
{
@@ -1493,6 +1506,9 @@ public:
default: break;
}
if (dragState.dragging)
handleExternalDragButtonReleaseEvent (buttonRelEvent);
handleMouseEvent (0, getMousePos (buttonRelEvent), currentModifiers, getEventTime (buttonRelEvent));
clearLastMousePos();
@@ -1531,6 +1547,9 @@ public:
}
}
if (dragState.dragging)
handleExternalDragMotionNotify();
handleMouseEvent (0, mousePos - getScreenPosition(), currentModifiers, getEventTime (movedEvent));
}
}
@@ -1718,14 +1737,42 @@ public:
}
else if (clientMsg.message_type == atoms.XdndStatus)
{
handleDragAndDropStatus (clientMsg);
handleExternalDragAndDropStatus (clientMsg);
}
else if (clientMsg.message_type == atoms.XdndFinished)
{
resetDragAndDrop();
externalResetDragAndDrop();
}
}
bool externalDragTextInit (const String& text)
{
if (dragState.dragging)
return false;
return externalDragInit (true, text);
}
bool externalDragFileInit (const StringArray& files, bool /*canMoveFiles*/)
{
if (dragState.dragging)
return false;
StringArray uriList;
for (int i = 0; i < files.size(); ++i)
{
const String& f = files[i];
if (f.matchesWildcard ("?*://*", false))
uriList.add (f);
else
uriList.add ("file://" + f);
}
return externalDragInit (false, uriList.joinIntoString ("\r\n"));
}
//==============================================================================
void showMouseCursor (Cursor cursor) noexcept
{
@@ -2128,6 +2175,7 @@ private:
{
ScopedXLock xlock;
resetDragAndDrop();
resetExternalDragState();
// Get defaults for various properties
const int screen = DefaultScreen (display);
@@ -2307,6 +2355,46 @@ private:
}
}
//==============================================================================
struct DragState
{
bool isText;
bool dragging; // currently performing outgoing external dnd as Xdnd source, have grabbed mouse
bool expectingStatus; // XdndPosition sent, waiting for XdndStatus
Window targetWindow; // potential drop target
Rectangle<int> silentRect;
bool canDrop; // target window signals it will accept the drop
int xdndVersion; // negotiated version with target
String textOrFiles;
void reset()
{
isText = false;
dragging = false;
expectingStatus = false;
canDrop = false;
silentRect = Rectangle<int>();
targetWindow = None;
xdndVersion = -1;
textOrFiles = String::empty;
}
const Atom* getMimeTypes() const noexcept { return isText ? Atoms::get().externalAllowedTextMimeTypes
: Atoms::get().externalAllowedFileMimeTypes; }
int getNumMimeTypes() const noexcept { return isText ? numElementsInArray (Atoms::get().externalAllowedTextMimeTypes)
: numElementsInArray (Atoms::get().externalAllowedFileMimeTypes); }
bool matchesTarget (Atom targetType) const
{
for (int i = getNumMimeTypes(); --i >= 0;)
if (getMimeTypes()[i] == targetType)
return true;
return false;
}
};
//==============================================================================
void resetDragAndDrop()
{
@@ -2318,6 +2406,11 @@ private:
finishAfterDropDataReceived = false;
}
void resetExternalDragState()
{
dragState.reset();
}
void sendDragAndDropMessage (XClientMessageEvent& msg)
{
msg.type = ClientMessage;
@@ -2330,6 +2423,63 @@ private:
XSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg);
}
bool sendExternalDragAndDropMessage (XClientMessageEvent& msg, const Window targetWindow)
{
msg.type = ClientMessage;
msg.display = display;
msg.window = targetWindow;
msg.format = 32;
msg.data.l[0] = windowH;
ScopedXLock xlock;
return XSendEvent (display, targetWindow, False, 0, (XEvent*) &msg) != 0;
}
void sendExternalDragAndDropDrop (const Window targetWindow)
{
XClientMessageEvent msg = { 0 };
msg.message_type = Atoms::get().XdndDrop;
msg.data.l[2] = CurrentTime;
sendExternalDragAndDropMessage (msg, targetWindow);
}
void sendExternalDragAndDropEnter (const Window targetWindow)
{
XClientMessageEvent msg = { 0 };
msg.message_type = Atoms::get().XdndEnter;
const Atoms& atoms = Atoms::get();
const Atom* mimeTypes = dragState.getMimeTypes();
const int numMimeTypes = dragState.getNumMimeTypes();
msg.data.l[1] = dragState.xdndVersion << 24 | numMimeTypes > 3;
msg.data.l[2] = numMimeTypes > 0 ? mimeTypes[0] : 0;
msg.data.l[3] = numMimeTypes > 1 ? mimeTypes[1] : 0;
msg.data.l[4] = numMimeTypes > 2 ? mimeTypes[2] : 0;
sendExternalDragAndDropMessage (msg, targetWindow);
}
void sendExternalDragAndDropPosition (const Window targetWindow)
{
XClientMessageEvent msg = { 0 };
msg.message_type = Atoms::get().XdndPosition;
const Point<int> mousePos (Desktop::getInstance().getMousePosition());
if (dragState.silentRect.contains (mousePos)) // we've been asked to keep silent
return;
msg.data.l[1] = 0;
msg.data.l[2] = (mousePos.x << 16) | mousePos.y;
msg.data.l[3] = CurrentTime;
msg.data.l[4] = Atoms::get().XdndActionCopy; // this is all JUCE currently supports
dragState.expectingStatus = sendExternalDragAndDropMessage (msg, targetWindow);
}
void sendDragAndDropStatus (const bool acceptDrop, Atom dropAction)
{
XClientMessageEvent msg = { 0 };
@@ -2340,11 +2490,11 @@ private:
sendDragAndDropMessage (msg);
}
void sendDragAndDropLeave()
void sendExternalDragAndDropLeave (const Window targetWindow)
{
XClientMessageEvent msg = { 0 };
msg.message_type = Atoms::get().XdndLeave;
sendDragAndDropMessage (msg);
sendExternalDragAndDropMessage (msg, targetWindow);
}
void sendDragAndDropFinish()
@@ -2354,19 +2504,116 @@ private:
sendDragAndDropMessage (msg);
}
void handleDragAndDropStatus (const XClientMessageEvent& clientMsg)
void handleExternalSelectionClear()
{
if ((clientMsg.data.l[1] & 1) == 0)
if (dragState.dragging)
externalResetDragAndDrop();
}
void handleExternalSelectionRequest (const XEvent& evt)
{
Atom targetType = evt.xselectionrequest.target;
XEvent s;
s.xselection.type = SelectionNotify;
s.xselection.requestor = evt.xselectionrequest.requestor;
s.xselection.selection = evt.xselectionrequest.selection;
s.xselection.target = targetType;
s.xselection.property = None;
s.xselection.time = evt.xselectionrequest.time;
if (dragState.matchesTarget (targetType))
{
sendDragAndDropLeave();
s.xselection.property = evt.xselectionrequest.property;
if (! dragInfo.isEmpty())
handleDragExit (dragInfo);
xchangeProperty (evt.xselectionrequest.requestor,
evt.xselectionrequest.property,
targetType, 8,
dragState.textOrFiles.toUTF8().getAddress(),
dragState.textOrFiles.getNumBytesAsUTF8());
}
XSendEvent (display, evt.xselectionrequest.requestor, True, 0, &s);
}
dragInfo.clear();
void handleExternalDragAndDropStatus (const XClientMessageEvent& clientMsg)
{
if (dragState.expectingStatus)
{
dragState.expectingStatus = false;
dragState.canDrop = false;
dragState.silentRect = Rectangle<int>();
if ((clientMsg.data.l[1] & 1) != 0
&& (clientMsg.data.l[4] == Atoms::get().XdndActionCopy
|| clientMsg.data.l[4] == Atoms::get().XdndActionPrivate))
{
if ((clientMsg.data.l[1] & 2) == 0) // target requests silent rectangle
dragState.silentRect.setBounds (clientMsg.data.l[2] >> 16,
clientMsg.data.l[2] & 0xffff,
clientMsg.data.l[3] >> 16,
clientMsg.data.l[3] & 0xffff);
dragState.canDrop = true;
}
}
}
void handleExternalDragButtonReleaseEvent (const XButtonReleasedEvent& buttonRelEvent)
{
if (dragState.dragging)
XUngrabPointer (display, CurrentTime);
if (dragState.canDrop)
{
sendExternalDragAndDropDrop (dragState.targetWindow);
}
else
{
sendExternalDragAndDropLeave (dragState.targetWindow);
externalResetDragAndDrop();
}
}
void handleExternalDragMotionNotify()
{
Window targetWindow = externalFindDragTargetWindow (RootWindow (display, DefaultScreen (display)));
if (dragState.targetWindow != targetWindow)
{
if (dragState.targetWindow != None)
sendExternalDragAndDropLeave (dragState.targetWindow);
dragState.canDrop = false;
dragState.silentRect = Rectangle<int>();
if (targetWindow == None)
return;
GetXProperty prop (targetWindow, Atoms::get().XdndAware,
0, 2, false, AnyPropertyType);
if (prop.success
&& prop.data != None
&& prop.actualFormat == 32
&& prop.numItems == 1)
{
dragState.xdndVersion = jmin ((int) prop.data[0], (int) Atoms::DndVersion);
}
else
{
dragState.xdndVersion = -1;
return;
}
sendExternalDragAndDropEnter (targetWindow);
dragState.targetWindow = targetWindow;
}
if (! dragState.expectingStatus)
sendExternalDragAndDropPosition (targetWindow);
}
void handleDragAndDropPosition (const XClientMessageEvent& clientMsg)
{
if (dragAndDropSourceWindow == 0)
@@ -2425,7 +2672,7 @@ private:
sendDragAndDropFinish();
resetDragAndDrop();
if (dragInfoCopy.files.size() > 0 || dragInfoCopy.text.isNotEmpty())
if (! dragInfoCopy.isEmpty())
handleDragDrop (dragInfoCopy);
}
@@ -2499,7 +2746,7 @@ private:
for (;;)
{
GetXProperty prop (evt.xany.window, evt.xselection.property,
dropData.getSize() / 4, 65536, true, AnyPropertyType);
dropData.getSize() / 4, 65536, false, AnyPropertyType);
if (! prop.success)
break;
@@ -2548,6 +2795,84 @@ private:
}
}
static bool isWindowDnDAware (Window w)
{
int numProperties = 0;
Atom* const atoms = XListProperties (display, w, &numProperties);
bool dndAwarePropFound = false;
for (int i = 0; i < numProperties; ++i)
if (atoms[i] == Atoms::get().XdndAware)
dndAwarePropFound = true;
if (atoms != nullptr)
XFree (atoms);
return dndAwarePropFound;
}
Window externalFindDragTargetWindow (Window targetWindow)
{
if (targetWindow == None)
return None;
if (isWindowDnDAware (targetWindow))
return targetWindow;
Window child, phonyWin;
int phony;
unsigned int uphony;
XQueryPointer (display, targetWindow, &phonyWin, &child,
&phony, &phony, &phony, &phony, &uphony);
return externalFindDragTargetWindow (child);
}
bool externalDragInit (bool isText, const String& textOrFiles)
{
ScopedXLock xlock;
resetExternalDragState();
dragState.isText = isText;
dragState.textOrFiles = textOrFiles;
const int pointerGrabMask = Button1MotionMask | ButtonReleaseMask;
if (XGrabPointer (display, windowH, True, pointerGrabMask,
GrabModeAsync, GrabModeAsync, None, None, CurrentTime) == GrabSuccess)
{
// No other method of changing the pointer seems to work, this call is needed from this very context
XChangeActivePointerGrab (display, pointerGrabMask, (Cursor) createDraggingHandCursor(), CurrentTime);
const Atoms& atoms = Atoms::get();
XSetSelectionOwner (display, atoms.XdndSelection, windowH, CurrentTime);
// save the available types to XdndTypeList
xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32,
dragState.getMimeTypes(),
dragState.getNumMimeTypes());
dragState.dragging = true;
handleExternalDragMotionNotify();
return true;
}
return false;
}
void externalResetDragAndDrop()
{
if (dragState.dragging)
{
ScopedXLock xlock;
XUngrabPointer (display, CurrentTime);
}
resetExternalDragState();
}
DragState dragState;
DragInfo dragInfo;
Atom dragAndDropCurrentMimeType;
Window dragAndDropSourceWindow;
@@ -2981,16 +3306,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty
case BottomLeftCornerResizeCursor: shape = XC_bottom_left_corner; break;
case BottomRightCornerResizeCursor: shape = XC_bottom_right_corner; break;
case CrosshairCursor: shape = XC_crosshair; break;
case DraggingHandCursor:
{
static unsigned char dragHandData[] = { 71,73,70,56,57,97,16,0,16,0,145,2,0,0,0,0,255,255,255,0,
0,0,0,0,0,33,249,4,1,0,0,2,0,44,0,0,0,0,16,0, 16,0,0,2,52,148,47,0,200,185,16,130,90,12,74,139,107,84,123,39,
132,117,151,116,132,146,248,60,209,138,98,22,203,114,34,236,37,52,77,217, 247,154,191,119,110,240,193,128,193,95,163,56,60,234,98,135,2,0,59 };
const int dragHandDataSize = 99;
return CustomMouseCursorInfo (ImageFileFormat::loadFrom (dragHandData, dragHandDataSize), 8, 7).create();
}
case DraggingHandCursor: return createDraggingHandCursor();
case CopyingCursor:
{
@@ -3033,13 +3349,31 @@ Image juce_createIconForFile (const File& file)
//==============================================================================
bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& files, const bool canMoveFiles)
{
jassertfalse; // not implemented!
if (files.size() == 0)
return false;
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
return lp->externalDragFileInit (files, canMoveFiles);
// This method must be called in response to a component's mouseDown or mouseDrag event!
jassertfalse;
return false;
}
bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
{
jassertfalse; // not implemented!
if (text.isEmpty())
return false;
if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0))
if (Component* sourceComp = draggingSource->getComponentUnderMouse())
if (LinuxComponentPeer* const lp = dynamic_cast <LinuxComponentPeer*> (sourceComp->getPeer()))
return lp->externalDragTextInit (text);
// This method must be called in response to a component's mouseDown or mouseDrag event!
jassertfalse;
return false;
}


Loading…
Cancel
Save