Bug 1130935 part.10 nsIMM32Handler should forcibly update composition font when active IME is changed r=emk
authorMasayuki Nakano <masayuki@d-toybox.com>
Fri, 15 May 2015 10:18:08 +0900
changeset 244016 3c1906570833cea5b8af06943cc4ac4c35feb92d
parent 244015 e64588f219f4d67ac639d11822dbc8d7d2232df2
child 244017 c6c67158efeffa4445db742dc85e89ec76056519
push id28762
push usercbook@mozilla.com
push dateFri, 15 May 2015 15:40:04 +0000
treeherdermozilla-central@1a8343f8ed83 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemk
bugs1130935
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1130935 part.10 nsIMM32Handler should forcibly update composition font when active IME is changed r=emk
widget/windows/nsIMM32Handler.cpp
widget/windows/nsIMM32Handler.h
--- a/widget/windows/nsIMM32Handler.cpp
+++ b/widget/windows/nsIMM32Handler.cpp
@@ -6,17 +6,16 @@
 
 #include "prlog.h"
 
 #include "nsIMM32Handler.h"
 #include "nsWindow.h"
 #include "nsWindowDefs.h"
 #include "WinUtils.h"
 #include "KeyboardLayout.h"
-#include "WritingModes.h"
 #include <algorithm>
 
 #include "mozilla/MiscEvents.h"
 #include "mozilla/TextEvents.h"
 
 #ifndef IME_PROP_ACCEPT_WIDE_VKEY
 #define IME_PROP_ACCEPT_WIDE_VKEY 0x20
 #endif
@@ -127,16 +126,17 @@ static UINT sWM_MSIME_MOUSE = 0; // mous
 
 #define IMEMOUSE_NONE       0x00    // no mouse button was pushed
 #define IMEMOUSE_LDOWN      0x01
 #define IMEMOUSE_RDOWN      0x02
 #define IMEMOUSE_MDOWN      0x04
 #define IMEMOUSE_WUP        0x10    // wheel up
 #define IMEMOUSE_WDOWN      0x20    // wheel down
 
+WritingMode nsIMM32Handler::sWritingModeOfCompositionFont;
 nsString nsIMM32Handler::sIMEName;
 UINT nsIMM32Handler::sCodePage = 0;
 DWORD nsIMM32Handler::sIMEProperty = 0;
 DWORD nsIMM32Handler::sIMEUIProperty = 0;
 bool nsIMM32Handler::sAssumeVerticalWritingModeNotSupported = false;
 
 /* static */ void
 nsIMM32Handler::EnsureHandlerInstance()
@@ -153,17 +153,17 @@ nsIMM32Handler::Initialize()
     gIMM32Log = PR_NewLogModule("nsIMM32HandlerWidgets");
 
   if (!sWM_MSIME_MOUSE) {
     sWM_MSIME_MOUSE = ::RegisterWindowMessage(RWM_MOUSE);
   }
   sAssumeVerticalWritingModeNotSupported =
     Preferences::GetBool(
       "intl.imm.vertical_writing.always_assume_not_supported", false);
-  InitKeyboardLayout(::GetKeyboardLayout(0));
+  InitKeyboardLayout(nullptr, ::GetKeyboardLayout(0));
 }
 
 /* static */ void
 nsIMM32Handler::Terminate()
 {
   if (!gIMM32Handler)
     return;
   delete gIMM32Handler;
@@ -236,17 +236,18 @@ nsIMM32Handler::IsVerticalWritingSupport
   // return false if it's active IME.
   if (IsGoogleJapaneseInputActive()) {
     return false;
   }
   return !!(sIMEUIProperty & (UI_CAP_2700 | UI_CAP_ROT90 | UI_CAP_ROTANY));
 }
 
 /* static */ void
-nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
+nsIMM32Handler::InitKeyboardLayout(nsWindow* aWindow,
+                                   HKL aKeyboardLayout)
 {
   UINT IMENameLength = ::ImmGetDescriptionW(aKeyboardLayout, nullptr, 0);
   if (IMENameLength) {
     // Add room for the terminating null character
     sIMEName.SetLength(++IMENameLength);
     IMENameLength =
       ::ImmGetDescriptionW(aKeyboardLayout, sIMEName.BeginWriting(),
                            IMENameLength);
@@ -266,16 +267,23 @@ nsIMM32Handler::InitKeyboardLayout(HKL a
   // If active IME is a TIP of TSF, we cannot retrieve the name with IMM32 API.
   // For hacking some bugs of some TIP, we should set an IME name from the
   // pref.
   if (sCodePage == 932 && sIMEName.IsEmpty()) {
     sIMEName =
       Preferences::GetString("intl.imm.japanese.assume_active_tip_name_as");
   }
 
+  // Whether the IME supports vertical writing mode might be changed or
+  // some IMEs may need specific font for their UI.  Therefore, we should
+  // update composition font forcibly here.
+  if (aWindow) {
+    MaybeAdjustCompositionFont(aWindow, sWritingModeOfCompositionFont, true);
+  }
+
   PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
     ("IMM32: InitKeyboardLayout, aKeyboardLayout=%08x (\"%s\"), sCodePage=%lu, "
      "sIMEProperty=%s, sIMEUIProperty=%s",
      aKeyboardLayout, NS_ConvertUTF16toUTF8(sIMEName).get(),
      sCodePage, GetIMEGeneralPropertyName(sIMEProperty).get(),
      GetIMEUIPropertyName(sIMEUIProperty).get()));
 }
 
@@ -416,48 +424,59 @@ nsIMM32Handler::OnUpdateComposition(nsWi
 // static
 void
 nsIMM32Handler::OnSelectionChange(nsWindow* aWindow,
                                   const IMENotification& aIMENotification)
 {
   if (aIMENotification.mSelectionChangeData.mCausedByComposition) {
     return;
   }
+  MaybeAdjustCompositionFont(aWindow,
+    aIMENotification.mSelectionChangeData.GetWritingMode());
+}
 
+// static
+void
+nsIMM32Handler::MaybeAdjustCompositionFont(nsWindow* aWindow,
+                                           const WritingMode& aWritingMode,
+                                           bool aForceUpdate)
+{
   switch (sCodePage) {
     case 932: // Japanese Shift-JIS
     case 936: // Simlified Chinese GBK
     case 949: // Korean
     case 950: // Traditional Chinese Big5
       EnsureHandlerInstance();
       break;
     default:
-      return;
+      // If there is no instance of nsIMM32Hander, we shouldn't waste footprint.
+      if (!gIMM32Handler) {
+        return;
+      }
   }
 
   // Like Navi-Bar of ATOK, some IMEs may require proper composition font even
   // before sending WM_IME_STARTCOMPOSITION.
   nsIMEContext IMEContext(aWindow->GetWindowHandle());
-  gIMM32Handler->AdjustCompositionFont(IMEContext,
-                   aIMENotification.mSelectionChangeData.GetWritingMode());
+  gIMM32Handler->AdjustCompositionFont(IMEContext, aWritingMode, aForceUpdate);
 }
 
 /* static */ bool
 nsIMM32Handler::ProcessInputLangChangeMessage(nsWindow* aWindow,
                                               WPARAM wParam,
                                               LPARAM lParam,
                                               MSGResult& aResult)
 {
   aResult.mResult = 0;
   aResult.mConsumed = false;
   // We don't need to create the instance of the handler here.
   if (gIMM32Handler) {
     gIMM32Handler->OnInputLangChange(aWindow, wParam, lParam, aResult);
   }
-  InitKeyboardLayout(reinterpret_cast<HKL>(lParam));
+  InitKeyboardLayout(aWindow, reinterpret_cast<HKL>(lParam));
   // We can release the instance here, because the instance may be never
   // used. E.g., the new keyboard layout may not use IME, or it may use TSF.
   Terminate();
   // Don't return as "processed", the messages should be processed on nsWindow
   // too.
   return false;
 }
 
@@ -2325,35 +2344,36 @@ SetVerticalFontToLogFont(const nsAString
   aLogFont.lfFaceName[0] = '@';
   memcpy(&aLogFont.lfFaceName[1], aFontFace.BeginReading(),
          aFontFace.Length() * sizeof(wchar_t));
   aLogFont.lfFaceName[aFontFace.Length() + 1] = 0;
 }
 
 void
 nsIMM32Handler::AdjustCompositionFont(const nsIMEContext& aIMEContext,
-                                      const WritingMode& aWritingMode)
+                                      const WritingMode& aWritingMode,
+                                      bool aForceUpdate)
 {
   // An instance of nsIMM32Handler is destroyed when active IME is changed.
   // Therefore, we need to store the information which are set to the IM
   // context to static variables since IM context is never recreated.
   static bool sCompositionFontsInitialized = false;
   static nsString sCompositionFont =
     Preferences::GetString("intl.imm.composition_font");
 
   // If composition font is customized by pref, we need to modify the
   // composition font of the IME context at first time even if the writing mode
   // is horizontal.
-  bool setCompositionFontForcibly =
-    !sCompositionFontsInitialized && !sCompositionFont.IsEmpty();
+  bool setCompositionFontForcibly = aForceUpdate ||
+    (!sCompositionFontsInitialized && !sCompositionFont.IsEmpty());
 
   static WritingMode sCurrentWritingMode;
   static nsString sCurrentIMEName;
   if (!setCompositionFontForcibly &&
-      sCurrentWritingMode == aWritingMode &&
+      sWritingModeOfCompositionFont == aWritingMode &&
       sCurrentIMEName == sIMEName) {
     // Nothing to do if writing mode isn't being changed.
     return;
   }
 
   // Decide composition fonts for both horizontal writing mode and vertical
   // writing mode.  If the font isn't specified by the pref, use default
   // font which is already set to the IM context.  And also in vertical writing
@@ -2392,17 +2412,17 @@ nsIMM32Handler::AdjustCompositionFont(co
     // "MS PGothic" instead.
     if (sCompositionFontForJapanist2003.IsEmpty() ||
         sCompositionFontForJapanist2003.Length() > LF_FACESIZE - 2 ||
         sCompositionFontForJapanist2003[0] == '@') {
       sCompositionFontForJapanist2003.AssignLiteral("MS PGothic");
     }
   }
 
-  sCurrentWritingMode = aWritingMode;
+  sWritingModeOfCompositionFont = aWritingMode;
   sCurrentIMEName = sIMEName;
 
   LOGFONTW logFont;
   memset(&logFont, 0, sizeof(logFont));
   if (!::ImmGetCompositionFont(aIMEContext.get(), &logFont)) {
     PR_LOG(gIMM32Log, PR_LOG_ERROR,
       ("IMM32: AdjustCompositionFont, ::ImmGetCompositionFont() failed"));
     logFont.lfFaceName[0] = 0;
--- a/widget/windows/nsIMM32Handler.h
+++ b/widget/windows/nsIMM32Handler.h
@@ -9,23 +9,21 @@
 #include "nscore.h"
 #include <windows.h>
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIWidget.h"
 #include "mozilla/EventForwards.h"
 #include "nsRect.h"
+#include "WritingModes.h"
 
 class nsWindow;
 
 namespace mozilla {
-
-class WritingMode;
-
 namespace widget {
 
 struct MSGResult;
 
 } // namespace widget
 } // namespace mozilla
 
 class nsIMEContext
@@ -163,17 +161,18 @@ protected:
   static bool IsComposingOnPlugin();
   static bool IsComposingWindow(nsWindow* aWindow);
 
   static bool IsJapanist2003Active();
   static bool IsGoogleJapaneseInputActive();
 
   static bool ShouldDrawCompositionStringOurselves();
   static bool IsVerticalWritingSupported();
-  static void InitKeyboardLayout(HKL aKeyboardLayout);
+  // aWindow can be nullptr if it's called without receiving WM_INPUTLANGCHANGE.
+  static void InitKeyboardLayout(nsWindow* aWindow, HKL aKeyboardLayout);
   static UINT GetKeyboardCodePage();
 
   /**
    * Checks whether the window is top level window of the composing window.
    * In this method, the top level window means in all windows, not only in all
    * OUR windows.  I.e., if the aWindow is embedded, this always returns FALSE.
    */
   static bool IsTopLevelWindowOfComposition(nsWindow* aWindow);
@@ -293,19 +292,33 @@ protected:
                     nsIntRect& aCaretRect,
                     mozilla::WritingMode* aWritingMode = nullptr);
   void GetCompositionString(const nsIMEContext &aIMEContext,
                             DWORD aIndex,
                             nsAString& aCompositionString) const;
 
   /**
    * AdjustCompositionFont() makes IME vertical writing mode if it's supported.
+   * If aForceUpdate is true, it will update composition font even if writing
+   * mode isn't being changed.
    */
   void AdjustCompositionFont(const nsIMEContext& aIMEContext,
-                             const mozilla::WritingMode& aWritingMode);
+                             const mozilla::WritingMode& aWritingMode,
+                             bool aForceUpdate = false);
+
+  /**
+   * MaybeAdjustCompositionFont() calls AdjustCompositionFont() when the
+   * locale of active IME is CJK.  Note that this creates an instance even
+   * when there is no composition but the locale is CJK.
+   */
+  static void MaybeAdjustCompositionFont(
+                nsWindow* aWindow,
+                const mozilla::WritingMode& aWritingMode,
+                bool aForceUpdate = false);
+
   /**
    *  Get the current target clause of composition string.
    *  If there are one or more characters whose attribute is ATTR_TARGET_*,
    *  this returns the first character's offset and its length.
    *  Otherwise, e.g., the all characters are ATTR_INPUT, this returns
    *  the composition string range because the all is the current target.
    *
    *  aLength can be null (default), but aOffset must not be null.
@@ -373,16 +386,17 @@ protected:
 
   int32_t mCursorPosition;
   uint32_t mCompositionStart;
 
   bool mIsComposing;
   bool mIsComposingOnPlugin;
   bool mNativeCaretIsCreated;
 
+  static mozilla::WritingMode sWritingModeOfCompositionFont;
   static nsString sIMEName;
   static UINT sCodePage;
   static DWORD sIMEProperty;
   static DWORD sIMEUIProperty;
   static bool sAssumeVerticalWritingModeNotSupported;
 };
 
 #endif // nsIMM32Handler_h__