mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 789706 part.1 Create native caret over our caret when ITextStoreACP::GetTextExt() is called during composition r=emk
This commit is contained in:
parent
9ef3919738
commit
1aa091b2bc
@ -529,6 +529,7 @@ nsTextStore::nsTextStore()
|
||||
mInputScopeRequested = false;
|
||||
mIsRecordingActionsWithoutLock = false;
|
||||
mNotifySelectionChange = false;
|
||||
mNativeCaretIsCreated = false;
|
||||
mIsIMM_IME = IsIMM_IME(::GetKeyboardLayout(0));
|
||||
// We hope that 5 or more actions don't occur at once.
|
||||
mPendingActions.SetCapacity(5);
|
||||
@ -876,9 +877,7 @@ nsTextStore::RequestLock(DWORD dwLockFlags,
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<",
|
||||
this, GetLockFlagNameStr(mLock).get()));
|
||||
if (IsReadWriteLocked()) {
|
||||
FlushPendingActions();
|
||||
}
|
||||
DidLockGranted();
|
||||
while (mLockQueued) {
|
||||
mLock = mLockQueued;
|
||||
mLockQueued = 0;
|
||||
@ -893,9 +892,7 @@ nsTextStore::RequestLock(DWORD dwLockFlags,
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<",
|
||||
this, GetLockFlagNameStr(mLock).get()));
|
||||
if (IsReadWriteLocked()) {
|
||||
FlushPendingActions();
|
||||
}
|
||||
DidLockGranted();
|
||||
}
|
||||
mLock = 0;
|
||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||
@ -925,6 +922,18 @@ nsTextStore::RequestLock(DWORD dwLockFlags,
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStore::DidLockGranted()
|
||||
{
|
||||
if (mNativeCaretIsCreated) {
|
||||
::DestroyCaret();
|
||||
mNativeCaretIsCreated = false;
|
||||
}
|
||||
if (IsReadWriteLocked()) {
|
||||
FlushPendingActions();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStore::FlushPendingActions()
|
||||
{
|
||||
@ -2413,6 +2422,20 @@ nsTextStore::GetTextExt(TsViewCookie vcView,
|
||||
// not equal if text rect was clipped
|
||||
*pfClipped = !::EqualRect(prc, &textRect);
|
||||
|
||||
// ATOK refers native caret position and size on Desktop applications for
|
||||
// deciding candidate window. Therefore, we need to create native caret
|
||||
// for hacking the bug.
|
||||
if (XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Desktop &&
|
||||
mComposition.IsComposing() &&
|
||||
mComposition.mStart <= acpStart && mComposition.EndOffset() >= acpStart &&
|
||||
mComposition.mStart <= acpEnd && mComposition.EndOffset() >= acpEnd) {
|
||||
if (mNativeCaretIsCreated) {
|
||||
::DestroyCaret();
|
||||
mNativeCaretIsCreated = false;
|
||||
}
|
||||
CreateNativeCaret();
|
||||
}
|
||||
|
||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||
("TSF: 0x%p nsTextStore::GetTextExt() succeeded: "
|
||||
"*prc={ left=%ld, top=%ld, right=%ld, bottom=%ld }, *pfClipped=%s",
|
||||
@ -3190,6 +3213,69 @@ nsTextStore::OnLayoutChange()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStore::CreateNativeCaret()
|
||||
{
|
||||
// This method must work only on desktop application.
|
||||
if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Desktop) {
|
||||
return;
|
||||
}
|
||||
|
||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||
("TSF: 0x%p nsTextStore::CreateNativeCaret(), "
|
||||
"mComposition.IsComposing()=%s",
|
||||
this, GetBoolName(mComposition.IsComposing())));
|
||||
|
||||
Selection& currentSel = CurrentSelection();
|
||||
if (currentSel.IsDirty()) {
|
||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||
("TSF: 0x%p nsTextStore::CreateNativeCaret() FAILED due to "
|
||||
"CurrentSelection() failure", this));
|
||||
return;
|
||||
}
|
||||
|
||||
// XXX If this is called without composition and the selection isn't
|
||||
// collapsed, is it OK?
|
||||
uint32_t caretOffset = currentSel.MaxOffset();
|
||||
|
||||
WidgetQueryContentEvent queryCaretRect(true, NS_QUERY_CARET_RECT, mWidget);
|
||||
queryCaretRect.InitForQueryCaretRect(caretOffset);
|
||||
mWidget->InitEvent(queryCaretRect);
|
||||
mWidget->DispatchWindowEvent(&queryCaretRect);
|
||||
if (!queryCaretRect.mSucceeded) {
|
||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||
("TSF: 0x%p nsTextStore::CreateNativeCaret() FAILED due to "
|
||||
"NS_QUERY_CARET_RECT failure (offset=%d)", this, caretOffset));
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect& caretRect = queryCaretRect.mReply.mRect;
|
||||
mNativeCaretIsCreated = ::CreateCaret(mWidget->GetWindowHandle(), nullptr,
|
||||
caretRect.width, caretRect.height);
|
||||
if (!mNativeCaretIsCreated) {
|
||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||
("TSF: 0x%p nsTextStore::CreateNativeCaret() FAILED due to "
|
||||
"CreateCaret() failure", this));
|
||||
return;
|
||||
}
|
||||
|
||||
nsWindow* window = static_cast<nsWindow*>(mWidget.get());
|
||||
nsWindow* toplevelWindow = window->GetTopLevelWindow(false);
|
||||
if (!toplevelWindow) {
|
||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||
("TSF: 0x%p nsTextStore::CreateNativeCaret() FAILED due to "
|
||||
"no top level window", this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (toplevelWindow != window) {
|
||||
caretRect.MoveBy(toplevelWindow->WidgetToScreenOffset());
|
||||
caretRect.MoveBy(-window->WidgetToScreenOffset());
|
||||
}
|
||||
|
||||
::SetCaretPos(caretRect.x, caretRect.y);
|
||||
}
|
||||
|
||||
void
|
||||
nsTextStore::CommitCompositionInternal(bool aDiscard)
|
||||
{
|
||||
|
@ -230,6 +230,10 @@ protected:
|
||||
bool IsReadLocked() const { return IsReadLock(mLock); }
|
||||
bool IsReadWriteLocked() const { return IsReadWriteLock(mLock); }
|
||||
|
||||
// This is called immediately after a call of OnLockGranted() of mSink.
|
||||
// Note that mLock isn't cleared yet when this is called.
|
||||
void DidLockGranted();
|
||||
|
||||
bool GetScreenExtInternal(RECT &aScreenExt);
|
||||
// If aDispatchTextEvent is true, this method will dispatch text event if
|
||||
// this is called during IME composing. aDispatchTextEvent should be true
|
||||
@ -265,6 +269,10 @@ protected:
|
||||
const TS_ATTRID *paFilterAttrs);
|
||||
void SetInputScope(const nsString& aHTMLInputType);
|
||||
|
||||
// Creates native caret over our caret. This method only works on desktop
|
||||
// application. Otherwise, this does nothing.
|
||||
void CreateNativeCaret();
|
||||
|
||||
// Holds the pointer to our current win32 or metro widget
|
||||
nsRefPtr<nsWindowBase> mWidget;
|
||||
// Document manager for the currently focused editor
|
||||
@ -644,6 +652,8 @@ protected:
|
||||
// during recoding actions and then, FlushPendingActions() will call
|
||||
// mSink->OnSelectionChange().
|
||||
bool mNotifySelectionChange;
|
||||
// While there is native caret, this is true. Otherwise, false.
|
||||
bool mNativeCaretIsCreated;
|
||||
|
||||
// True if current IME is implemented with IMM.
|
||||
bool mIsIMM_IME;
|
||||
|
Loading…
Reference in New Issue
Block a user