ページ 11

sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年6月29日(火) 00:27
by rk
sendMouseEventでマウスクリックイベントを起こしたいのですが思ったような動作をしません。
Firefoxのツールバーなどのボタンを押したりはできるようなのですが、座標をwebページ中にすると効果がありません(リンクなどのクリック対象に座標を合わせても反応が無い)。

sendMouseEventはwebページに対してイベントを起こすことは出来ないのでしょうか?

環境
os:xp
Firefox:3.6.4

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年6月29日(火) 02:16
by Piro

コード: 全て選択

var utils = window
                  .QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIDOMWindowUtils);
でnsIDOMWindowUtilsインターフェースのユーティリティを取得できますが、このユーティリティのイベント発行系の機能は基本的に、そのウィンドウ(フレーム)自身に対してしか働きません。ブラウズ領域はインラインフレーム扱いなので、トップレベルのウィンドウではなくそのフレームのnsIDOMWindowUtilsインターフェースのユーティリティを取得する必要があります。
例えばマウス系のイベントから対応するフレームのユーティリティを取得するなら、こんな感じでしょうか。

コード: 全て選択

var utils = event.originalTarget.ownerDocument.defaultView
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIDOMWindowUtils);
座標ベースなら、document.elementFromPointを使う事になると思います。

コード: 全て選択

var view = window;
while (true) {
   let target = view.document.elementFromPoint(x, y);
   if (target.localName.match(/^(iframe|frame|browser|tabbrowser)$/)
     view = target.contentWindow;
   else
     break;
}
var utils = view.QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIDOMWindowUtils);
これは省略した例なので、実際にはx, yのズレやら何やらを計算しないといけませんが。

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年6月29日(火) 12:32
by Masayuki
何がしたいのか分かりませんが、普通にDOMイベントを生成し、狙いの要素にdispatchするのでは実現できませんか? また、やりたいことを直接実行できるAPIはありませんか?

nsIDOMWindowUtilsは自動テストでの利用を主に想定していて、拡張での利用すら想定されていませんので他のAPIよりもより一層、unstableです。そのため、利用は極力避けた方が賢明です。

また、普通のDOMイベントを弾く、セキュリティ的に問題があるイベントハンドラもこれらのAPI経由で生成されたネイティブイベントは処理してしまいます(ここをテストするためのAPIなため)。つまり、セキュリティリスクが大きいものです。

ちなみに利用するにあたってはどこからどこまでが一つのnsIWidgetであるのかを理解しておかなくてはいけません(これがバージョンごとに変わっているのですが)。
ブラウズ領域はインラインフレーム扱いなので、トップレベルのウィンドウではなくそのフレームのnsIDOMWindowUtilsインターフェースのユーティリティを取得する必要があります。
この部分も今は真ですが、そのうち偽になります。

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年6月30日(水) 00:08
by rk
Piroさん、Masayukiさん、お返事ありがとうございます。
やりたいことはFlashゲーム上の指定した座標でマウスクリックを行うというものです。
DOMイベントを生成してdispatchするという方法だと、以下のような方法になるのでしょうか?

var view = window;
let target = view.document.elementFromPoint(x, y);
view = target.contentWindow;

var e = document.createEvent('MouseEvents');
e.initMouseEvent("click",true,true,window,1,10,50,10,50,0,0,0,0,1,null);
view.dispatchEvent(e);

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年8月10日(火) 13:46
by Masayuki
rk さんが書きました:DOMイベントを生成してdispatchするという方法だと、以下のような方法になるのでしょうか?

var view = window;
let target = view.document.elementFromPoint(x, y);
view = target.contentWindow;

var e = document.createEvent('MouseEvents');
e.initMouseEvent("click",true,true,window,1,10,50,10,50,0,0,0,0,1,null);
view.dispatchEvent(e);
Yes.

http://mxr.mozilla.org/mozilla-central/ ... et.idl#106

target.dispatchEvent(e);の方がスマートかも。

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年8月22日(日) 23:09
by rk
上手くいきました。 ありがとうございます。

ところで、initMouseEventはスクリーン・クライアント座標を引数にとっていますが、これに値を入れても機能していないようにみえるのですがどのように使うのでしょうか(座標はelementFromPointのみに依存して機能しているようです)。 

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年8月23日(月) 15:57
by Masayuki
rk さんが書きました:上手くいきました。 ありがとうございます。

ところで、initMouseEventはスクリーン・クライアント座標を引数にとっていますが、これに値を入れても機能していないようにみえるのですがどのように使うのでしょうか(座標はelementFromPointのみに依存して機能しているようです)。 
各イベントのプロパティに反映されていませんか?

イベントが発生する要素を自動的に選択してほしい、というのであれば、そのようには使えません。dispatchEvent()は文字通り、そのイベントをそのDOMEventTargetに対して送信するものであって、本物のイベントをエミュレートする訳ではありません。これが、nsIDOMWindowUtilsのSend*()との大きな違いです。

Re: sendMouseEventによるイベントシミュレートの効果範囲

Posted: 2010年9月11日(土) 05:52
by rk
Masayuki さんが書きました:dispatchEvent()は文字通り、そのイベントをそのDOMEventTargetに対して送信するものであって、本物のイベントをエミュレートする訳ではありません。これが、nsIDOMWindowUtilsのSend*()との大きな違いです。
分かりました。 ありがとございます。