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経由でてきとうにメソッド呼び出せばいいかな。それでいけるはず。