Bug 378752 Mnemonic of Menu doesn't work if an editor has focus and IME is on r+sr=roc
authormasayuki@d-toybox.com
Wed, 02 May 2007 08:34:35 -0700
changeset 998 ffbfd38337f2494c13e4046642c56bfd1e447f6f
parent 997 14e09aa3c540e1f568170e6cca2fcaadd354bee8
child 999 fb9405225769af5e852e83bb2ee46edd1aa77817
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs378752
milestone1.9a5pre
Bug 378752 Mnemonic of Menu doesn't work if an editor has focus and IME is on r+sr=roc
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
content/events/src/nsIMEStateManager.cpp
content/events/src/nsIMEStateManager.h
layout/xul/base/src/nsMenuBarFrame.cpp
layout/xul/base/src/nsMenuPopupFrame.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1018,16 +1018,23 @@ public:
     PRUint32 mLangID;
     void *mObject;
   };
 
   /**
    * Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
    */
   static PRUint32 GetKBStateControlStatusFromIMEStatus(PRUint32 aState);
+
+  /*
+   * Notify when the first XUL menu is opened and when the all XUL menus are
+   * closed. At opening, aInstalling should be TRUE, otherwise, it should be
+   * FALSE.
+   */
+  static void NotifyInstalledMenuKeyboardListener(PRBool aInstalling);
 private:
 
   static PRBool InitializeEventTable();
 
   static nsresult doReparentContentWrapper(nsIContent *aChild,
                                            JSContext *cx,
                                            JSObject *aOldGlobal,
                                            JSObject *aNewGlobal,
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -132,16 +132,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsAttrName.h"
 #include "nsIDOMUserDataHandler.h"
 #include "nsIFragmentContentSink.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsTPtrArray.h"
 #include "nsGUIEvent.h"
 #include "nsMutationEvent.h"
 #include "nsIKBStateControl.h"
+#include "nsIMEStateManager.h"
 
 #ifdef IBMBIDI
 #include "nsIBidiKeyboard.h"
 #endif
 #include "nsCycleCollectionParticipant.h"
 
 // for ReportToConsole
 #include "nsIStringBundle.h"
@@ -3586,8 +3587,15 @@ nsContentUtils::GetKBStateControlStatusF
       return nsIKBStateControl::IME_STATUS_ENABLED;
     case nsIContent::IME_STATUS_PASSWORD:
       return nsIKBStateControl::IME_STATUS_PASSWORD;
     default:
       NS_ERROR("The given state doesn't have valid enable state");
       return nsIKBStateControl::IME_STATUS_ENABLED;
   }
 }
+
+/* static */
+void
+nsContentUtils::NotifyInstalledMenuKeyboardListener(PRBool aInstalling)
+{
+  nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
+}
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -57,16 +57,17 @@
 
 /******************************************************************/
 /* nsIMEStateManager                                              */
 /******************************************************************/
 
 nsIContent*    nsIMEStateManager::sContent      = nsnull;
 nsPresContext* nsIMEStateManager::sPresContext  = nsnull;
 nsPIDOMWindow* nsIMEStateManager::sActiveWindow = nsnull;
+PRBool         nsIMEStateManager::sInstalledMenuKeyboardListener = PR_FALSE;
 
 nsresult
 nsIMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
   if (aPresContext != sPresContext)
     return NS_OK;
   sContent = nsnull;
@@ -185,16 +186,23 @@ nsIMEStateManager::OnDeactivate(nsPresCo
   // We should enable the IME state for other applications.
   nsCOMPtr<nsIKBStateControl> kb = GetKBStateControl(aPresContext);
   if (kb)
     SetIMEState(aPresContext, nsIContent::IME_STATUS_ENABLE, kb);
 #endif // NS_KBSC_USE_SHARED_CONTEXT
   return NS_OK;
 }
 
+void
+nsIMEStateManager::OnInstalledMenuKeyboardListener(PRBool aInstalling)
+{
+  sInstalledMenuKeyboardListener = aInstalling;
+  OnChangeFocus(sPresContext, sContent);
+}
+
 PRBool
 nsIMEStateManager::IsActive(nsPresContext* aPresContext)
 {
   NS_ENSURE_ARG_POINTER(aPresContext);
   nsPIDOMWindow* window = aPresContext->Document()->GetWindow();
   NS_ENSURE_TRUE(window, PR_FALSE);
   if (!sActiveWindow || sActiveWindow != window->GetPrivateRoot()) {
     // This root window is not active.
@@ -224,16 +232,19 @@ nsIMEStateManager::GetNewIMEState(nsPres
                                   nsIContent*    aContent)
 {
   // On Printing or Print Preview, we don't need IME.
   if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
       aPresContext->Type() == nsPresContext::eContext_Print) {
     return nsIContent::IME_STATUS_DISABLE;
   }
 
+  if (sInstalledMenuKeyboardListener)
+    return nsIContent::IME_STATUS_DISABLE;
+
   PRBool isEditable = PR_FALSE;
   nsCOMPtr<nsISupports> container = aPresContext->GetContainer();
   nsCOMPtr<nsIEditorDocShell> editorDocShell(do_QueryInterface(container));
   if (editorDocShell)
     editorDocShell->GetEditable(&isEditable);
 
   if (isEditable)
     return nsIContent::IME_STATUS_ENABLE;
--- a/content/events/src/nsIMEStateManager.h
+++ b/content/events/src/nsIMEStateManager.h
@@ -56,26 +56,28 @@ class nsIMEStateManager
 public:
   static nsresult OnDestroyPresContext(nsPresContext* aPresContext);
   static nsresult OnRemoveContent(nsPresContext* aPresContext,
                                   nsIContent* aContent);
   static nsresult OnChangeFocus(nsPresContext* aPresContext,
                                 nsIContent* aContent);
   static nsresult OnActivate(nsPresContext* aPresContext);
   static nsresult OnDeactivate(nsPresContext* aPresContext);
+  static void OnInstalledMenuKeyboardListener(PRBool aInstalling);
 protected:
   static void SetIMEState(nsPresContext* aPresContext,
                           PRUint32 aState,
                           nsIKBStateControl* aKB);
   static PRUint32 GetNewIMEState(nsPresContext* aPresContext,
                                  nsIContent* aContent);
 
   static PRBool IsActive(nsPresContext* aPresContext);
 
   static nsIFocusController* GetFocusController(nsPresContext* aPresContext);
   static nsIKBStateControl* GetKBStateControl(nsPresContext* aPresContext);
 
   static nsIContent*    sContent;
   static nsPresContext* sPresContext;
   static nsPIDOMWindow* sActiveWindow;
+  static PRBool         sInstalledMenuKeyboardListener;
 };
 
 #endif // nsIMEStateManager_h__
--- a/layout/xul/base/src/nsMenuBarFrame.cpp
+++ b/layout/xul/base/src/nsMenuBarFrame.cpp
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsMenuListener.h"
 #include "nsMenuBarFrame.h"
 #include "nsIServiceManager.h"
 #include "nsIContent.h"
+#include "nsContentUtils.h"
 #include "prtypes.h"
 #include "nsIAtom.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsCSSRendering.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventReceiver.h"
@@ -754,32 +755,36 @@ nsMenuBarFrame::InstallKeyboardNavigator
     return NS_OK;
 
   mKeyboardNavigator = new nsMenuListener(this);
   NS_IF_ADDREF(mKeyboardNavigator);
 
   mTarget->AddEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE); 
   mTarget->AddEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);  
   mTarget->AddEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);   
-  
+
+  nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_TRUE);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMenuBarFrame::RemoveKeyboardNavigator()
 {
   if (!mKeyboardNavigator || mIsActive)
     return NS_OK;
 
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
-  
+
   NS_IF_RELEASE(mKeyboardNavigator);
 
+  nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_FALSE);
+
   return NS_OK;
 }
 
 // helpers ///////////////////////////////////////////////////////////
 
 PRBool 
 nsMenuBarFrame::IsValidItem(nsIContent* aContent)
 {
--- a/layout/xul/base/src/nsMenuPopupFrame.cpp
+++ b/layout/xul/base/src/nsMenuPopupFrame.cpp
@@ -39,16 +39,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsMenuPopupFrame.h"
 #include "nsGkAtoms.h"
 #include "nsIContent.h"
+#include "nsContentUtils.h"
 #include "prtypes.h"
 #include "nsIAtom.h"
 #include "nsPresContext.h"
 #include "nsStyleContext.h"
 #include "nsCSSRendering.h"
 #include "nsINameSpaceManager.h"
 #include "nsIViewManager.h"
 #include "nsWidgetsCID.h"
@@ -1795,32 +1796,36 @@ nsMenuPopupFrame::InstallKeyboardNavigat
   
   mTarget = target;
   mKeyboardNavigator = new nsMenuListener(this);
   NS_IF_ADDREF(mKeyboardNavigator);
 
   target->AddEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE); 
   target->AddEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);  
   target->AddEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);   
-  
+
+  nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_TRUE);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMenuPopupFrame::RemoveKeyboardNavigator()
 {
   if (!mKeyboardNavigator)
     return NS_OK;
 
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
   mTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), (nsIDOMKeyListener*)mKeyboardNavigator, PR_TRUE);
-  
+
   NS_IF_RELEASE(mKeyboardNavigator);
 
+  nsContentUtils::NotifyInstalledMenuKeyboardListener(PR_FALSE);
+
   return NS_OK;
 }
 
 // helpers /////////////////////////////////////////////////////////////
 
 PRBool 
 nsMenuPopupFrame::IsValidItem(nsIContent* aContent)
 {