mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 950559 part.2 nsIMM32Handler should set IME releated windows to left-bottom of focused plugin r=emk
This commit is contained in:
parent
e0ff6eabfe
commit
b8cb3cd758
@ -104,6 +104,18 @@ IMEHandler::ProcessMessage(nsWindow* aWindow, UINT aMessage,
|
||||
{
|
||||
#ifdef NS_ENABLE_TSF
|
||||
if (IsTSFAvailable()) {
|
||||
if (aMessage == WM_IME_SETCONTEXT) {
|
||||
// If a windowless plugin had focus and IME was handled on it, composition
|
||||
// window was set the position. After that, even in TSF mode, WinXP keeps
|
||||
// to use composition window at the position if the active IME is not
|
||||
// aware TSF. For avoiding this issue, we need to hide the composition
|
||||
// window here.
|
||||
if (aWParam) {
|
||||
aLParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aMessage == WM_USER_TSF_TEXTCHANGE) {
|
||||
nsTextStore::OnTextChangeMsg();
|
||||
aResult.mConsumed = true;
|
||||
|
@ -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,
|
||||
|
@ -261,7 +261,9 @@ protected:
|
||||
nsACString& aANSIStr);
|
||||
|
||||
bool SetIMERelatedWindowsPos(nsWindow* aWindow,
|
||||
const nsIMEContext &aIMEContext);
|
||||
const nsIMEContext& aIMEContext);
|
||||
void SetIMERelatedWindowsPosOnPlugin(nsWindow* aWindow,
|
||||
const nsIMEContext& aIMEContext);
|
||||
bool GetCharacterRectOfSelectedTextAt(nsWindow* aWindow,
|
||||
uint32_t aOffset,
|
||||
nsIntRect &aCharRect);
|
||||
|
Loading…
Reference in New Issue
Block a user