Bug 1130935 part.2 Set proper composition font when writing mode is changed r=emk

This commit is contained in:
Masayuki Nakano 2015-05-15 10:18:07 +09:00
Родитель f98deed367
Коммит 600cb6eeee
3 изменённых файлов: 150 добавлений и 15 удалений

Просмотреть файл

@ -3069,9 +3069,18 @@ pref("intl.tsf.hack.google_ja_input.do_not_return_no_layout_error_at_first_char"
pref("intl.tsf.hack.google_ja_input.do_not_return_no_layout_error_at_caret", true);
#endif
// If composition_font is set, Gecko sets the font to IME. IME may use
// the fonts on their window like candidate window. If they are empty,
// Gecko uses the system default font which is set to the IM context.
// The font name must not start with '@'. When the writing mode is vertical,
// Gecko inserts '@' to the start of the font name automatically.
// FYI: Changing these prefs requires to restart.
pref("intl.imm.composition_font", "");
// Even if IME claims that they support vertical writing mode but it may not
// support vertical writing mode for its candidate window. This pref allows
// to ignore the claim.
// FYI: Changing this pref requires to restart.
pref("intl.imm.vertical_writing.always_assume_not_supported", false);
// See bug 448927, on topmost panel, some IMEs are not usable on Windows.

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsWindowDefs.h"
#include "WinUtils.h"
#include "KeyboardLayout.h"
#include "WritingModes.h"
#include <algorithm>
#include "mozilla/MiscEvents.h"
@ -113,6 +114,7 @@ static UINT sWM_MSIME_MOUSE = 0; // mouse message for MSIME 98/2000
#define IMEMOUSE_WUP 0x10 // wheel up
#define IMEMOUSE_WDOWN 0x20 // wheel down
nsString nsIMM32Handler::sIMEName;
UINT nsIMM32Handler::sCodePage = 0;
DWORD nsIMM32Handler::sIMEProperty = 0;
DWORD nsIMM32Handler::sIMEUIProperty = 0;
@ -202,21 +204,18 @@ nsIMM32Handler::IsVerticalWritingSupported()
/* static */ void
nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
{
#ifdef PR_LOGGING
nsAutoString IMEName;
if (PR_LOG_TEST(gIMM32Log, PR_LOG_ALWAYS)) {
UINT IMENameLength = ::ImmGetDescriptionW(aKeyboardLayout, nullptr, 0);
if (IMENameLength) {
// Add room for the terminating null character
IMEName.SetLength(++IMENameLength);
IMENameLength =
::ImmGetDescriptionW(aKeyboardLayout, IMEName.BeginWriting(),
IMENameLength);
// Adjust the length to ignore the terminating null character
IMEName.SetLength(IMENameLength);
}
UINT IMENameLength = ::ImmGetDescriptionW(aKeyboardLayout, nullptr, 0);
if (IMENameLength) {
// Add room for the terminating null character
sIMEName.SetLength(++IMENameLength);
IMENameLength =
::ImmGetDescriptionW(aKeyboardLayout, sIMEName.BeginWriting(),
IMENameLength);
// Adjust the length to ignore the terminating null character
sIMEName.SetLength(IMENameLength);
} else {
sIMEName.Truncate();
}
#endif // #ifdef PR_LOGGING
WORD langID = LOWORD(aKeyboardLayout);
::GetLocaleInfoW(MAKELCID(langID, SORT_DEFAULT),
@ -227,7 +226,7 @@ nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: InitKeyboardLayout, aKeyboardLayout=%08x (\"%s\"), sCodePage=%lu, "
"sIMEProperty=%s, sIMEUIProperty=%s",
aKeyboardLayout, NS_ConvertUTF16toUTF8(IMEName).get(),
aKeyboardLayout, NS_ConvertUTF16toUTF8(sIMEName).get(),
sCodePage, GetIMEGeneralPropertyName(sIMEProperty).get(),
GetIMEUIPropertyName(sIMEUIProperty).get()));
}
@ -872,6 +871,9 @@ nsIMM32Handler::OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
mComposingWindow = aWindow;
nsIMEContext IMEContext(aWindow->GetWindowHandle());
SetIMERelatedWindowsPosOnPlugin(aWindow, IMEContext);
// On widnowless plugin, we should assume that the focused editor is always
// in horizontal writing mode.
AdjustCompositionFont(IMEContext, WritingMode());
aResult.mConsumed =
aWindow->DispatchPluginEvent(WM_IME_STARTCOMPOSITION, wParam, lParam,
false);
@ -1048,6 +1050,8 @@ nsIMM32Handler::HandleStartComposition(nsWindow* aWindow,
return;
}
AdjustCompositionFont(aIMEContext, selection.GetWritingMode());
mCompositionStart = selection.mReply.mOffset;
WidgetCompositionEvent event(true, NS_COMPOSITION_START, aWindow);
@ -2118,6 +2122,118 @@ nsIMM32Handler::ResolveIMECaretPos(nsIWidget* aReferenceWidget,
aOutRect.MoveBy(-aNewOriginWidget->WidgetToScreenOffsetUntyped());
}
static void
SetHorizontalFontToLogFont(const nsAString& aFontFace,
LOGFONTW& aLogFont)
{
aLogFont.lfEscapement = aLogFont.lfOrientation = 0;
if (NS_WARN_IF(aFontFace.Length() > LF_FACESIZE - 1)) {
memcpy(aLogFont.lfFaceName, L"System", sizeof(L"System"));
return;
}
memcpy(aLogFont.lfFaceName, aFontFace.BeginReading(),
aFontFace.Length() * sizeof(wchar_t));
aLogFont.lfFaceName[aFontFace.Length()] = 0;
}
static void
SetVerticalFontToLogFont(const nsAString& aFontFace,
LOGFONTW& aLogFont)
{
aLogFont.lfEscapement = aLogFont.lfOrientation = 2700;
if (NS_WARN_IF(aFontFace.Length() > LF_FACESIZE - 2)) {
memcpy(aLogFont.lfFaceName, L"@System", sizeof(L"@System"));
return;
}
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)
{
// 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();
static WritingMode sCurrentWritingMode;
static nsString sCurrentIMEName;
if (!setCompositionFontForcibly &&
sCurrentWritingMode == 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
// mode, insert '@' to the start of the font.
if (!sCompositionFontsInitialized) {
sCompositionFontsInitialized = true;
// sCompositionFontH must not start with '@' and its length is less than
// LF_FACESIZE since it needs to end with null terminating character.
if (sCompositionFont.IsEmpty() ||
sCompositionFont.Length() > LF_FACESIZE - 1 ||
sCompositionFont[0] == '@') {
LOGFONTW defaultLogFont;
if (NS_WARN_IF(!::ImmGetCompositionFont(aIMEContext.get(),
&defaultLogFont))) {
PR_LOG(gIMM32Log, PR_LOG_ERROR,
("IMM32: AdjustCompositionFont, ::ImmGetCompositionFont() failed"));
sCompositionFont.AssignLiteral("System");
} else {
// The font face is typically, "System".
sCompositionFont.Assign(defaultLogFont.lfFaceName);
}
}
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: AdjustCompositionFont, sCompositionFont=\"%s\" is initialized",
NS_ConvertUTF16toUTF8(sCompositionFont).get()));
}
sCurrentWritingMode = 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;
}
// Need to reset some information which should be recomputed with new font.
logFont.lfWidth = 0;
logFont.lfWeight = FW_DONTCARE;
logFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logFont.lfPitchAndFamily = DEFAULT_PITCH;
if (!mIsComposingOnPlugin &&
aWritingMode.IsVertical() && IsVerticalWritingSupported()) {
SetVerticalFontToLogFont(sCompositionFont, logFont);
} else {
SetHorizontalFontToLogFont(sCompositionFont, logFont);
}
PR_LOG(gIMM32Log, PR_LOG_WARNING,
("IMM32: AdjustCompositionFont, calling ::ImmSetCompositionFont(\"%s\")",
NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get()));
::ImmSetCompositionFontW(aIMEContext.get(), &logFont);
}
/* static */ nsresult
nsIMM32Handler::OnMouseButtonEvent(nsWindow* aWindow,
const IMENotification& aIMENotification)

Просмотреть файл

@ -18,6 +18,9 @@
class nsWindow;
namespace mozilla {
class WritingMode;
namespace widget {
struct MSGResult;
@ -283,6 +286,12 @@ protected:
void GetCompositionString(const nsIMEContext &aIMEContext,
DWORD aIndex,
nsAString& aCompositionString) const;
/**
* AdjustCompositionFont() makes IME vertical writing mode if it's supported.
*/
void AdjustCompositionFont(const nsIMEContext& aIMEContext,
const mozilla::WritingMode& aWritingMode);
/**
* Get the current target clause of composition string.
* If there are one or more characters whose attribute is ATTR_TARGET_*,
@ -360,6 +369,7 @@ protected:
bool mIsComposingOnPlugin;
bool mNativeCaretIsCreated;
static nsString sIMEName;
static UINT sCodePage;
static DWORD sIMEProperty;
static DWORD sIMEUIProperty;