Bug 950559 part.2 nsIMM32Handler should set IME releated windows to left-bottom of focused plugin r=emk

This commit is contained in:
Masayuki Nakano
2013-12-18 10:43:15 +09:00
parent 2bbb64a8d5
commit d66c4afff2
3 changed files with 87 additions and 1 deletions

View File

@@ -763,6 +763,8 @@ nsIMM32Handler::OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
aWindow->GetWindowHandle(), mIsComposingOnPlugin ? "TRUE" : "FALSE"));
mIsComposingOnPlugin = true;
mComposingWindow = aWindow;
nsIMEContext IMEContext(aWindow->GetWindowHandle());
SetIMERelatedWindowsPosOnPlugin(aWindow, IMEContext);
aResult.mConsumed =
aWindow->DispatchPluginEvent(WM_IME_STARTCOMPOSITION, wParam, lParam,
false);
@@ -795,6 +797,8 @@ nsIMM32Handler::OnIMECompositionOnPlugin(nsWindow* aWindow,
if (IS_COMPOSING_LPARAM(lParam)) {
mIsComposingOnPlugin = true;
mComposingWindow = aWindow;
nsIMEContext IMEContext(aWindow->GetWindowHandle());
SetIMERelatedWindowsPosOnPlugin(aWindow, IMEContext);
}
aResult.mConsumed =
aWindow->DispatchPluginEvent(WM_IME_COMPOSITION, wParam, lParam, true);
@@ -813,6 +817,12 @@ nsIMM32Handler::OnIMEEndCompositionOnPlugin(nsWindow* aWindow,
mIsComposingOnPlugin = false;
mComposingWindow = nullptr;
if (mNativeCaretIsCreated) {
::DestroyCaret();
mNativeCaretIsCreated = false;
}
aResult.mConsumed =
aWindow->DispatchPluginEvent(WM_IME_ENDCOMPOSITION, wParam, lParam,
false);
@@ -1930,6 +1940,68 @@ nsIMM32Handler::SetIMERelatedWindowsPos(nsWindow* aWindow,
return true;
}
void
nsIMM32Handler::SetIMERelatedWindowsPosOnPlugin(nsWindow* aWindow,
const nsIMEContext& aIMEContext)
{
WidgetQueryContentEvent editorRectEvent(true, NS_QUERY_EDITOR_RECT, aWindow);
aWindow->InitEvent(editorRectEvent);
aWindow->DispatchWindowEvent(&editorRectEvent);
if (!editorRectEvent.mSucceeded) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: SetIMERelatedWindowsPosOnPlugin, "
"FAILED (NS_QUERY_EDITOR_RECT)"));
return;
}
// Clip the plugin rect by the client rect of the window because composition
// window needs to be specified the position in the client area.
nsWindow* toplevelWindow = aWindow->GetTopLevelWindow(false);
nsIntRect pluginRectInScreen =
editorRectEvent.mReply.mRect + toplevelWindow->WidgetToScreenOffset();
nsIntRect winRectInScreen;
aWindow->GetClientBounds(winRectInScreen);
// composition window cannot be positioned on the edge of client area.
winRectInScreen.width--;
winRectInScreen.height--;
nsIntRect clippedPluginRect;
clippedPluginRect.x =
std::min(std::max(pluginRectInScreen.x, winRectInScreen.x),
winRectInScreen.XMost());
clippedPluginRect.y =
std::min(std::max(pluginRectInScreen.y, winRectInScreen.y),
winRectInScreen.YMost());
int32_t xMost = std::min(pluginRectInScreen.XMost(), winRectInScreen.XMost());
int32_t yMost = std::min(pluginRectInScreen.YMost(), winRectInScreen.YMost());
clippedPluginRect.width = std::max(0, xMost - clippedPluginRect.x);
clippedPluginRect.height = std::max(0, yMost - clippedPluginRect.y);
clippedPluginRect -= aWindow->WidgetToScreenOffset();
// Cover the plugin with native caret. This prevents IME's window and plugin
// overlap.
if (mNativeCaretIsCreated) {
::DestroyCaret();
}
mNativeCaretIsCreated =
::CreateCaret(aWindow->GetWindowHandle(), nullptr,
clippedPluginRect.width, clippedPluginRect.height);
::SetCaretPos(clippedPluginRect.x, clippedPluginRect.y);
// Set the composition window to bottom-left of the clipped plugin.
// As far as we know, there is no IME for RTL language. Therefore, this code
// must not need to take care of RTL environment.
COMPOSITIONFORM compForm;
compForm.dwStyle = CFS_POINT;
compForm.ptCurrentPos.x = clippedPluginRect.BottomLeft().x;
compForm.ptCurrentPos.y = clippedPluginRect.BottomLeft().y;
if (!::ImmSetCompositionWindow(aIMEContext.get(), &compForm)) {
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
("IMM32: SetIMERelatedWindowsPosOnPlugin, "
"FAILED to set composition window"));
return;
}
}
void
nsIMM32Handler::ResolveIMECaretPos(nsIWidget* aReferenceWidget,
nsIntRect& aCursorRect,