gfx/text_drag.h
Dragging TEXT: between components, in from other applications, and out to them.
#include <sonore/gfx/text_drag.h>- 1type
- 1other declaration
- Guides: The native editor
On this page
Design notes
The three paths, and why they meet at one interface
A TextDragAndDropTarget (component.h) is told about text being dragged over it, wherever the text came from:
Inside the editor. A field the user selects text in starts the drag with MouseRouter::startTextDrag, and the router's ordinary drag machinery carries it -- the same capture, the same walk up from the pointer to find a component that wants it. Component's default item-drag handlers hand a text drag to the TextDragAndDropTarget, so a target needs no other code. From another application. The platform's drop target -- an OLE IDropTarget on Windows, the view's dragging destination on macOS -- reads the text off the drag and hands it to a TextDragDispatcher, which finds the target the same way and tells it the same things. Out to another application. performExternalDragDropOfText puts the text on the platform's drag pasteboard and runs the system's drag.
Windows: why OLE now, when files came by WM_DROPFILES
window_win32.h explains why files arrive by WM_DROPFILES: one call, no COM, nothing to unwind. Text has no such message -- dragged text exists only as an IDataObject handed to a registered IDropTarget -- so accepting it means registering one. Once one is registered, Windows sends it EVERYTHING dropped on the window and stops sending WM_DROPFILES, so the drop target here reads files (CF_HDROP) as well as text (CF_UNICODETEXT, then CF_TEXT), and files gain the live hover feedback WM_DROPFILES could not give.
The cost the old comment named is real and is paid carefully. The target is registered only on a thread the host has already made a single-threaded apartment -- every host that does drag and drop has -- and OleInitialize, which on such a thread adds OLE without changing the apartment, is balanced at close. A thread with no apartment or in the multithreaded one is left untouched and the window keeps WM_DROPFILES exactly as before. ole32 is loaded at run time rather than linked, so a plugin that never drags text imports nothing new.
macOS
The view registers for the string pasteboard type beside the file types and reads public.utf8-plain-text off a drag that has no files. Compiled against the shim, never run. Dragging text OUT on macOS is not implemented: it needs an NSDraggingSource registered at run time and the mouse-down NSEvent that started the gesture, which the component tree does not keep.
X11's XDND already negotiates text/plain for the file path; the X11 peer does not yet hand text drops to a dispatcher, and the row says so.
Types 1
Takes text dragged in from OUTSIDE the tree and delivers it to whichever TextDragAndDropTarget is under the pointer.
One per window, driven by the platform's drop target. Finds its target the way the router finds an item-drag target -- up from the component under the pointer to the first that is interested -- and holds it only while it is alive: a target destroyed mid-drag is forgotten, not called.
Functions 1
- fn
inline bool performExternalDragDropOfText(const std::string& text)Draggfx::performExternalDragDropOfText · text_drag.h:667textout of the editor, to wherever the user lets go -- another application's text field, the desktop, another plugin.