ドラッグアンドドロップで転送されるデータは、プレーンテキストかファイルやその他のリソースを示すURLのリストであることが一般的です。テキストをドロップするとドロップした場所にテキストが挿入されますが、それが不可能ならリソースはkillリングに保存されます。
ドロップされたURLは変数dnd-protocol-alist
内の適切なDNDハンドラー関数(DND handler
functions)、または変数browse-url-handlers
とbrowse-url-default-handlers
に設定された“URLハンドラー”に提供されます。いずれのタイプのハンドラーにもマッチが存在しなければプレーンテキストとみなされてバッファーに挿入されます。
この変数はURLをマッチさせるregexp、およびマッチしたURLのドロップ時に呼び出されるDNDハンドラー関数からなるalist。
ハンドラー関数がdnd-multiple-handler
プロパティがセットされたシンボル(シンボルのプロパティを参照)の場合には、ドロップ時にはそのregexpにマッチするすべての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ハンドラー関数への転送など)とリクエストされた選択データタイプからなるコンスのいずれかをリターンしなければならない。このコンスでリターンされるアクションはシンボル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"
のようなlMIMEのタイプ名(“utf-8”の大文字小文字が異なる)から、UTF8_STRING
のような標準的なXの選択名への置き換えです。
XDSプロトコル(X Direct Save Protocol)により、プログラムがドロップするファイルにたいする命名責任を受信者に委譲することが可能になります。このようなドロップが発生すると、ドロップに応答するために別の関数が用いられて、DNDハンドラーおよび前述したX固有のインターフェイスの大部分が回避されます。
この変数nはXDSプロトコルを用いて2ステップの手続きを経て、ドロップされたファイルの登録と命名を行う関数をセットすること。この関数はneed-name、filenameという2つの引数を受け取る。
nil
、2つ目の引数filenameに保存するファイルのディレクトリー部分を除いた名前をセットしてdirect-save関数が呼び出される。この関数はファイルを保存するための完全に展開された絶対ファイル名をリターンする必要がある。たとえばDiredウィンドウにファイルがドラッグされれば、そのファイルのディレクトリーは当然ドロップされた場所に表示されているファイルのディレクトリーになるだろう。何らかの理由によりファイルの保存が不可能な場合には、この関数はドラッグアンドドロップ操作をキャンセルするnil
をリターンする必要がある。
nil
、2つ目の引数filenameに保存したファイルの完全な絶対ファイル名をセットして、もう一度direct-save関数を呼び出す。この関数にはファイルが保存されたという事実に鑑み、何であれ必要な処理を行うことが期待される。たとえばDiredならそこに新たなファイルを表示して、ディスプレイ上のディレクトリーを更新する必要があるだろう。
デフォルトのx-dnd-direct-save-function
はx-dnd-save-direct
。
引数need-nameが非nil
で呼び出されると、この関数はファイルを保存するためにユーザーに絶対ファイル名の入力を求める。指定されたファイルがすでに存在する場合には、上書きするかどうかの入力をユーザーに追加で求めて、ユーザーが上書きに同意した場合のみ絶対ファイル名をリターンする。
引数need-nameがnil
で呼び出された際には、カレントバッファーがDiredモード、あるいはDiredを継承する子孫の場合にはDiredの一覧リストをリバート、それ以外の場合にはfind-file
(ファイルをvisitする関数を参照)を呼び出してそのファイルをvisitする。
この関数はx-dnd-save-direct
と同様に機能するが、引数need-nameが非nil
で呼び出されても、ファイルを保存するための完全なファイル名の入力をユーザーに求めずに、カレントバッファーのデフォルトディレクトリーにたいしてfilename引数を展開してリターンする(デフォルトディレクトリーにその名前のファイルが既に存在する場合に確認を求めるのは変わらず)。
カレントのウィンドウシステムでサポートされていれば、Emacsから他のプログラムへのコンテンツのドラッグも可能です。以下はこのために提供される関数です:
関数はframeから別のアプリケーション(ドロップターゲットと呼ばれる)へのfileのドラッグアンドドロップを開始して、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がファイルのリストである点が異なる。ドロップターゲットが複数ファイルのドロップをサポートしていなければ、かわりに1つ目のファイルが使用される。
この関数の挙動は(デフォルトのアクションcopy
を使用した際は)dnd-begin-file-drag
と似ているが、実際にコピーする際に名前を受け付ける点が異なる。
上述した高レベルのインターフェイスは、低レベルなプリミティブの上位に実装されています。低レベルのインターフェイスx-begin-drag
はテキストやファイル以外のコンテンツのドラッグにも利用できます。これには呼び出し側がサポートしたいプラットフォームそれぞれにおいて、プログラムが理解できるデータタイプおよびアクションにたいする詳細な知識が必要でしょう。
この関数はframeからのドラッグを開始して、そのドラッグアンドドロップがドロップに成功するか、あるいは拒絶されたかのいずれにより操作終了したらリターンする。ドロップはframe以外のトップレベルのXウィンドウ(ドロップターゲット、allow-current-frameが非nil
なら任意のXウィンドウ)の上でマウスボタンがリリースされた際に発生する。そのドラッグアンドドロップ操作の開始時にどのマウスボタンも押されていなければ、この関数は即座にnil
をリターンする。
targetsはgui-get-selection
のdata-type引数のような、選択されているターゲットを表す文字列のリストであり、ドロップターゲットがEmacsに要求する可能性がある(ウィンドウシステムによる選択を参照)。
actionはターゲットに推奨されているアクションを示すシンボル。XdndActionCopy
かXdndActionMove
のいずれか。どちらも選択コンテンツのコピーをコピーを暗に示し、XdndSelection
はドロップターゲットへのコピーだが、後者はさらにコピー後に選択コンテンツの削除を指示する。
利用できるアクションを表すシンボル、およびユーザーにそれらのアクションを選択させる際に提示する文字列との連想を示すalistでもよい。
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
なら、x-begin-drag
によって与えられたターゲットのいずれかが"FILE_NAME"
の場合のみOffiXプロトコルが使用される。それ以外の値の場合には、サポートされているコンテンツのドロップにOffiXプロトコルが使用される。
x-begin-drag
によって与えられたリスト内に"STRING"
、"UTF8_STRING"
、"COMPOUND_TEXT"
、"TEXT"
のいずれかのターゲットがあれば、ドロップターゲットが何もドラッグアンドドロップのプロトコルをサポートしていなくても、Emacsは合成されたマウスイベントとプライマリー選択を用いてテキストの挿入を試みる。
そのようなドロップにおいては、Emacsがそのプライマリー選択の所有者になるという副作用がある。この変数をnil
にセットすれば、このようなエミュレーションを無効にできる。