ドラッグ&ドロップで転送されるデータは、一般的にプレーンテキストか、ファイルやその他のリソースを指定するURLのリストのいずれかです。テキストをドロップすると、その位置に挿入され、それが不可能な場合はキルリングに保存されます。
ドロップされたURLは、変数dnd-protocol-alistを介して該当するDNDハンドラ関数に、あるいは変数browse-url-handlersおよびbrowse-url-default-handlersで定義される「URLハンドラ」に渡されます。いずれのタイプの対応するハンドラも存在しない場合は、プレーンテキストとして扱われ、バッファに挿入されます。
この変数は、URLの照合に用いる正規表現と、一致するURLがドロップされた際に呼び出されるDNDハンドラ関数との対応関係を示すalistです。
ハンドラ関数が、dnd-multiple-handler プロパティ(シンボルプロパティを参照)が設定されたシンボルである場合、ドロップ時にその正規表現に一致するすべてのURLのリストが渡されます。このプロパティが設定されていない場合は、それらのURLごとに1回ずつ呼び出されます。この第1引数に続くのは、実行すべきアクションを識別するシンボル
copy、move、link、private、または ask のいずれかです。
action が private
である場合、ドロップを開始したプログラムは、受信側に対して特定の動作を要求しません。その場合に取るべき妥当な対応は、URL
を開くか、その内容を現在のバッファにコピーすることです。action のその他の値は、dnd-begin-file-drag の action
引数とほぼ同様の意味を持ちます。
処理が完了すると、ハンドラ関数は実行したアクションを示すシンボルを返さなければなりません。それは、指定されたアクションか、あるいは指定されたアクションが実行されなかったことをドロップ元に伝えるシンボル
private のいずれかです。
ドロップ内の重複するアイテムのサブセットに対して複数のハンドラがマッチした場合、最も多くのアイテムにマッチしたハンドラが呼び出され、そのサブセットを開きます。当該ハンドラに渡されたアイテムは、その後、たとえ他のハンドラにもマッチする場合であっても、それらのハンドラには渡されません。
Emacsでは、テキストとURL以外のデータを受け付けるための措置を講じていない。これを可能にするウィンドウシステムのインターフェース同士は、互いに乖離しすぎており、一貫した形で抽象化することができないためである。また、特定のドラッグ&ドロッププロトコルが受信側にそのような制御権を認めていないため、DNDハンドラが本来行うべき動作に影響を及ぼすこともできない。X11のドラッグ&ドロップ実装は、選択転送を利用し、多くの共通点を持つ複数の基盤プロトコルに基づいており、それらへの低レベルアクセスは以下の関数および変数を通じて提供されている:
この関数は、Emacsがドロップを受け付けるべきかどうかを判定するために呼び出されます。3つの引数を取って呼び出されます:
move、copy、link、または ask のいずれか。これらのシンボルは、x-begin-drag と同様の意味を持つ。
この関数は、ドロップを拒否する場合は nil
を、実行されるアクション(DNDハンドラ関数への転送など)の cons および要求する選択データ型を返さなければなりません。その cons
で返されるアクションにはシンボル private
が含まれる場合もあり、これは実行されるアクションが現時点では未確定であることを示します。
x-dnd-test-function
を変更することは一般的に不要です。というのも、ドロップを受理するためのデフォルトの判定基準は、この選択データ型のリストを変更することで調整できるからです。各要素は文字列であり、デフォルトの「テスト関数」によってデータ型リスト内の要素のシンボル名として検出された場合、その関数がドロップを受理するようになります。
このリストに新しいエントリを追加する場合、x-dnd-types-alistに対応するハンドラ関数を追記しない限り意味がありません。
この変数は、選択データ型を指定する文字列と、それらの型のオブジェクトがドロップされた際に呼び出される関数との対応関係を示すalistです。
こうした各関数には3つの引数が渡されます。1つ目は、x-dnd-test-functionのようにドロップ位置の下にあるウィンドウまたはフレーム、2つ目は実行されるアクション(テスト関数が返すアクションのいずれか)、そして3つ目は選択データそのものです(選択へのアクセスを参照)。
X11のドラッグ&ドロッププロトコルで提供される選択データ型は、ICCCMや準拠するクリップボードまたはプライマリ選択オーナーが提供するものとは異なる場合があります。多くの場合、"text/plain;charset=utf-8"(“utf-8”の大文字・小文字が異なる)のようなMIMEタイプ名が、UTF8_STRINGのような標準的なX選択名の代わりに用いられます。
X Direct Save (XDS) プロトコルにより、プログラムはドロップされたファイルの命名責任を受信側に委譲できるようになります。このようなドロップが発生すると、DNDハンドラや前述のX固有のインターフェースは概ねバイパスされ、別の機能がドロップへの対応を担うことになります。
この変数には、XDSプロトコルを用いてドロップされたファイルを2段階の手順で登録し、命名する関数を設定する必要があります。この変数には、need-name と filename の2つの引数が渡されます。
nil)が、第2引数には保存対象ファイルのベース名であるfilenameが指定されます。この関数は、ファイルを保存する際の完全に展開された絶対ファイル名を返す必要があります。例えば、ファイルをDiredウィンドウにドラッグした場合、そのファイルの自然なディレクトリは、ドロップ位置に表示されているファイルのディレクトリとなります。何らかの理由でファイルの保存が不可能な場合、関数はnilを返す必要があり、これによりドラッグ&ドロップ操作がキャンセルされます。
nil が、第2引数
filename
には保存されたファイルの完全な絶対名が設定されます。その後、この関数はファイルが保存されたという事実に基づき、必要な処理を行うことになります。例えば、Diredは画面上のディレクトリを更新し、そこに新しいファイルを表示させる必要があります。
デフォルトの x-dnd-direct-save-function は x-dnd-save-direct です。
need-name 引数に non-nil
を指定して呼び出すと、この関数は保存先となる絶対ファイル名をユーザーに入力させます。指定したファイルが既に存在する場合は、さらに上書きするかどうかをユーザーに確認し、ユーザーが上書きを承認した場合にのみ絶対ファイル名を返します。
need-name 引数 nil
を指定して呼び出すと、現在のバッファが Dired モードまたはその派生モードにある場合は Dired の一覧表示に戻り、そうでない場合は find-file を呼び出してファイルを訪問します(ファイル訪問用関数 を参照)。
この関数は x-dnd-save-direct と同様に動作しますが、引数 need-name に non-nil
を指定して呼び出すと、保存するファイル名のフルネームをユーザーに問い合わせることはなく、代わりに現在のバッファのデフォルトディレクトリに基づいて展開された引数
filename を返します(ファイル名を展開する関数
を参照)。(ただし、デフォルトディレクトリにその名前のファイルが既に存在する場合は、引き続き確認を求めます。)
また、現在のウィンドウシステムが対応していれば、Emacsから他のプログラムへコンテンツをドラッグすることも可能です。これを実現する関数は以下の通りです。
この関数は、frame から別のプログラム(ドロップ先と呼ばれる)へのドラッグ&ドロップ操作を開始し、text がドロップされるか、あるいは操作がキャンセルされたときに戻ります。
action はシンボル copy または move のいずれかである必要があります。ここで copy
はドロップターゲットによって text が挿入されるべきであることを意味し、move は copy
と同じ意味ですが、呼び出し側はまた、以下のリストで説明されている通り、ソースから text
を削除しなければなりません。
frame は現在マウスボタンが押されているフレーム、nil
は選択中のフレームを使用することを意味します。この関数は、マウスボタンが押されていない場合には即座に返り値を返す可能性があるため、down-mouse-1 またはそれに類するイベント(マウスイベント を参照)に応じてのみ呼び出すべきであり、その際 frame にはそのイベントが発生したフレーム(クリックイベント を参照)を設定します。
allow-same-frame が nil
の場合、frame の上にドロップしたものは無視されます。
戻り値は、ドロップターゲットが実際に実行した操作を反映しており、したがって、呼び出し側が次にどのような操作を行うべきか(あるいは行う必要がないか)も示します。戻り値は、以下のシンボルのいずれかとなります。
copyドロップターゲットにドロップしたテキストが挿入されました。
moveドロップターゲットがドロップされたテキストを挿入し、必要に応じて、呼び出し元はそれが抽出されたバッファから text を削除する必要があります。
privateドロップターゲットは、その他の不特定の操作を行った。
nilドラッグ&ドロップ操作がキャンセルされました。
この関数は、frame から別のプログラム(ドロップ先と呼ばれる)へのドラッグ&ドロップ操作を開始し、file がドロップされるか、あるいは操作がキャンセルされたときに戻ります。
file がリモートファイルの場合、一時的なローカルコピーが作成されます。
action は copy、move、または link
のいずれかの記号である必要があります。ここで、copy はドロップ先が file を展開またはコピーすることを、move
はドロップ先がファイルを別の場所に移動することを、link はドロップ先が file へのシンボリックリンクを作成することをそれぞれ意味します。file がリモートファイルである場合に、アクションとして link を指定するとエラーとなります。
frame および allow-same-frame
は、dnd-begin-text-drag の呼び出し時と同様の意味を持ちます。
戻り値は、ドロップターゲットが実際に実行した操作であり、以下のシンボルのいずれかとなります。
copyドロップ先が開いたか、file を別の場所にコピーしました。
moveドロップターゲットが file だけ別の位置に移動しました。
linkドロップ先(通常はファイルマネージャー)が file へのシンボリックリンクを作成しました。
privateドロップターゲットが、その他の不特定の操作を行った。
nilドラッグ&ドロップ操作がキャンセルされました。
この関数は dnd-begin-file-drag と同様ですが、files
がファイルのリストである点が異なります。ドロップ先が複数ファイルのドロップに対応していない場合は、代わりに最初のファイルが使用されます。
この関数の動作は、dnd-begin-file-drag(デフォルトの動作であるcopyが使用される場合)と同様ですが、コピーを格納するファイル名を指定できる点が異なります。
上述の高レベルインターフェースは、より低レベルなプリミティブの上に実装されています。また、テキストやファイル以外のコンテンツをドラッグするための低レベルインターフェース
x-begin-drag
も利用可能です。これには、呼び出し元がサポートしたい各プラットフォーム上のプログラムが認識するデータ型や操作に関する詳細な知識が求められます。
この関数は frame
からドラッグを開始し、ドロップが成功したか、あるいはドロップが拒否されたかのいずれかの理由でドラッグ&ドロップ操作が終了した際に復帰します。ドロップは、frame 以外の X ウィンドウ(ドロップターゲット)、または allow-current-frame が nil
以外の場合は任意の X
ウィンドウ上で、すべてのマウスボタンが離されたときに発生します。ドラッグ&ドロップ操作の開始時にマウスボタンが一つも押されていない場合、この関数は直ちに
nil を返すことがあります。
targets は、gui-get-selection
の引数 data-type と同様に、ドロップターゲットが Emacs
に要求できる選択対象を表す文字列のリストです(ウィンドウシステムの選択 を参照)。
action は、対象に対して推奨される操作を示す記号です。XdndActionCopy または XdndActionMove のいずれかであり、いずれも選択範囲 XdndSelection
の内容をドロップ先にコピーすることを意味しますが、後者はさらにコピー後に選択範囲の内容を削除するという約束を含んでいます。
action は、利用可能なアクションを表すシンボルと、ドロップターゲットがユーザーに提示してそれらのアクションから選択させる文字列とを対応付けるアリストである場合もあります。
return-frame が nil ではなく、まず
frame の外に移動した後にマウスが Emacs
フレーム上に移動した場合、マウスが移動した先のフレームが直ちに返されます。return-frame
がシンボル now である場合、マウスが frame
の外に最初に移動するのを待たずに、マウスポインタの下にある任意のフレームが返されます。return-frame
は、あるフレームから別のフレームへコンテンツをドラッグする場合を特別に扱いつつ、同時に他のプログラムへもコンテンツをドラッグしたい場合に有用ですが、すべてのシステムやすべてのウィンドウマネージャで動作することが保証されているわけではありません。
follow-tooltip が nil
以外の場合、任意のツールチップ(tooltip-show
によって表示されるものなど)の位置は、ドラッグ&ドロップ操作中に移動するマウスポインタの位置に従います。すべてのマウスボタンが離されると、ツールチップは非表示になります。
ドロップが拒否されたか、あるいはドロップ先が見つからなかった場合、この関数は nil
を返します。それ以外の場合は、ターゲットが選択しようとしたアクションを表すシンボルを返します。ドロップ先がそのアクションをサポートしていない場合、この値は
action とは異なることがあります。XdndActionCopy および XdndActionMove に加えて、XdndActionPrivate
も有効な戻り値となります。これは、ドロップ先が未確定のアクションを選択したことを示しており、呼び出し側でさらなるアクションを行う必要はありません。
呼び出し元は、ターゲットが選択したアクションを完了させるために、ターゲットに協力しなければなりません。例えば、この関数が XdndActionMove
を返した場合、呼び出し元はドラッグされたバッファテキストを削除すべきであり、同様の基準が適用される他のドラッグデータについても同様とします。
x-begin-drag
関数は、「裏側」で複数のドラッグ&ドロッププロトコルを活用しています。特定のドラッグ&ドロッププロトコルでサポートされていないことが分かっているコンテンツをドラッグする場合、以下の変数の値を変更することで、そのプロトコルを無効化できます。
これが nil 以外の場合、Motif
のドラッグ&ドロッププロトコルは無効となり、それらのみに対応しているプログラム上にドロップしても動作しません。
これが nil
の場合、OffiX(旧KDE)のドラッグ&ドロッププロトコルは無効になります。これがシンボル files の場合、"FILE_NAME" が x-begin-drag
に指定されたターゲットのいずれかである場合にのみ、OffiXプロトコルが使用されます。それ以外の値は、サポートされているすべてのコンテンツをドロップする際にOffiXプロトコルを使用することを意味します。
x-begin-drag に指定されたリストに "STRING"、"UTF8_STRING"、"COMPOUND_TEXT"、または "TEXT"
のいずれかのターゲットが含まれている場合、ドロップターゲットがドラッグ&ドロッププロトコルを一切サポートしていないなら、Emacs
は合成マウスイベントとプライマリセレクションを用いてテキストを挿入しようとします。
副作用として、このようなドロップを行うと Emacs がプライマリセレクションの所有者になります。このエミュレーションは、この変数を nil に設定することで無効にできます。