Bug 891292. r=jimm, a=bajaj
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 10 Jul 2013 00:54:41 +0900
changeset 147993 fbba0c968440f1e3ae66324c4eff62d3c2b8a02d
parent 147992 6afaaba028272492488d79264f396df7247a4447
child 147994 5d8474fe858d0193568600b2740a87c867d49b92
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm, bajaj
bugs891292
milestone24.0a2
Bug 891292. r=jimm, a=bajaj
widget/windows/KeyboardLayout.cpp
widget/windows/KeyboardLayout.h
widget/windows/nsWindow.cpp
--- a/widget/windows/KeyboardLayout.cpp
+++ b/widget/windows/KeyboardLayout.cpp
@@ -745,28 +745,32 @@ NativeKey::InitKeyEvent(nsKeyEvent& aKey
   aKeyEvent.location = GetKeyLocation();
   aModKeyState.InitInputEvent(aKeyEvent);
 }
 
 bool
 NativeKey::DispatchKeyEvent(nsKeyEvent& aKeyEvent,
                             const MSG* aMsgSentToPlugin) const
 {
+  if (mWidget->Destroyed()) {
+    MOZ_CRASH("NativeKey tries to dispatch a key event on destroyed widget");
+  }
+
   KeyboardLayout::NotifyIdleServiceOfUserActivity();
 
   NPEvent pluginEvent;
   if (aMsgSentToPlugin &&
       mWidget->GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN) {
     pluginEvent.event = aMsgSentToPlugin->message;
     pluginEvent.wParam = aMsgSentToPlugin->wParam;
     pluginEvent.lParam = aMsgSentToPlugin->lParam;
     aKeyEvent.pluginEvent = static_cast<void*>(&pluginEvent);
   }
 
-  return mWidget->DispatchWindowEvent(&aKeyEvent);
+  return (mWidget->DispatchWindowEvent(&aKeyEvent) || mWidget->Destroyed());
 }
 
 bool
 NativeKey::HandleKeyDownMessage(bool* aEventDispatched) const
 {
   MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
 
   if (aEventDispatched) {
@@ -785,16 +789,22 @@ NativeKey::HandleKeyDownMessage(bool* aE
     bool isIMEEnabled = WinUtils::IsIMEEnabled(mWidget->GetInputContext());
     nsKeyEvent keydownEvent(true, NS_KEY_DOWN, mWidget);
     InitKeyEvent(keydownEvent, mModKeyState);
     if (aEventDispatched) {
       *aEventDispatched = true;
     }
     defaultPrevented = DispatchKeyEvent(keydownEvent, &mMsg);
 
+    if (mWidget->Destroyed()) {
+      // If this was destroyed by the keydown event handler, we shouldn't
+      // dispatch keypress event on this window.
+      return true;
+    }
+
     // If IMC wasn't associated to the window but is associated it now (i.e.,
     // focus is moved from a non-editable editor to an editor by keydown
     // event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character
     // inputting if IME is opened.  But then, we should redirect the native
     // keydown message to IME.
     // However, note that if focus has been already moved to another
     // application, we shouldn't redirect the message to it because the keydown
     // message is processed by us, so, nobody shouldn't process it.
@@ -819,22 +829,16 @@ NativeKey::HandleKeyDownMessage(bool* aE
 
       ::SendInput(1, &keyinput, sizeof(keyinput));
 
       // Return here.  We shouldn't dispatch keypress event for this WM_KEYDOWN.
       // If it's needed, it will be dispatched after next (redirected)
       // WM_KEYDOWN.
       return true;
     }
-
-    if (mWidget->Destroyed()) {
-      // If this was destroyed by the keydown event handler, we shouldn't
-      // dispatch keypress event on this window.
-      return true;
-    }
   } else {
     defaultPrevented = RedirectedKeyDownMessageManager::DefaultPrevented();
     // If this is redirected keydown message, we have dispatched the keydown
     // event already.
     if (aEventDispatched) {
       *aEventDispatched = true;
     }
   }
@@ -1075,64 +1079,74 @@ NativeKey::RemoveFollowingCharMessage() 
 
   MOZ_ASSERT(mCharMsg.message == msg.message &&
              mCharMsg.wParam == msg.wParam &&
              mCharMsg.lParam == msg.lParam);
 
   return mCharMsg;
 }
 
-void
+bool
 NativeKey::RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg,
                                                UINT aLastMsg) const
 {
   MSG msg;
   if (mIsFakeCharMsg) {
     if (aFirstMsg > WM_CHAR || aLastMsg < WM_CHAR) {
-      return;
+      return false;
     }
     msg = mCharMsg;
   } else {
     WinUtils::GetMessage(&msg, mMsg.hwnd, aFirstMsg, aLastMsg);
   }
+  if (mWidget->Destroyed()) {
+    MOZ_CRASH("NativeKey tries to dispatch a plugin event on destroyed widget");
+  }
   mWidget->DispatchPluginEvent(msg);
+  return mWidget->Destroyed();
 }
 
 bool
 NativeKey::DispatchKeyPressEventsAndDiscardsCharMessages(
                         const EventFlags& aExtraFlags) const
 {
   MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
 
   // Remove a possible WM_CHAR or WM_SYSCHAR messages from the message queue.
   // They can be more than one because of:
   //  * Dead-keys not pairing with base character
   //  * Some keyboard layouts may map up to 4 characters to the single key
   bool anyCharMessagesRemoved = false;
 
   if (mIsFakeCharMsg) {
-    RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
+    if (RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST)) {
+      return true;
+    }
     anyCharMessagesRemoved = true;
   } else {
     MSG msg;
     bool gotMsg =
       WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
                             PM_NOREMOVE | PM_NOYIELD);
     while (gotMsg && (msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) {
-      RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST);
+      if (RemoveMessageAndDispatchPluginEvent(WM_KEYFIRST, WM_KEYLAST)) {
+        return true;
+      }
       anyCharMessagesRemoved = true;
       gotMsg = WinUtils::PeekMessage(&msg, mMsg.hwnd, WM_KEYFIRST, WM_KEYLAST,
                                      PM_NOREMOVE | PM_NOYIELD);
     }
   }
 
   if (!anyCharMessagesRemoved &&
       mDOMKeyCode == NS_VK_BACK && IsIMEDoingKakuteiUndo()) {
     MOZ_ASSERT(!mIsFakeCharMsg);
-    RemoveMessageAndDispatchPluginEvent(WM_CHAR, WM_CHAR);
+    if (RemoveMessageAndDispatchPluginEvent(WM_CHAR, WM_CHAR)) {
+      return true;
+    }
   }
 
   return DispatchKeyPressEventsWithKeyboardLayout(aExtraFlags);
 }
 
 bool
 NativeKey::DispatchKeyPressEventsWithKeyboardLayout(
                         const EventFlags& aExtraFlags) const
@@ -1287,16 +1301,19 @@ NativeKey::DispatchKeyPressEventsWithKey
     }
 
     nsKeyEvent keypressEvent(true, NS_KEY_PRESS, mWidget);
     keypressEvent.mFlags.Union(aExtraFlags);
     keypressEvent.charCode = uniChar;
     keypressEvent.alternativeCharCodes.AppendElements(altArray);
     InitKeyEvent(keypressEvent, modKeyState);
     defaultPrevented = (DispatchKeyEvent(keypressEvent) || defaultPrevented);
+    if (mWidget->Destroyed()) {
+      return true;
+    }
   }
 
   return defaultPrevented;
 }
 
 bool
 NativeKey::DispatchKeyPressEventForFollowingCharMessage(
                         const EventFlags& aExtraFlags) const
@@ -1334,17 +1351,19 @@ NativeKey::DispatchKeyPressEventForFollo
     return HandleCharMessage(msg, nullptr, &aExtraFlags);
   }
 
   // If prevent default set for keydown, do same for keypress
   if (msg.message == WM_DEADCHAR) {
     bool defaultPrevented = aExtraFlags.mDefaultPrevented;
     if (mWidget->PluginHasFocus()) {
       // We need to send the removed message to focused plug-in.
-      defaultPrevented = mWidget->DispatchPluginEvent(msg) || defaultPrevented;
+      defaultPrevented =
+        (mWidget->DispatchPluginEvent(msg) || defaultPrevented ||
+         mWidget->Destroyed());
     }
     return defaultPrevented;
   }
 
   bool defaultPrevented = (HandleCharMessage(msg, nullptr, &aExtraFlags) ||
                            aExtraFlags.mDefaultPrevented);
   // If a syschar keypress wasn't processed, Windows may want to
   // handle it to activate a native menu.
--- a/widget/windows/KeyboardLayout.h
+++ b/widget/windows/KeyboardLayout.h
@@ -389,18 +389,19 @@ private:
    * "Kakutei-Undo" of ATOK or WXG (both of them are Japanese IME) causes
    * strange WM_KEYDOWN/WM_KEYUP/WM_CHAR message pattern.  So, when this
    * returns true, the caller needs to be careful for processing the messages.
    */
   bool IsIMEDoingKakuteiUndo() const;
 
   /*
    * Dispatches a plugin event after the specified message is removed.
+   * Returns true if the widget is destoyed.  Otherwise, false.
    */
-  void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg) const;
+  bool RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg) const;
 
   bool IsKeyDownMessage() const
   {
     return (mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
   }
   bool IsFollowedByCharMessage() const
   {
     MOZ_ASSERT(mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3738,17 +3738,17 @@ void nsWindow::DispatchPendingEvents()
 
 bool nsWindow::DispatchPluginEvent(UINT aMessage,
                                      WPARAM aWParam,
                                      LPARAM aLParam,
                                      bool aDispatchPendingEvents)
 {
   bool ret = nsWindowBase::DispatchPluginEvent(
                WinUtils::InitMSG(aMessage, aWParam, aLParam, mWnd));
-  if (aDispatchPendingEvents) {
+  if (aDispatchPendingEvents && !Destroyed()) {
     DispatchPendingEvents();
   }
   return ret;
 }
 
 // Deal with all sort of mouse event
 bool nsWindow::DispatchMouseEvent(uint32_t aEventType, WPARAM wParam,
                                     LPARAM lParam, bool aIsContextMenuKey,