右クリックメニューの実装(1) 表示編
はい。これを実装したのみなはもうちょい待ち。
メモだけ。
右クリックというイベントの取得
これは、nsIContextMenuListener2で取得します。
…いや、nsIContextMenuListenerでもいいのですが、2のほうが便利なので。
具体的に…はめんどくさいので、これを実装したChromeを作成すると思ってください。
たとえば、こんなかんじ
NS_IMETHODIMP nmnWebBrowserChrome::OnShowContextMenu(PRUint32 aContextFlags, nsIContextMenuInfo *aUtils) { //ほげほげ return 0; }
…なにがなんだかわかりませんが、まあ、これから。
#ちなみに、nsIDOMEventListenerで取得するのもアリだとは思います。が、僕にはわかりません。
aContextFlagsの中の人
CONTEXT_LINK | <A> |
CONTEXT_IMAGE | <IMG> |
CONTEXT_IMAGE CONTEXT_LINK | <IMG> with <A> as an ancestor |
CONTEXT_INPUT | <INPUT> |
CONTEXT_INPUT CONTEXT_IMAGE | <INPUT> with type=image |
CONTEXT_TEXT | <TEXTAREA> |
CONTEXT_DOCUMENT | <HTML> |
CONTEXT_BACKGROUND_IMAGE | <HTML> with background image |
そう、clickされたのの組み合わせなのです。
nsIContextMenuInfoの中の人
ざっと、こんな感じ。
- GetMouseEvent(nsIDOMEvent * *aMouseEvent)
- GetTargetNode(nsIDOMNode * *aTargetNode)
- GetAssociatedLink(nsAString & aAssociatedLink)
- GetImageContainer(imgIContainer * *aImageContainer)
- GetImageSrc(nsIURI * *aImageSrc)
- GetBackgroundImageContainer(imgIContainer * *aBackgroundImageContainer)
- GetBackgroundImageSrc(nsIURI * *aBackgroundImageSrc)
…よくわかんないのもありますが、とりあえず、いろいろできそうです。
選択範囲がclickされたかどうかを調べる
そう、ここまでで気づいた方もいらっしゃると思うのですが、
選択範囲がclickされたかどうかはこれからはわからないのです。
どうするか。
ちょっと煩雑ですが、こんなふうにする…っぽいです。
- nsIContextMenuInfo::GetTargetNode(nsIDOMNode**)でclickされたDOMNodeを取得
- nsIDOMNode::GetOwnerDocument(nsIDOMDocument**)で、そのDOMNodeの親のDOMDocumentを取得
- そのnsIDOMDocumentを、nsIDOMDocumentViewにcast
- nsIDOMDocumentView::GetDefaultViewer(nsIDOMAbstractViewer**)で、そのDOMDocumentのViewerを取得
- nsIDOMAbstractViewerをnsIDOMWindowにcast
- nsIDOMWindow::GetSelection(nsISelection**)で、そのDOMWindow内の選択範囲を取得
- nsISelection::ContainsNode(nsIDOMNode*, PRBool, PRBool*)で、最初のDOMNodeが選択範囲にあるかどうかを調べる
…疲れましたね。
はい、26時の脳味噌にはとっても辛いです。
ここまでくれば自明だとは思いますが、一応、sampleを載せておきます。
//* 選択範囲を右clickしたかどうかを調べる // * nsIContextMenuListener2::OnShowContextMenu()内 // * なので、nsIContextMenuInfo* aUtilsをもらっているとする nsCOMPtr<nsIDOMNode> domNode; aUtils->GetTargetNode(getter_AddRefs(domNode)); if (domNode) { nsCOMPtr<nsIDOMDocument> domDocument; domNode->GetOwnerDocument(getter_AddRefs(domDocument)); nsCOMPtr<nsIDOMDocumentView> domDocumentView = do_QueryInterface(domDocument); if (domDocumentView) { nsCOMPtr<nsIDOMAbstractView> domAbstractView; domDocumentView->GetDefaultView(getter_AddRefs(domAbstractView)); nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(domAbstractView); if (domWindow) { nsCOMPtr<nsISelection> selection; domWindow->GetSelection(getter_AddRefs(selection)); if (selection) { PRBool contains; selection->ContainsNode(domNode, PR_TRUE, &contains); if (contains == PR_TRUE) { //選択範囲です } } } } }
と、ここまででなにがclickされたかはわかると思いますので…
あとは、win32APIなりC#なりGtkなりお好きな方法で、ポップアップメニューを表示します。
そのあと、選択範囲をほげったり、いろいろしたりするのは、また明日。
Reference
- Bagel 0.xのsrc
- K-Meleon1.02のsrc
- DOMのdocumentについて
- Mozillaのsrcたち
- webbrwsr/nsIContextMenuListener2.h
- nsIDOMNode.h
- nsIDOMDocument.h
- nsIDOMDocumentView.h
- nsIDOMAbstractView.h
- nsIDOMWindow.h
- nsISelection.h