Search guides and the APICtrl K
  1. API reference
  2. Native GUI

gfx/text_drag.h

Dragging TEXT: between components, in from other applications, and out to them.

#include <sonore/gfx/text_drag.h>
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

↑↓ to move↵ to openEvery public name in the headers, and every guide