■
ProcessEventは
layout/generic/nsObjectFrame.cpp
にある。でもこれプラグイン用みたい。
~/mozilla/widget/public/nsGUIEvent.h
class nsEvent { ....... // See event struct types PRUint8 eventStructType; // See GUI MESSAGES, PRUint32 message; // In widget relative coordinates, not modified by layout code. nsPoint refPoint; // Elapsed time, in milliseconds, from a platform-specific zero time // to the time the message was created PRUint32 time; // Flags to hold event flow stage and capture/bubble cancellation // status. This is used also to indicate whether the event is trusted. PRUint32 flags; // Additional type info for user defined events nsCOMPtr<nsIAtom> userType; // Event targets, needed by DOM Events // Using nsISupports, not nsIDOMEventTarget because in some cases // nsIDOMEventTarget is implemented as a tearoff. nsCOMPtr<nsISupports> target; nsCOMPtr<nsISupports> currentTarget; nsCOMPtr<nsISupports> originalTarget; };
べつのスレッドにdispatchさせるのは可能そう。
だからやっぱりmEventCallbackを探る。
~/mozilla/xpfe/appshell/src/nsWebShellWindow.cpp
mWindow->SetClientData(this); mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget r, // Widget dimensions nsWebShellWindow::HandleEvent, // Event handler function nsnull, // Device context aShell, // Application shell nsnull, // nsIToolkit &widgetInitData); // Widget initialization data mWindow->GetClientBounds(r); mWindow->SetBackgroundColor(NS_RGB(192,192,192));
こっちが正しいみたい。
でもウインドウのリサイズとかの処理をしてるだけでキーイベントとか書いてない。
/* * Event handler function... * * This function is called to process events for the nsIWidget of the * nsWebShellWindow... */ nsEventStatus PR_CALLBACK nsWebShellWindow::HandleEvent(nsGUIEvent *aEvent) {
もっかいやりなおしかな.....
tools/tests/win32/inbox これみる。
~/mozilla/view/src/nsView.cpp
nsresult nsIView::CreateWidget(const nsIID &aWindowIID, nsWidgetInitData *aWidgetInitData, nsNativeWidget aNative, PRBool aEnableDragDrop, PRBool aResetVisibility, nsContentType aContentType) { ..... if (aNative) mWindow->Create(aNative, trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData); else {
こいつがCreateしてmEventCallbackを設定していると思われる。
// // Main events handler // nsEventStatus PR_CALLBACK HandleEvent(nsGUIEvent *aEvent) { //printf(" %d %d %d (%d,%d) \n", aEvent->widget, aEvent->widgetSupports, // aEvent->message, aEvent->point.x, aEvent->point.y); nsEventStatus result = nsEventStatus_eIgnore; nsView *view = nsView::GetViewFor(aEvent->widget); if (view) { view->GetViewManager()->DispatchEvent(aEvent, &result); } return result; }
おおお、これいかんじだ。
~/mozilla/view/src/nsViewManager.cpp
NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aStatus) { ........... default: { if ((NS_IS_MOUSE_EVENT(aEvent) && // Ignore moves that we synthesize. static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal && // Ignore mouse exit and enter (we'll get moves if the user // is really moving the mouse) since we get them when we // create and destroy widgets. aEvent->message != NS_MOUSE_EXIT && aEvent->message != NS_MOUSE_ENTER) || NS_IS_KEY_EVENT(aEvent) || NS_IS_IME_EVENT(aEvent)) { gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); }
時間はかってるだけ。まったく意味なし....
~/mozilla/layout/base/nsPresShell.cpp
NS_IMETHODIMP PresShell::HandleEvent(nsIView *aView, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { ......... } else { // Focus events need to be dispatched even if no frame was found, since // we don't want the focus controller to be out of sync. if (!NS_EVENT_NEEDS_FRAME(aEvent)) { mCurrentEventFrame = nsnull; return HandleEventInternal(aEvent, aView, aEventStatus); } else if (NS_IS_KEY_EVENT(aEvent)) { // Keypress events in new blank tabs should not be completely thrown away. // Retarget them -- the parent chrome shell might make use of them. return RetargetEventToParent(aEvent, aEventStatus); } }
nsresult PresShell::HandleEventInternal(nsEvent* aEvent, nsIView *aView, nsEventStatus* aStatus) { nsCOMPtr<nsIEventStateManager> manager = mPresContext->EventStateManager(); nsresult rv = NS_OK; // FIXME. If the event was reused, we need to clear the old target, // bug 329430 aEvent->target = nsnull; // 1. Give event to event manager for pre event state changes and // generation of synthetic events. rv = manager->PreHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView); // 2. Give event to the DOM for third party and JS use. if ((GetCurrentEventFrame()) && NS_SUCCEEDED(rv)) { // We want synthesized mouse moves to cause mouseover and mouseout // DOM events (PreHandleEvent above), but not mousemove DOM events. if (!IsSynthesizedMouseMove(aEvent)) { nsPresShellEventCB eventCB(this); if (mCurrentEventContent) { nsEventDispatcher::Dispatch(mCurrentEventContent, mPresContext, aEvent, nsnull, aStatus, &eventCB); } else { nsCOMPtr<nsIContent> targetContent; rv = mCurrentEventFrame->GetContentForEvent(mPresContext, aEvent, getter_AddRefs(targetContent)); if (NS_SUCCEEDED(rv) && targetContent) { nsEventDispatcher::Dispatch(targetContent, mPresContext, aEvent, nsnull, aStatus, &eventCB); } else if (mDocument) { nsEventDispatcher::Dispatch(mDocument, mPresContext, aEvent, nsnull, aStatus, nsnull); } } } // 3. Give event to event manager for post event state changes and // generation of synthetic events. if (NS_SUCCEEDED (rv) && (GetCurrentEventFrame() || !NS_EVENT_NEEDS_FRAME(aEvent))) { rv = manager->PostHandleEvent(mPresContext, aEvent, mCurrentEventFrame, aStatus, aView); } } }
あれ、これけっきょく直接イベントハンドラ呼ぶんだけど.....
と思ったら違うかも。
~/mozilla/content/events/src/nsEventStateManager.cpp
NS_IMETHODIMP nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext, nsEvent *aEvent, nsIFrame* aTargetFrame, nsEventStatus* aStatus, nsIView* aView) { ........ case NS_KEY_DOWN: case NS_KEY_UP: { if (mCurrentFocus) { mCurrentTargetContent = mCurrentFocus; } }
関係ない。ターゲットはフレームとかのことでスレッドじゃない。
うーん、OSからキーボードが押されたメッセージを受け取ってるスレッドがjsのハンドラを実行しているように見える。
でもそれだと::Runのループを回ってないはず。
nsEventDispatcher::Dispatch
はいろんなところから呼ばれてるなー。
~/mozilla/content/html/content/src/nsHTMLInputElement.cpp
void nsHTMLInputElement::FireOnChange() { // // Since the value is changing, send out an onchange event (bug 23571) // nsEventStatus status = nsEventStatus_eIgnore; nsEvent event(PR_TRUE, NS_FORM_CHANGE); nsCOMPtr<nsPresContext> presContext = GetPresContext(); nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext, &event, nsnull, &status); }
そもそもdispatchする段階でターゲットのスレッド情報なんかはない。だからそれより前の段階でターゲットのスレッドにスイッチしてる。
もうよくわかんないけどproxyObject経由でてきとうにメソッド呼び出せばいいかな。それでいけるはず。