しかしながら、X上には、標準とされるもがない為、さまざまなグループが自分達のプロトコルを開発して来ました。その結果、あるプロトコルの為に書かれたプログラムは、異なるプロトコルのプログラムとは、通信し合うことができません。DND により、ユーザーがあるプログラムから他のプログラムに、データをドラッグすることが出来るという基本的な必要条件を満していないことです。
全てのプログラムが DND によってデータを交換するために、誰もが使うことができる、たった一つのプロトコルに必要な事とは?(X Selectionのメカニズムは、クリップボード によってデータを交換することができることを保証します。)
このようなプロトコルの基本的な必要条件は、ドラッグ中、ユーザーに視覚的フィードバックを与えることであり、ソースが供給するあらゆるフォーマットから好ましいデータフォーマットを、ターゲットが選ぶことを可能にするものであります。それに加えて、視覚的フィードバックがユーザーのアクションに対して遅れないことです。これにより、デッドロック、レース・コンディション、そして非同期システムにあるその他の障害に対しても、安全を確保するのに効果的であります。
現在のバージョン: 4
最新更新日: 1999年6月7日
ターゲットは、カーソルがあり置かれるウィンドウで、もしマウスが解放されるならばドロップを受けウィンドウである。
あなたは Xlib マニュアル:Volume 0、Appendix L とVolume 1( Chapter 10 )に記述されているX Selection メカニズムに精通するべきであります。
全てのデータタイプとアクションは、それらのX Atoms に対応しているものとして照会される。 データタイプのアトム名は、全て小文字(Lower Case)のMIME タイプに対応している。(RFC の MIME 参照項:RFC's for MIME: 2045, 2046, 2047, 2048, 2049)
このドキュメントで述べられている全ての定数が、大文字で表されているXアトムのストリング名であるハードコーディング値の必要性を回避し、グローバル・レジストリーを要求します。
Step 0:
XdndAwareウィンドウ・プロパティを作成することで、.XDND プロトコルをサポートすることをウィンドウがアナウンスする。
Step 1:
マウスが XDND をサポートするウィンドウ内に入るとき(ウィンドウプロパティの引数8を捜す)、ソースは、ソースによってサポートされるデータタイプと、使用するプロトコル・バージョンを含むタイプ XdndEnter型(2)のClientMessage を送る。
拡張機能 は、他のウィンドウへのドロップを許可すために開発された。
Step 2:
ターゲットは、 XdndEnter を受ける。.
ClientMessage には、3データタイプだけの余地がある。ソースが、これ以上のものをサポートすならば、ターゲットは、利用可能なタイプのリストを得るために、ソースウィンドウからXdndTypeList のプロパティを取り戻さなければならない。(2)
Step 3:
ソースは、XdndPosition タイプのClientMessage を送る。(2) ユーザーがリクエストしたアクションとマウスの位置をターゲットに知らせる。
Step 4:
ターゲットは、 XdndPosition を受ける。
ターゲットウィンドウは、マウスがどのウィジェットにいるかを、決定しなければならない。そして、それがドロップをを受けるかどうか問い合わすさなければならない。効率的には、ターゲットウィンドウがウィジェットがドロップを受けるかどうかだけでなく、アクションが変更されたか、マウスが別のウィンドウへ移動したかを監視しなければならない。アクションが同じであり、マウスが同じ領域に留まり、ウィジェットが XdndPosition メッセージを受け、ウィジェットがドロップを受け付ける時、それが適切であるならば、ユーザーにデータが挿入されたことを示し、再描画される。
ドロップを受け付けるかどうかを決定するには、ターゲットウィンドウは、 XdndEnter メッセージからタイプのリストと、XdndPosition メッセージからの要求されたアクションを調べる。
要求されたアクションを実行出来ない場合、XdndActionCopy か、XdndActionPrivate のどちらかを、返すことが可能。
データ自身を見る必要が無いのであれば、XdndSelection の関係するデータタイプと、与えられたタイム・スタンプに対する XConvertSelection()を呼ぶ(7)。もし必要であるならば、一度だけでなく、これを実行可能。.
もし、それがドロップを受けることができるのであれば、ボーダーをハイライトして、ユーザに知らせるべきだ。データを取り戻す場合は、一旦、退避しておく。実際のドロップが起こる時、それを再び取り戻す必要はない。
Step 5:
ターゲットが、XdndStatus 型の ClientMessage を送る。(2)ソースにドロップを受けるかどうか伝える。受けるのであれば、そのアクションが開始する。"マウスがここから移動するまでは、他の XdndPosition メッセージを送らない"と言う意味の長方形(短形領域)のデータを含む。
Step 6:
ソースは、XdndStatus を受ける。ユーザーの要求するアクションが実行されたかどうかを示すために、カーソルを変えることが可能である。
マウスが与えられた長方形の範囲から移動すとき、 Step 3に行く。
XdndPosition メッセージは、通常は MotionNotify イベントが引き金となる。しかし、ソースが、XdndStatus
を待つ間、マウスが移動するならば、ソースには新しいマウス位置を退避し、XdndStatusメッセージを受けるやいなや、
別の XdndPositionメッセージ を生み出す。(サーバー-ターゲット間のコネクションが、サーバー-ソース間のコネクションより遅い場合、必要である)
Step 7:
もしマウスが、ウインドウから離れた場合、ソースは、XdndLeave 型のClientMessage を送る。(2)
もしマウスボタンが、ウィンドウ内で放された場合、ソースは、最後の XdndStatusメッセージを待ち、(もし必要であるならば)その時、最後の XdndStatus の"accept"フラグに依存する XdndLeave型か、XdndDrop型の ClientMessage を送る。(2)
もしソースがどんな XdndStatus メッセージも受けないならば、それは待つことなしに XdndLeave を送るべきである。
もしソースが、適切な時間の範囲内で XdndStatus を受けないならば、XdndLeave を送るべきである。XdndStatus を待つ間、ソースはブロックすることが可能である。少なくともSelectionRequest イベントを処理しなければならない。それにより、ターゲットがデータを調べることが出来る。
Step 8:
もしターゲットが XdndLeave を受けるならば、退避したデータを開放し、全てのイベントを放棄する。
もしターゲットが XdndDrop を受けて、それを受け付けるならば、最初に、与えられたタイムスタンプを使うデータを取り戻す為に、XConvertSelection()を使用する。(7)その時、最後のアクションに関連したデータと XdndStatus によ認識されたマウスの位置を使う(遅いネットワーク上でも、ドロップロケーションが、ユーザーに与えられた視覚的なフィードバックと一致する)。
もしターゲットが XdndDrop を受けて、それを受け付けないならば、XdndFinished を送って、XdndLeave のようにそれを扱う。
プロパティーは、余分なフィルターとして働くことができる。技術の詳細(Technical Details)セクションで説明されている、ターゲットによって受けられたタイプのリストを持つことができるからである。
他の DND プロトコルと共存するのためにも(もし XdndAware が無ければ、何か別のものを試みるだろうが)それがスクロールすることも重大でもある( 下記、注意セクションを参照)。XdndStatus メッセージを受けるのを予期することができるので、ターゲットの XDND のバージョンをチェックし、デバッグするのに役立つ。
XdndSelection を使うことによって、ドロップされたデータは、XA_PRIMARY に蓄えられたクリップボードデータと干渉しなくなる。
XConvertSelection()を使うことで、データ転送が終わる前に、ユーザーが、何かをドラッグ開始することができてしまう問題がある。しかし、Xクリップボードも同じ問題がある。これよって、ユーザーにどのような特別な制約も課さない。これは、XdndFinished メッセージの議論での説明で避けられる。
特別なアクション XdndActionAsk が、ドロップの発生後に行なうことを、ユーザーに尋ねるべきであるとターゲットに伝える。ファイルマネージャーがユーザーに移動、コピー、リンクの作成、キャンセルかを尋ねる、 Windows95 の右ボタン・ドラッグにより影響を与えられた実装するものです。アクションのリストは、XdndActionList プロパティより取り戻され、ユーザーに表示される、それぞれのアクションの内容は、両方のソースウィンドウ上で、 XdndActionDescription プロパティから戻される。
特別なアクション XdndActionPrivate が、ターゲットが、ソースに理解できないことをすると、ソースに伝える。それはデータのコピーのほかにソースからどんなものも必要としない。
XdndPosition メッセージは、マウス・ロケーションを与えるので、自身を正確に再描画する為に、ターゲットがXサーバーに尋ねる必要がない。ターゲットがマウスロケーションを得るのために、他の信頼できる方法はない。何故なら、Xが、カーソルをソースウィンドウにより捕まえ、それにより、ソースウィンドウだけが、イベントを受ける。ターゲットは、マウスロケーションを必要とする。これは、どこにデータが挿入されたかを見せる為に、自身を更新しなければならない。テキストエディタ、スプレッドシート、ファイルマネージャには、特に重要である。
XdndPosition メッセージのタイムスタンプは、正しいデータが受け取られたか確認するために、XConvertSelection() へ渡されなければならない。
XdndStatus メッセージがソースへフィードバックを与えて(カーソルを変えてほしいと思うかもしれない )、ネットワークの接続が遅いとき、 XdndPosition メッセージが、積み重ならない事を確認する。
XdndLeave メッセージは、セッションを取り消す。
XdndDrop メッセージは、ターゲットにドロップを処理することを伝える。タイムスタンプは、正しいデータが受けられることを確認する為に、XConvertSelection()に渡られなければならない。
XdndFinished メッセージは、ターゲットが終了し、もうデータは必要ないことをソースに伝える。これは、ソースに、3種類の異なる振る舞いの内、1つを実行することを許す;
ソースとターゲットがお互いに XDND メッセージを受け取えり合っている間、他のウィンドウからの全ての XDND メッセージを無視するべきである。
もしDND がアクティブで、どちらかのアプリケーションがクラッシュするならば、他のアプリケーションは、BadWindow error の衝突を避けなければならない。これを行なう安全な方法が、XSetErrorHandler()によるエラー・ハンドラーをインストールすることにより、実際のエラーを捕えることである。加えて、ターゲットはソースが、XdndStatus 受け側と XdndPosition 送信側の両方で衝突するならば、他の XdndPosition を永遠に待つことがない DestroyNotify イベントも聞かなければならない。
我々が DND がどのようなケースで働くということを示すために、サンプルを集めています。テキストのドラッグは、容易である。それは、text/plain と text/enriched を含み、良く知られたフォーマットであるからだ。ファイルをドラッグすることは、少なくと同様に重要である。
我々は、ルートウィンドウ、そして、XDND をサポートしないウィンドウ.へのドロップするのを許すような、拡張機能を開発しました。
XdndActionLink が、唯一、一つのプログラムの範囲内、或いは、協力し合うプログラム間で意味をなす。それは、ターゲットがデータだけでなく、データのロケーションも得らなければならないからである。他のケースとして、ターゲットは、XdndStatus メッセージ中の XdndActionCopy か XdndActionPrivate に、反応しなければならない。
もう一方方では、XdndActionAsk は、無関係なプログラムと協力し合うプログラムとの間で、同等の理解をする。しかしながらソースとターゲットが無関係であるとき、ターゲットは、アクション・リストをソースに頼む代わりに、データを取り戻すした後、自身で実行可能なアクション・リストを供給することを選ぶかもしれない。
マウス・ドラッグを失敗することも覚えておいて下さい。もしユーザーが、何かを選ぶためにクリックしている間、単に数ピクセル位置をずらし、マウスを動かしてしまうのであれば、そのユーザーは、多分、少し無器用だということです。3 ピクセル境界値は,一般的です。
このプロトコルを実行している間、サーバーが知っている全てのアトムをリストするめのプログラム xlsatoms 、及び、特定のウィンドウの全プロパティをリストするプログラム xprop を使って、これらが非常に役立つのを気づかれるでしょう。
わたしの意見:..
わたしの意見では、ドラッグ中にプログラムがカーソルを変えるべきではありません。最も一貫したイメージを、ユーザーに与えるからです。現在、ターゲットがそれを受け付けるかどうかに関わらず、ユーザーがデータをドラッグします。ドロップを受けるかどうか示す為に、変えるべきなのは、ターゲットです。
しかしながら、あなたが Microsoft に盲従したいと思うならば、カーソルを変えるべきです。たいていの場合、Microsoftは遅れています。.
Alan Cooperの本"About Face"のページ 253 の注釈には心から意見が一致します。
わたしが支持するたった一つの例外が、リクエストされたアクションが実行されるのを示すために、カーソルに小さいシンボルを加えることです。(XdndActionPrivateの代わり)例として、ドラッグ・ファイルのページを参照のこと。
上記ケースでは、XConvertSelection()を呼ぶのを避ける:
マウスが静止してる時、XdndPosition メッセージを送ることは意味がない。
ソースからサーバーへの不必要なメッセージを避けるには、ターゲット、或いはステータス(受け入れとアクション)が変更した時に、カーソルを変えるべきだ。
不幸にも、オーバーラップ・ウィンドウの為に連続的に XTranslateCoordinates() を呼ぶことを避けることができない。
下記に述べた全ての定数が、Xアトムのストリング名前であり、大文字で示す。グロ−バル・レジストリーを要求するハードコート値の必要を避ける。.
このウィンドウ・プロパティが、 XA_ATOM タイプに属しなければならなく、ターゲットによってサポートさてる最も高いバージョン・ナンバーのプロトコルを含まなければならない。(バージョン・ナンバーは、0から始まり、最大のバージョンナンバー0xFF である。何故なら、この為に、XdndEnter message 中に、たった1バイトを割り当てるだけで済むからである。3ヶ月毎に、1つ新しいバージョンへ変更しても64年はもつであろう。)
プロパティは、ドロップを受けることが可能なウィジェットを含む、各々のトップ-レベルXウィンドウに置かれなければならない(バージョン3が最新)。プロパティは、サブウィンドウに置かれるべきでない。ターゲットがメッセージを適切なウィジェットに派遣されなければならない。ウィンドウマネージャが、しばしウィンドウの余分なレイヤーを挿入する為、XTranslateCoordinates()を使って、サブウィンドウ・ツリーの階層下から捜すことを必要とする。
XdndSelection
これは、ターゲットがドラッグの段階でのデータを調べたい時、又は、いつドロップの後にデータを取り戻したいかと言う時に使われたX Selection の名前である。
全てのデータタイプは、X Atoms に対応して参照される。アトム名は、全て小文字の MIME types に対応している. (RFC の MIME: 2045, 2046, 2047, 2048, 2049)
テキストのために、キャラクターセット(charset)属性が、MIME タイプに付け加えられる。(日本語 => text/plain;charset=iso2022-jp ) charset 属性が、詳細に述べられない場合、iso8859-1 が想定される(バージョン4より)
どんなデータ・タイプも、INCR プロトコルによって転送されるかもしれないので注意が必要。
XdndTypeList
もしソースが少なくとも3つのデータタイプをサポートするならば、このウィンドウ・プロパティは、ソースウィンドウ上に設定され、XA_ATOM タイプに属し、サポートされたる全てのデータタイプのリストを含まなければならない。
アクション (バージョン2より)
全てのアクションは、X Atoms に対応して参照される。定義されているアクションは
定義されているアトムは、アクションとして許されない。デフォルトは、 XdndActionCopy であり、これはバージョン 0 か1を使っているときのアクションとしてみなされる。
一般的には、XdndActionMove が最初にデータをリクエストすることで実行され、そして、特別なターゲット DELETE がX Selection protocol を定義する。(ファイル・マネージャーは、明らかに私のものか、或いは同等のものを使用するだろう)
詳しい情報は、理論と注意のセクションを参照のこと。
XdndActionList (バージョン2より)
もしソースが XdndActionAsk を送るならば、このウィンドウ・プロパティは、ソースウィンドウ上に設定され、XA_ATOM タイプに属し、サポートされたる全てのデータタイプのリストを含まなければならない。最初のものが、デフォルトであるべきであり、ユーザーが、しばしばラジオグループ中の選択を変えないようにする。
XdndActionDescription (バージョン2より)
もしソースが XdndActionAsk を送るならば、このウィンドウ・プロパティは、ソースウィンドウ上に設定され、XA_STRING タイプに属し、ターゲットがユーザーに選択を描写する時に表示すべき、全てNULL によって分けられたASCII ストリングのリストを含まなければならない。これらのストリングは、 XdndActionList プロパティのアトムと同じ命令にならなければならない。
操作を取り消す選択は、Cancel ボタンによって、常にユーザーにダイアログを表示して与えられなければならない。XdndActionList に含めるべきではない。
XdndProxy (バージョン4より)
もしこのウィンドウ・プロパティが存在するならば、XA_WINDOW タイプに属し、XdndAware をチェックすべき代理ウィンドウの ID を含むべきであり、そして、全てのクライアント・メッセージを受けなければならない。代理ウィンドウが正しくふるまうために、クライアント・メッセージの適切フィールド、ウィンドウ、データ、l [ 0 ] 等は、代理ウィンドウがメッセージを受けるのではなく、マウスが位置するウィンドウの ID を含まなければならない。代理ウィンドウが使われるべき唯一の場所は、XSendEvent()を呼ぶ時や、XdndAware をチェックしている時である。
代理ウィンドウは、XdndProxy プロパティのポインタを自分自身に設定しなければならない。もし代理ウィンドウが存在しないのであれば、クラッシュ後に残っていると仮定して、 XdndProxy を無視すべきである。
XdndEnter
マウスが XDND をサポートするウィンドウに入るとき、ソースからターゲットへ送られる。
ソースが少なくとも3つのデータタイプをサポートするならば、ビット 0のデータ l [ 1 ] はセットされる。これは、ターゲットに利用可能なタイプのリストのためのソース・ウィンドウの上のXdndTypeList プロパティをチェックするように伝えるものだ。
ソースからターゲットへマウスロケーションを与えるために送る。
ドロップが受けられたかどうかのフィードバックを与えるためにソースからターゲットへ送る。もしそうであれば、どんなアクションが取られるか:
ドロップを取り消すためにソースからターゲットへ送る。
ドロップを完了するためにソースからターゲットへ送る。
もはやターゲットが、データをアクセスする必要がない為、ソースがデータを投げることができることを示すためにターゲットからソースへ送る。
Paul Sheer は、汎用ライブラリをして、Cで XDND v2 を実装しました。 xdnd.c と xdnd.h のファイルです。
もしあなたが異なる言語を使うのであれば、他の人があなたのコードを見易いように、心がけてください。
正規の実装とあなたの実装とのテストを行なう為に使用するバイナリがあります。
たとえあなたが、無から XDND を実装するとしても、もしあなたの配布時、また、このウェブページへの参照と、このプロトコルをサポートしているとはっきりと述べた文章を添付して頂ければ幸いです。同じプロトコルをサポートするプログラムが増えれば、ユーザーにとって、ドラッグ・アンド・ドロップは、より有用なものとなるでしょう。あなたが、このプロトコルをサポートすることを伝えて下されば、サポーター・リストにあなたを加えます。.
バージョン4では、ルートウィンドウへのドロップに対する新しいプロトコルをサポートする為、 XdndProxy ウィンドウ・プロパティを追加。December 1, 1998:最新の実装に対応するために、ルートウィンドウへののドロップ に対するプロトコルを書き直す。
どのようにテキストのキャラクターセットを指定するかについて、"技術の詳細"セクション中に注釈を加える。
XDND のレイヤー上に、Direct Save (XDS) プロトコルを作成。
最新の実装に対応するために、ルートウィンドウへののドロップ に対するプロトコルを書き直す。September 19, 1998:
File Dragging protocol は、url/url の代わりに、確立された text/uri-list を使う。September 7, 1998:ウィンドウ・スタックの退避について、 "最適化" セクションに注釈を追加
バージョン3にて、XdndAware が ハンドルされる方法を変更。Xサーバーへの XTranslateCoordinates() コールの回数を減らすために、又、ウィジェットにつきマルチXウィンドウを使うプログラムにとってより生存し易いように、XdndAware は、サブウィンドウではなく、トップ-レベルXウィンドウに置かれなければならない。この変更は、不幸にも、前のバージョンとの互換性がありません。 XDND をサポートするプログラムが比較的少ない為、このスペックは、単に調整されだけであり、XDND の使用は、バージョン3以上のサポートを要求されます。( 再び起こりません!)August 17, 1998:それに加えて、Jeroen van der Zijp が、XDND をサポートしないウィンドウへのドロップを可能とする 拡張機能 を発明しました。そして Arnt Gulbrandsen は、ルートウィンドウへのドロップ方法を開発しました。
バージョン2は、次の機能を追加:February 25, 1998:これらの新しい機能により、File Dragging protocol は、より単純になる。
- 以前、アクションの概念は、コピーだけのサポートであったが、今回、ソースは、どの様なアクションも指定可能であり、ターゲットがそれを受けるたり、コピーもしくは、private を利用すことができる。予め定義されてるアクションは、XdndActionCopy(デフォルト)、 XdndActionMove、XdndActionLink、XdndActionAsk、XdndActionPrivateである。Ask がソースのXdndActionList と XdndActionDescription ウィンドウから許容可能なアクション・リストを得るために、ターゲットに伝え、それでユーザーに、どれを実行するか尋ねます。
- ターゲットは、 XdndFinished を送ることを要求される(降参しました)。しかし、もしソースがブロックするならば、ターゲットがうまく機能しない場合の時間に対する準備をしなければならない。理想的には、ソースが、さえぎる必要がないだろう。何故なら、ソースが、過去の選択履歴を保持するからである。それが XdndDrop 中の タイムスタンプが、時間遅れのリクエストだけを拒絶することによって、履歴を保持したり、ブロックする事を安全に避けるように、ソースにさせる。
XdndFinished を付け加えることの理由は、操作の終わりに通知を要求する、XDND がより高水準 API (たとえば、JavaBeans等)に使われるのを可能にするためである。支持者 のページを追加.。
協力し合うアプリケーションでの大きな画像ファイルを、XDND がどの様に適用するか、サンプル を追加。February 24, 1998:
File Dragging protocolへ、ゴミ場箱についての議論を追加。February 2, 1998:
バージョン 0 に穴がありました。ユーザーが、データを最初のターゲットへ移す前に、同じソースから、次のドラッグを開始する場合(明らかに遅いネットワーク上でのことですが)、最初のターゲットは、違ったデータを受け取ってしまう場合があります。この指摘をして下さった、Donal K. Fellows に感謝します。January 28, 1998:バージョン1は、データをリクエストする時使われるXdndPosition と XdndDrop にタイムスタンプを加えることによって修正しました。この方法では、もしユーザーが素早く2番目のドラッグを始めるならば、最初のターゲットは、少なくとも間違ったデータの代わりに、どんなデータも受け取りません。
より完全な理論については、何故、"ドロップは、終えた"のメッセージを加えて修正しないかの理由に対しては、理論のセクションを参照して下さい。
Xdeとの比較を追加