Bug 790516 part.1 Move composition string data of nsTextStore into a nested class r=emk
This commit is contained in:
@@ -496,10 +496,7 @@ nsTextStore::~nsTextStore()
|
|||||||
"mWidget=0x%p, mDocumentMgr=0x%p, mContext=0x%p",
|
"mWidget=0x%p, mDocumentMgr=0x%p, mContext=0x%p",
|
||||||
this, mWidget.get(), mDocumentMgr.get(), mContext.get()));
|
this, mWidget.get(), mDocumentMgr.get(), mContext.get()));
|
||||||
|
|
||||||
if (mCompositionTimer) {
|
mComposition.EnsureLayoutChangeTimerStopped();
|
||||||
mCompositionTimer->Cancel();
|
|
||||||
mCompositionTimer = nullptr;
|
|
||||||
}
|
|
||||||
SaveTextEvent(nullptr);
|
SaveTextEvent(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -886,13 +883,13 @@ nsTextStore::GetSelection(ULONG ulIndex,
|
|||||||
bool
|
bool
|
||||||
nsTextStore::GetSelectionInternal(TS_SELECTION_ACP &aSelectionACP)
|
nsTextStore::GetSelectionInternal(TS_SELECTION_ACP &aSelectionACP)
|
||||||
{
|
{
|
||||||
if (mCompositionView) {
|
if (mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::GetSelectionInternal(), "
|
("TSF: 0x%p nsTextStore::GetSelectionInternal(), "
|
||||||
"there is no composition view", this));
|
"there is no composition view", this));
|
||||||
|
|
||||||
// Emulate selection during compositions
|
// Emulate selection during compositions
|
||||||
aSelectionACP = mCompositionSelection;
|
aSelectionACP = mComposition.mSelection;
|
||||||
} else {
|
} else {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::GetSelectionInternal(), "
|
("TSF: 0x%p nsTextStore::GetSelectionInternal(), "
|
||||||
@@ -980,7 +977,8 @@ nsTextStore::GetDisplayAttribute(ITfProperty* aAttrProperty,
|
|||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::GetDisplayAttribute(): "
|
("TSF: 0x%p nsTextStore::GetDisplayAttribute(): "
|
||||||
"GetDisplayAttribute range=%ld-%ld (hr=%s)",
|
"GetDisplayAttribute range=%ld-%ld (hr=%s)",
|
||||||
this, start - mCompositionStart, start - mCompositionStart + length,
|
this, start - mComposition.mStart,
|
||||||
|
start - mComposition.mStart + length,
|
||||||
GetCommonReturnValueName(hr)));
|
GetCommonReturnValueName(hr)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1094,9 +1092,9 @@ nsTextStore::UpdateCompositionExtent(ITfRange* aRangeNew)
|
|||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::UpdateCompositionExtent(aRangeNew=0x%p), "
|
("TSF: 0x%p nsTextStore::UpdateCompositionExtent(aRangeNew=0x%p), "
|
||||||
"mCompositionView=0x%p", this, aRangeNew, mCompositionView.get()));
|
"mComposition.mView=0x%p", this, aRangeNew, mComposition.mView.get()));
|
||||||
|
|
||||||
if (!mCompositionView) {
|
if (!mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::UpdateCompositionExtent() FAILED due to "
|
("TSF: 0x%p nsTextStore::UpdateCompositionExtent() FAILED due to "
|
||||||
"no composition view", this));
|
"no composition view", this));
|
||||||
@@ -1104,7 +1102,7 @@ nsTextStore::UpdateCompositionExtent(ITfRange* aRangeNew)
|
|||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
nsRefPtr<ITfCompositionView> pComposition(mCompositionView);
|
nsRefPtr<ITfCompositionView> pComposition(mComposition.mView);
|
||||||
nsRefPtr<ITfRange> composingRange(aRangeNew);
|
nsRefPtr<ITfRange> composingRange(aRangeNew);
|
||||||
if (!composingRange) {
|
if (!composingRange) {
|
||||||
hr = pComposition->GetRange(getter_AddRefs(composingRange));
|
hr = pComposition->GetRange(getter_AddRefs(composingRange));
|
||||||
@@ -1128,12 +1126,12 @@ nsTextStore::UpdateCompositionExtent(ITfRange* aRangeNew)
|
|||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::UpdateCompositionExtent(), range=%ld-%ld, "
|
("TSF: 0x%p nsTextStore::UpdateCompositionExtent(), range=%ld-%ld, "
|
||||||
"mCompositionStart=%ld, mCompositionString.Length()=%lu",
|
"mComposition={ mStart=%ld, mString.Length()=%lu }",
|
||||||
this, compStart, compStart + compLength, mCompositionStart,
|
this, compStart, compStart + compLength, mComposition.mStart,
|
||||||
mCompositionString.Length()));
|
mComposition.mString.Length()));
|
||||||
|
|
||||||
if (mCompositionStart != compStart ||
|
if (mComposition.mStart != compStart ||
|
||||||
mCompositionString.Length() != (ULONG)compLength) {
|
mComposition.mString.Length() != (ULONG)compLength) {
|
||||||
// If the queried composition length is different from the length
|
// If the queried composition length is different from the length
|
||||||
// of our composition string, OnUpdateComposition is being called
|
// of our composition string, OnUpdateComposition is being called
|
||||||
// because a part of the original composition was committed.
|
// because a part of the original composition was committed.
|
||||||
@@ -1143,7 +1141,7 @@ nsTextStore::UpdateCompositionExtent(ITfRange* aRangeNew)
|
|||||||
OnEndComposition(pComposition);
|
OnEndComposition(pComposition);
|
||||||
OnStartCompositionInternal(pComposition, composingRange, true);
|
OnStartCompositionInternal(pComposition, composingRange, true);
|
||||||
} else {
|
} else {
|
||||||
mCompositionLength = compLength;
|
mComposition.mLength = compLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
@@ -1200,11 +1198,11 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString(), "
|
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString(), "
|
||||||
"mCompositionView=0x%p, mCompositionString=\"%s\"",
|
"mComposition={ mView=0x%p, mString=\"%s\" }",
|
||||||
this, mCompositionView.get(),
|
this, mComposition.mView.get(),
|
||||||
NS_ConvertUTF16toUTF8(mCompositionString).get()));
|
NS_ConvertUTF16toUTF8(mComposition.mString).get()));
|
||||||
|
|
||||||
if (!mCompositionView) {
|
if (!mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() FAILED "
|
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() FAILED "
|
||||||
"due to no composition view", this));
|
"due to no composition view", this));
|
||||||
@@ -1234,11 +1232,11 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
mWidget->InitEvent(event);
|
mWidget->InitEvent(event);
|
||||||
|
|
||||||
nsRefPtr<ITfRange> composingRange;
|
nsRefPtr<ITfRange> composingRange;
|
||||||
hr = mCompositionView->GetRange(getter_AddRefs(composingRange));
|
hr = mComposition.mView->GetRange(getter_AddRefs(composingRange));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() FAILED "
|
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() FAILED "
|
||||||
"due to mCompositionView->GetRange() failure", this));
|
"due to mComposition.mView->GetRange() failure", this));
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1257,7 +1255,7 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
// No matter if we have display attribute info or not,
|
// No matter if we have display attribute info or not,
|
||||||
// we always pass in at least one range to NS_TEXT_TEXT
|
// we always pass in at least one range to NS_TEXT_TEXT
|
||||||
newRange.mStartOffset = 0;
|
newRange.mStartOffset = 0;
|
||||||
newRange.mEndOffset = mCompositionString.Length();
|
newRange.mEndOffset = mComposition.mString.Length();
|
||||||
newRange.mRangeType = NS_TEXTRANGE_RAWINPUT;
|
newRange.mRangeType = NS_TEXTRANGE_RAWINPUT;
|
||||||
textRanges.AppendElement(newRange);
|
textRanges.AppendElement(newRange);
|
||||||
|
|
||||||
@@ -1269,10 +1267,10 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
nsTextRange newRange;
|
nsTextRange newRange;
|
||||||
newRange.mStartOffset = uint32_t(start - mCompositionStart);
|
newRange.mStartOffset = uint32_t(start - mComposition.mStart);
|
||||||
// The end of the last range in the array is
|
// The end of the last range in the array is
|
||||||
// always kept at the end of composition
|
// always kept at the end of composition
|
||||||
newRange.mEndOffset = mCompositionString.Length();
|
newRange.mEndOffset = mComposition.mString.Length();
|
||||||
|
|
||||||
TF_DISPLAYATTRIBUTE attr;
|
TF_DISPLAYATTRIBUTE attr;
|
||||||
hr = GetDisplayAttribute(attrPropetry, range, &attr);
|
hr = GetDisplayAttribute(attrPropetry, range, &attr);
|
||||||
@@ -1313,20 +1311,21 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
// We need to hack for Korean Input System which is Korean standard TIP.
|
// We need to hack for Korean Input System which is Korean standard TIP.
|
||||||
// It sets no change style to IME selection (the selection is always only
|
// It sets no change style to IME selection (the selection is always only
|
||||||
// one). So, the composition string looks like normal (or committed) string.
|
// one). So, the composition string looks like normal (or committed) string.
|
||||||
// At this time, mCompositionSelection range is same as the composition
|
// At this time, mComposition.mSelection range is same as the
|
||||||
// string range. Other applications set a wide caret which covers the
|
// composition string range. Other applications set a wide caret which covers
|
||||||
// composition string, however, Gecko doesn't support the wide caret drawing
|
// the composition string, however, Gecko doesn't support the wide caret
|
||||||
// now (Gecko doesn't support XOR drawing), unfortunately. For now, we should
|
// drawing now (Gecko doesn't support XOR drawing), unfortunately. For now,
|
||||||
// change the range style to undefined.
|
// we should change the range style to undefined.
|
||||||
if (mCompositionSelection.acpStart != mCompositionSelection.acpEnd &&
|
if (mComposition.mSelection.acpStart !=
|
||||||
|
mComposition.mSelection.acpEnd &&
|
||||||
textRanges.Length() == 1) {
|
textRanges.Length() == 1) {
|
||||||
nsTextRange& range = textRanges[0];
|
nsTextRange& range = textRanges[0];
|
||||||
LONG start = std::min(mCompositionSelection.acpStart,
|
LONG start = std::min(mComposition.mSelection.acpStart,
|
||||||
mCompositionSelection.acpEnd);
|
mComposition.mSelection.acpEnd);
|
||||||
LONG end = std::max(mCompositionSelection.acpStart,
|
LONG end = std::max(mComposition.mSelection.acpStart,
|
||||||
mCompositionSelection.acpEnd);
|
mComposition.mSelection.acpEnd);
|
||||||
if ((LONG)range.mStartOffset == start - mCompositionStart &&
|
if ((LONG)range.mStartOffset == start - mComposition.mStart &&
|
||||||
(LONG)range.mEndOffset == end - mCompositionStart &&
|
(LONG)range.mEndOffset == end - mComposition.mStart &&
|
||||||
range.mRangeStyle.IsNoChangeStyle()) {
|
range.mRangeStyle.IsNoChangeStyle()) {
|
||||||
range.mRangeStyle.Clear();
|
range.mRangeStyle.Clear();
|
||||||
// The looks of selected type is better than others.
|
// The looks of selected type is better than others.
|
||||||
@@ -1335,15 +1334,15 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The caret position has to be collapsed.
|
// The caret position has to be collapsed.
|
||||||
LONG caretPosition = std::max(mCompositionSelection.acpStart,
|
LONG caretPosition = std::max(mComposition.mSelection.acpStart,
|
||||||
mCompositionSelection.acpEnd);
|
mComposition.mSelection.acpEnd);
|
||||||
caretPosition -= mCompositionStart;
|
caretPosition -= mComposition.mStart;
|
||||||
nsTextRange caretRange;
|
nsTextRange caretRange;
|
||||||
caretRange.mStartOffset = caretRange.mEndOffset = uint32_t(caretPosition);
|
caretRange.mStartOffset = caretRange.mEndOffset = uint32_t(caretPosition);
|
||||||
caretRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
|
caretRange.mRangeType = NS_TEXTRANGE_CARETPOSITION;
|
||||||
textRanges.AppendElement(caretRange);
|
textRanges.AppendElement(caretRange);
|
||||||
|
|
||||||
event.theText = mCompositionString;
|
event.theText = mComposition.mString;
|
||||||
event.rangeArray = textRanges.Elements();
|
event.rangeArray = textRanges.Elements();
|
||||||
event.rangeCount = textRanges.Length();
|
event.rangeCount = textRanges.Length();
|
||||||
|
|
||||||
@@ -1356,15 +1355,15 @@ nsTextStore::SendTextEventForCompositionString()
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompositionString != mLastDispatchedCompositionString) {
|
if (mComposition.mString != mComposition.mLastData) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() "
|
("TSF: 0x%p nsTextStore::SendTextEventForCompositionString() "
|
||||||
"dispatching compositionupdate event...", this));
|
"dispatching compositionupdate event...", this));
|
||||||
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
|
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
|
||||||
mWidget);
|
mWidget);
|
||||||
mWidget->InitEvent(compositionUpdate);
|
mWidget->InitEvent(compositionUpdate);
|
||||||
compositionUpdate.data = mCompositionString;
|
compositionUpdate.data = mComposition.mString;
|
||||||
mLastDispatchedCompositionString = mCompositionString;
|
mComposition.mLastData = mComposition.mString;
|
||||||
mWidget->DispatchWindowEvent(&compositionUpdate);
|
mWidget->DispatchWindowEvent(&compositionUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1391,10 +1390,10 @@ nsTextStore::SetSelectionInternal(const TS_SELECTION_ACP* pSelection,
|
|||||||
"aDispatchTextEvent=%s), %s",
|
"aDispatchTextEvent=%s), %s",
|
||||||
this, pSelection->acpStart, pSelection->acpEnd,
|
this, pSelection->acpStart, pSelection->acpEnd,
|
||||||
GetBoolName(aDispatchTextEvent),
|
GetBoolName(aDispatchTextEvent),
|
||||||
mCompositionView ? "there is composition view" :
|
mComposition.mView ? "there is composition view" :
|
||||||
"there is no composition view"));
|
"there is no composition view"));
|
||||||
|
|
||||||
if (mCompositionView) {
|
if (mComposition.mView) {
|
||||||
if (aDispatchTextEvent) {
|
if (aDispatchTextEvent) {
|
||||||
HRESULT hr = UpdateCompositionExtent(nullptr);
|
HRESULT hr = UpdateCompositionExtent(nullptr);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@@ -1404,16 +1403,17 @@ nsTextStore::SetSelectionInternal(const TS_SELECTION_ACP* pSelection,
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pSelection->acpStart < mCompositionStart ||
|
if (pSelection->acpStart < mComposition.mStart ||
|
||||||
pSelection->acpEnd >
|
pSelection->acpEnd >
|
||||||
mCompositionStart + static_cast<LONG>(mCompositionString.Length())) {
|
mComposition.mStart +
|
||||||
|
static_cast<LONG>(mComposition.mString.Length())) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::SetSelectionInternal() FAILED due to "
|
("TSF: 0x%p nsTextStore::SetSelectionInternal() FAILED due to "
|
||||||
"the selection being out of the composition string", this));
|
"the selection being out of the composition string", this));
|
||||||
return TS_E_INVALIDPOS;
|
return TS_E_INVALIDPOS;
|
||||||
}
|
}
|
||||||
// Emulate selection during compositions
|
// Emulate selection during compositions
|
||||||
mCompositionSelection = *pSelection;
|
mComposition.mSelection = *pSelection;
|
||||||
if (aDispatchTextEvent) {
|
if (aDispatchTextEvent) {
|
||||||
HRESULT hr = SendTextEventForCompositionString();
|
HRESULT hr = SendTextEventForCompositionString();
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@@ -1492,16 +1492,16 @@ nsTextStore::GetText(LONG acpStart,
|
|||||||
LONG *pacpNext)
|
LONG *pacpNext)
|
||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::GetText(acpStart=%ld, acpEnd=%ld, pchPlain=0x%p, "
|
("TSF: 0x%p nsTextStore::GetText(acpStart=%ld, acpEnd=%ld, pchPlain=0x%p, "
|
||||||
"cchPlainReq=%lu, pcchPlainOut=0x%p, prgRunInfo=0x%p, ulRunInfoReq=%lu, "
|
"cchPlainReq=%lu, pcchPlainOut=0x%p, prgRunInfo=0x%p, ulRunInfoReq=%lu, "
|
||||||
"pulRunInfoOut=0x%p, pacpNext=0x%p), %s, mCompositionStart=%ld, "
|
"pulRunInfoOut=0x%p, pacpNext=0x%p), %s, mComposition={ mStart=%ld, "
|
||||||
"mCompositionLength=%ld, mCompositionString.Length()=%lu",
|
"mLength=%ld, mString.Length()=%lu }",
|
||||||
this, acpStart, acpEnd, pchPlain, cchPlainReq, pcchPlainOut,
|
this, acpStart, acpEnd, pchPlain, cchPlainReq, pcchPlainOut,
|
||||||
prgRunInfo, ulRunInfoReq, pulRunInfoOut, pacpNext,
|
prgRunInfo, ulRunInfoReq, pulRunInfoOut, pacpNext,
|
||||||
mCompositionView ? "there is composition view" :
|
mComposition.mView ? "there is composition view" :
|
||||||
"there is no composition view",
|
"there is no composition view",
|
||||||
mCompositionStart, mCompositionLength,
|
mComposition.mStart, mComposition.mLength,
|
||||||
mCompositionString.Length()));
|
mComposition.mString.Length()));
|
||||||
|
|
||||||
if (!IsReadLocked()) {
|
if (!IsReadLocked()) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
@@ -1540,20 +1540,22 @@ nsTextStore::GetText(LONG acpStart,
|
|||||||
}
|
}
|
||||||
if (length) {
|
if (length) {
|
||||||
LONG compNewStart = 0, compOldEnd = 0, compNewEnd = 0;
|
LONG compNewStart = 0, compOldEnd = 0, compNewEnd = 0;
|
||||||
if (mCompositionView) {
|
if (mComposition.mView) {
|
||||||
// Sometimes GetText gets called between InsertTextAtSelection and
|
// Sometimes GetText gets called between InsertTextAtSelection and
|
||||||
// OnUpdateComposition. In this case the returned text would
|
// OnUpdateComposition. In this case the returned text would
|
||||||
// be out of sync because we haven't sent NS_TEXT_TEXT in
|
// be out of sync because we haven't sent NS_TEXT_TEXT in
|
||||||
// OnUpdateComposition yet. Manually resync here.
|
// OnUpdateComposition yet. Manually resync here.
|
||||||
compOldEnd = std::min(LONG(length) + acpStart,
|
compOldEnd = std::min(LONG(length) + acpStart,
|
||||||
mCompositionLength + mCompositionStart);
|
mComposition.mLength + mComposition.mStart);
|
||||||
compNewEnd = std::min(LONG(length) + acpStart,
|
compNewEnd = std::min(LONG(length) + acpStart,
|
||||||
LONG(mCompositionString.Length()) + mCompositionStart);
|
LONG(mComposition.mString.Length()) +
|
||||||
compNewStart = std::max(acpStart, mCompositionStart);
|
mComposition.mStart);
|
||||||
|
compNewStart = std::max(acpStart, mComposition.mStart);
|
||||||
// Check if the range is affected
|
// Check if the range is affected
|
||||||
if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
|
if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
|
||||||
NS_ASSERTION(compOldEnd >= mCompositionStart &&
|
NS_ASSERTION(compOldEnd >= mComposition.mStart &&
|
||||||
compNewEnd >= mCompositionStart, "Range end is less than start\n");
|
compNewEnd >= mComposition.mStart,
|
||||||
|
"Range end is less than start\n");
|
||||||
length = uint32_t(LONG(length) + compOldEnd - compNewEnd);
|
length = uint32_t(LONG(length) + compOldEnd - compNewEnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1571,11 +1573,12 @@ nsTextStore::GetText(LONG acpStart,
|
|||||||
|
|
||||||
if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
|
if (compOldEnd > compNewStart || compNewEnd > compNewStart) {
|
||||||
// Resync composition string
|
// Resync composition string
|
||||||
const PRUnichar* compStrStart = mCompositionString.BeginReading() +
|
const PRUnichar* compStrStart =
|
||||||
std::max<LONG>(compNewStart - mCompositionStart, 0);
|
mComposition.mString.BeginReading() +
|
||||||
|
std::max<LONG>(compNewStart - mComposition.mStart, 0);
|
||||||
event.mReply.mString.Replace(compNewStart - acpStart,
|
event.mReply.mString.Replace(compNewStart - acpStart,
|
||||||
compOldEnd - mCompositionStart, compStrStart,
|
compOldEnd - mComposition.mStart, compStrStart,
|
||||||
compNewEnd - mCompositionStart);
|
compNewEnd - mComposition.mStart);
|
||||||
length = uint32_t(LONG(length) - compOldEnd + compNewEnd);
|
length = uint32_t(LONG(length) - compOldEnd + compNewEnd);
|
||||||
}
|
}
|
||||||
if (-1 != acpEnd && event.mReply.mString.Length() != length) {
|
if (-1 != acpEnd && event.mReply.mString.Length() != length) {
|
||||||
@@ -1627,8 +1630,8 @@ nsTextStore::SetText(DWORD dwFlags,
|
|||||||
pchText && cch ?
|
pchText && cch ?
|
||||||
NS_ConvertUTF16toUTF8(pchText, cch).get() : "",
|
NS_ConvertUTF16toUTF8(pchText, cch).get() : "",
|
||||||
cch, pChange,
|
cch, pChange,
|
||||||
mCompositionView ? "there is composition view" :
|
mComposition.mView ? "there is composition view" :
|
||||||
"there is no composition view"));
|
"there is no composition view"));
|
||||||
|
|
||||||
// Per SDK documentation, and since we don't have better
|
// Per SDK documentation, and since we don't have better
|
||||||
// ways to do this, this method acts as a helper to
|
// ways to do this, this method acts as a helper to
|
||||||
@@ -2263,8 +2266,8 @@ nsTextStore::InsertTextAtSelection(DWORD dwFlags,
|
|||||||
pchText,
|
pchText,
|
||||||
pchText && cch ? NS_ConvertUTF16toUTF8(pchText, cch).get() : "",
|
pchText && cch ? NS_ConvertUTF16toUTF8(pchText, cch).get() : "",
|
||||||
cch, pacpStart, pacpEnd, pChange,
|
cch, pacpStart, pacpEnd, pChange,
|
||||||
mCompositionView ? "there is composition view" :
|
mComposition.mView ? "there is composition view" :
|
||||||
"there is no composition view"));
|
"there is no composition view"));
|
||||||
|
|
||||||
if (cch && !pchText) {
|
if (cch && !pchText) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
@@ -2358,34 +2361,35 @@ nsTextStore::InsertTextAtSelectionInternal(const nsAString &aInsertStr,
|
|||||||
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal("
|
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal("
|
||||||
"aInsertStr=\"%s\", aTextChange=0x%p), %s",
|
"aInsertStr=\"%s\", aTextChange=0x%p), %s",
|
||||||
this, NS_ConvertUTF16toUTF8(aInsertStr).get(), aTextChange,
|
this, NS_ConvertUTF16toUTF8(aInsertStr).get(), aTextChange,
|
||||||
mCompositionView ? "there is composition view" :
|
mComposition.mView ? "there is composition view" :
|
||||||
"there is no composition view"));
|
"there is no composition view"));
|
||||||
|
|
||||||
TS_SELECTION_ACP oldSelection;
|
TS_SELECTION_ACP oldSelection;
|
||||||
oldSelection.acpStart = 0;
|
oldSelection.acpStart = 0;
|
||||||
oldSelection.acpEnd = 0;
|
oldSelection.acpEnd = 0;
|
||||||
|
|
||||||
if (mCompositionView) {
|
if (mComposition.mView) {
|
||||||
oldSelection = mCompositionSelection;
|
oldSelection = mComposition.mSelection;
|
||||||
// Emulate text insertion during compositions, because during a
|
// Emulate text insertion during compositions, because during a
|
||||||
// composition, editor expects the whole composition string to
|
// composition, editor expects the whole composition string to
|
||||||
// be sent in NS_TEXT_TEXT, not just the inserted part.
|
// be sent in NS_TEXT_TEXT, not just the inserted part.
|
||||||
// The actual NS_TEXT_TEXT will be sent in SetSelection or
|
// The actual NS_TEXT_TEXT will be sent in SetSelection or
|
||||||
// OnUpdateComposition.
|
// OnUpdateComposition.
|
||||||
mCompositionString.Replace(
|
mComposition.mString.Replace(
|
||||||
static_cast<uint32_t>(oldSelection.acpStart) - mCompositionStart,
|
static_cast<uint32_t>(oldSelection.acpStart) - mComposition.mStart,
|
||||||
static_cast<uint32_t>(oldSelection.acpEnd - oldSelection.acpStart),
|
static_cast<uint32_t>(oldSelection.acpEnd - oldSelection.acpStart),
|
||||||
aInsertStr);
|
aInsertStr);
|
||||||
|
|
||||||
mCompositionSelection.acpStart += aInsertStr.Length();
|
mComposition.mSelection.acpStart += aInsertStr.Length();
|
||||||
mCompositionSelection.acpEnd = mCompositionSelection.acpStart;
|
mComposition.mSelection.acpEnd =
|
||||||
mCompositionSelection.style.ase = TS_AE_END;
|
mComposition.mSelection.acpStart;
|
||||||
|
mComposition.mSelection.style.ase = TS_AE_END;
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() replaced "
|
("TSF: 0x%p nsTextStore::InsertTextAtSelectionInternal() replaced "
|
||||||
"a part of (%lu-%lu) the composition string, waiting "
|
"a part of (%lu-%lu) the composition string, waiting "
|
||||||
"SetSelection() or OnUpdateComposition()...", this,
|
"SetSelection() or OnUpdateComposition()...", this,
|
||||||
oldSelection.acpStart - mCompositionStart,
|
oldSelection.acpStart - mComposition.mStart,
|
||||||
oldSelection.acpEnd - mCompositionStart));
|
oldSelection.acpEnd - mComposition.mStart));
|
||||||
} else {
|
} else {
|
||||||
// Use actual selection if it's not composing.
|
// Use actual selection if it's not composing.
|
||||||
if (aTextChange && !GetSelectionInternal(oldSelection)) {
|
if (aTextChange && !GetSelectionInternal(oldSelection)) {
|
||||||
@@ -2508,12 +2512,13 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
|
|||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal("
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal("
|
||||||
"pComposition=0x%p, aRange=0x%p, aPreserveSelection=%s), "
|
"pComposition=0x%p, aRange=0x%p, aPreserveSelection=%s), "
|
||||||
"mCompositionView=0x%p",
|
"mComposition.mView=0x%p",
|
||||||
this, pComposition, aRange, GetBoolName(aPreserveSelection),
|
this, pComposition, aRange, GetBoolName(aPreserveSelection),
|
||||||
mCompositionView.get()));
|
mComposition.mView.get()));
|
||||||
|
|
||||||
mCompositionView = pComposition;
|
mComposition.mView = pComposition;
|
||||||
HRESULT hr = GetRangeExtent(aRange, &mCompositionStart, &mCompositionLength);
|
HRESULT hr = GetRangeExtent(aRange, &mComposition.mStart,
|
||||||
|
&mComposition.mLength);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() FAILED due "
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() FAILED due "
|
||||||
@@ -2523,8 +2528,8 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
|
|||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
||||||
"mCompositionStart=%ld, mCompositionLength=%ld",
|
"mComposition={ mStart=%ld, mLength=%ld }",
|
||||||
this, mCompositionStart, mCompositionLength));
|
this, mComposition.mStart, mComposition.mLength));
|
||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
||||||
@@ -2533,8 +2538,8 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
|
|||||||
// Select composition range so the new composition replaces the range
|
// Select composition range so the new composition replaces the range
|
||||||
nsSelectionEvent selEvent(true, NS_SELECTION_SET, mWidget);
|
nsSelectionEvent selEvent(true, NS_SELECTION_SET, mWidget);
|
||||||
mWidget->InitEvent(selEvent);
|
mWidget->InitEvent(selEvent);
|
||||||
selEvent.mOffset = uint32_t(mCompositionStart);
|
selEvent.mOffset = uint32_t(mComposition.mStart);
|
||||||
selEvent.mLength = uint32_t(mCompositionLength);
|
selEvent.mLength = uint32_t(mComposition.mLength);
|
||||||
selEvent.mReversed = false;
|
selEvent.mReversed = false;
|
||||||
mWidget->DispatchWindowEvent(&selEvent);
|
mWidget->DispatchWindowEvent(&selEvent);
|
||||||
if (!selEvent.mSucceeded) {
|
if (!selEvent.mSucceeded) {
|
||||||
@@ -2559,12 +2564,13 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
|
|||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal(), "
|
||||||
"dispatching compositionstart event..."));
|
"dispatching compositionstart event..."));
|
||||||
|
|
||||||
mCompositionString = queryEvent.mReply.mString;
|
mComposition.mString = queryEvent.mReply.mString;
|
||||||
if (!aPreserveSelection) {
|
if (!aPreserveSelection) {
|
||||||
mCompositionSelection.acpStart = mCompositionStart;
|
mComposition.mSelection.acpStart = mComposition.mStart;
|
||||||
mCompositionSelection.acpEnd = mCompositionStart + mCompositionLength;
|
mComposition.mSelection.acpEnd =
|
||||||
mCompositionSelection.style.ase = TS_AE_END;
|
mComposition.mStart + mComposition.mLength;
|
||||||
mCompositionSelection.style.fInterimChar = FALSE;
|
mComposition.mSelection.style.ase = TS_AE_END;
|
||||||
|
mComposition.mSelection.style.fInterimChar = FALSE;
|
||||||
}
|
}
|
||||||
nsCompositionEvent event(true, NS_COMPOSITION_START, mWidget);
|
nsCompositionEvent event(true, NS_COMPOSITION_START, mWidget);
|
||||||
mWidget->InitEvent(event);
|
mWidget->InitEvent(event);
|
||||||
@@ -2572,41 +2578,30 @@ nsTextStore::OnStartCompositionInternal(ITfCompositionView* pComposition,
|
|||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() succeeded: "
|
("TSF: 0x%p nsTextStore::OnStartCompositionInternal() succeeded: "
|
||||||
"mCompositionStart=%ld, mCompositionLength=%ld, "
|
"mComposition={ mStart=%ld, mLength=%ld, "
|
||||||
"mCompositionSelection={ acpStart=%ld, acpEnd=%ld, style.ase=%s, "
|
"mSelection={ acpStart=%ld, acpEnd=%ld, style.ase=%s, "
|
||||||
"style.iInterimChar=%s }",
|
"style.iInterimChar=%s } }",
|
||||||
this, mCompositionStart, mCompositionLength,
|
this, mComposition.mStart, mComposition.mLength,
|
||||||
mCompositionSelection.acpStart, mCompositionSelection.acpEnd,
|
mComposition.mSelection.acpStart,
|
||||||
GetActiveSelEndName(mCompositionSelection.style.ase),
|
mComposition.mSelection.acpEnd,
|
||||||
GetBoolName(mCompositionSelection.style.fInterimChar)));
|
GetActiveSelEndName(mComposition.mSelection.style.ase),
|
||||||
|
GetBoolName(mComposition.mSelection.style.fInterimChar)));
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t
|
|
||||||
GetLayoutChangeIntervalTime()
|
|
||||||
{
|
|
||||||
static int32_t sTime = -1;
|
|
||||||
if (sTime > 0)
|
|
||||||
return uint32_t(sTime);
|
|
||||||
|
|
||||||
sTime = std::max(10,
|
|
||||||
Preferences::GetInt("intl.tsf.on_layout_change_interval", 100));
|
|
||||||
return uint32_t(sTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
nsTextStore::OnStartComposition(ITfCompositionView* pComposition,
|
nsTextStore::OnStartComposition(ITfCompositionView* pComposition,
|
||||||
BOOL* pfOk)
|
BOOL* pfOk)
|
||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnStartComposition(pComposition=0x%p, "
|
("TSF: 0x%p nsTextStore::OnStartComposition(pComposition=0x%p, "
|
||||||
"pfOk=0x%p), mCompositionView=0x%p",
|
"pfOk=0x%p), mComposition.mView=0x%p",
|
||||||
this, pComposition, pfOk, mCompositionView.get()));
|
this, pComposition, pfOk, mComposition.mView.get()));
|
||||||
|
|
||||||
*pfOk = FALSE;
|
*pfOk = FALSE;
|
||||||
|
|
||||||
// Only one composition at a time
|
// Only one composition at a time
|
||||||
if (mCompositionView) {
|
if (mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnStartComposition() FAILED due to "
|
("TSF: 0x%p nsTextStore::OnStartComposition() FAILED due to "
|
||||||
"there is another composition already (but returns S_OK)", this));
|
"there is another composition already (but returns S_OK)", this));
|
||||||
@@ -2629,13 +2624,8 @@ nsTextStore::OnStartComposition(ITfCompositionView* pComposition,
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_ASSERTION(!mCompositionTimer, "The timer is alive!");
|
mComposition.StartLayoutChangeTimer(this);
|
||||||
mCompositionTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
|
||||||
if (mCompositionTimer) {
|
|
||||||
mCompositionTimer->InitWithFuncCallback(CompositionTimerCallbackFunc, this,
|
|
||||||
GetLayoutChangeIntervalTime(),
|
|
||||||
nsITimer::TYPE_REPEATING_SLACK);
|
|
||||||
}
|
|
||||||
*pfOk = TRUE;
|
*pfOk = TRUE;
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnStartComposition() succeeded", this));
|
("TSF: 0x%p nsTextStore::OnStartComposition() succeeded", this));
|
||||||
@@ -2648,8 +2638,8 @@ nsTextStore::OnUpdateComposition(ITfCompositionView* pComposition,
|
|||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnUpdateComposition(pComposition=0x%p, "
|
("TSF: 0x%p nsTextStore::OnUpdateComposition(pComposition=0x%p, "
|
||||||
"pRangeNew=0x%p), mCompositionView=0x%p",
|
"pRangeNew=0x%p), mComposition.mView=0x%p",
|
||||||
this, pComposition, pRangeNew, mCompositionView.get()));
|
this, pComposition, pRangeNew, mComposition.mView.get()));
|
||||||
|
|
||||||
if (!mDocumentMgr || !mContext) {
|
if (!mDocumentMgr || !mContext) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
@@ -2657,13 +2647,13 @@ nsTextStore::OnUpdateComposition(ITfCompositionView* pComposition,
|
|||||||
"not ready for the composition", this));
|
"not ready for the composition", this));
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
if (!mCompositionView) {
|
if (!mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnUpdateComposition() FAILED due to "
|
("TSF: 0x%p nsTextStore::OnUpdateComposition() FAILED due to "
|
||||||
"no active composition", this));
|
"no active composition", this));
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
if (mCompositionView != pComposition) {
|
if (mComposition.mView != pComposition) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnUpdateComposition() FAILED due to "
|
("TSF: 0x%p nsTextStore::OnUpdateComposition() FAILED due to "
|
||||||
"different composition view specified", this));
|
"different composition view specified", this));
|
||||||
@@ -2696,14 +2686,15 @@ nsTextStore::OnUpdateComposition(ITfCompositionView* pComposition,
|
|||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnUpdateComposition() succeeded: "
|
("TSF: 0x%p nsTextStore::OnUpdateComposition() succeeded: "
|
||||||
"mCompositionStart=%ld, mCompositionLength=%ld, "
|
"mComposition={ mStart=%ld, mLength=%ld, "
|
||||||
"mCompositionSelection={ acpStart=%ld, acpEnd=%ld, style.ase=%s, "
|
"mSelection={ acpStart=%ld, acpEnd=%ld, style.ase=%s, "
|
||||||
"style.iInterimChar=%s }, mCompositionString=\"%s\"",
|
"style.iInterimChar=%s }, mString=\"%s\" }",
|
||||||
this, mCompositionStart, mCompositionLength,
|
this, mComposition.mStart, mComposition.mLength,
|
||||||
mCompositionSelection.acpStart, mCompositionSelection.acpEnd,
|
mComposition.mSelection.acpStart,
|
||||||
GetActiveSelEndName(mCompositionSelection.style.ase),
|
mComposition.mSelection.acpEnd,
|
||||||
GetBoolName(mCompositionSelection.style.fInterimChar),
|
GetActiveSelEndName(mComposition.mSelection.style.ase),
|
||||||
NS_ConvertUTF16toUTF8(mCompositionString).get()));
|
GetBoolName(mComposition.mSelection.style.fInterimChar),
|
||||||
|
NS_ConvertUTF16toUTF8(mComposition.mString).get()));
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2712,18 +2703,18 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
|
|||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnEndComposition(pComposition=0x%p), "
|
("TSF: 0x%p nsTextStore::OnEndComposition(pComposition=0x%p), "
|
||||||
"mCompositionView=0x%p, mCompositionString=\"%s\"",
|
"mComposition={ mView=0x%p, mString=\"%s\" }",
|
||||||
this, pComposition, mCompositionView.get(),
|
this, pComposition, mComposition.mView.get(),
|
||||||
NS_ConvertUTF16toUTF8(mCompositionString).get()));
|
NS_ConvertUTF16toUTF8(mComposition.mString).get()));
|
||||||
|
|
||||||
if (!mCompositionView) {
|
if (!mComposition.mView) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnEndComposition() FAILED due to "
|
("TSF: 0x%p nsTextStore::OnEndComposition() FAILED due to "
|
||||||
"no active composition", this));
|
"no active composition", this));
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompositionView != pComposition) {
|
if (mComposition.mView != pComposition) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
PR_LOG(sTextStoreLog, PR_LOG_ERROR,
|
||||||
("TSF: 0x%p nsTextStore::OnEndComposition() FAILED due to "
|
("TSF: 0x%p nsTextStore::OnEndComposition() FAILED due to "
|
||||||
"different composition view specified", this));
|
"different composition view specified", this));
|
||||||
@@ -2733,20 +2724,17 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
|
|||||||
// Clear the saved text event
|
// Clear the saved text event
|
||||||
SaveTextEvent(nullptr);
|
SaveTextEvent(nullptr);
|
||||||
|
|
||||||
if (mCompositionTimer) {
|
mComposition.EnsureLayoutChangeTimerStopped();
|
||||||
mCompositionTimer->Cancel();
|
|
||||||
mCompositionTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCompositionString != mLastDispatchedCompositionString) {
|
if (mComposition.mString != mComposition.mLastData) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnEndComposition(), "
|
("TSF: 0x%p nsTextStore::OnEndComposition(), "
|
||||||
"dispatching compositionupdate event...", this));
|
"dispatching compositionupdate event...", this));
|
||||||
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
|
nsCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE,
|
||||||
mWidget);
|
mWidget);
|
||||||
mWidget->InitEvent(compositionUpdate);
|
mWidget->InitEvent(compositionUpdate);
|
||||||
compositionUpdate.data = mCompositionString;
|
compositionUpdate.data = mComposition.mString;
|
||||||
mLastDispatchedCompositionString = mCompositionString;
|
mComposition.mLastData = mComposition.mString;
|
||||||
mWidget->DispatchWindowEvent(&compositionUpdate);
|
mWidget->DispatchWindowEvent(&compositionUpdate);
|
||||||
if (!mWidget || mWidget->Destroyed()) {
|
if (!mWidget || mWidget->Destroyed()) {
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
@@ -2763,7 +2751,7 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
|
|||||||
// Use NS_TEXT_TEXT to commit composition string
|
// Use NS_TEXT_TEXT to commit composition string
|
||||||
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
|
nsTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
|
||||||
mWidget->InitEvent(textEvent);
|
mWidget->InitEvent(textEvent);
|
||||||
textEvent.theText = mCompositionString;
|
textEvent.theText = mComposition.mString;
|
||||||
textEvent.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
textEvent.theText.ReplaceSubstring(NS_LITERAL_STRING("\r\n"),
|
||||||
NS_LITERAL_STRING("\n"));
|
NS_LITERAL_STRING("\n"));
|
||||||
mWidget->DispatchWindowEvent(&textEvent);
|
mWidget->DispatchWindowEvent(&textEvent);
|
||||||
@@ -2780,7 +2768,7 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
|
|||||||
"dispatching compositionend event...", this));
|
"dispatching compositionend event...", this));
|
||||||
|
|
||||||
nsCompositionEvent event(true, NS_COMPOSITION_END, mWidget);
|
nsCompositionEvent event(true, NS_COMPOSITION_END, mWidget);
|
||||||
event.data = mLastDispatchedCompositionString;
|
event.data = mComposition.mLastData;
|
||||||
mWidget->InitEvent(event);
|
mWidget->InitEvent(event);
|
||||||
mWidget->DispatchWindowEvent(&event);
|
mWidget->DispatchWindowEvent(&event);
|
||||||
|
|
||||||
@@ -2791,12 +2779,12 @@ nsTextStore::OnEndComposition(ITfCompositionView* pComposition)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
mCompositionView = NULL;
|
mComposition.mView = NULL;
|
||||||
mCompositionString.Truncate(0);
|
mComposition.mString.Truncate(0);
|
||||||
mLastDispatchedCompositionString.Truncate();
|
mComposition.mLastData.Truncate();
|
||||||
|
|
||||||
// Maintain selection
|
// Maintain selection
|
||||||
SetSelectionInternal(&mCompositionSelection);
|
SetSelectionInternal(&mComposition.mSelection);
|
||||||
|
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnEndComposition(), succeeded", this));
|
("TSF: 0x%p nsTextStore::OnEndComposition(), succeeded", this));
|
||||||
@@ -2910,7 +2898,7 @@ nsTextStore::OnSelectionChangeInternal(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsTextStore::OnCompositionTimer()
|
nsTextStore::OnLayoutChange()
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
|
||||||
NS_ENSURE_TRUE(mSink, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(mSink, NS_ERROR_FAILURE);
|
||||||
@@ -2920,7 +2908,7 @@ nsTextStore::OnCompositionTimer()
|
|||||||
// this only when the composition string screen position is changed by window
|
// this only when the composition string screen position is changed by window
|
||||||
// moving, resizing. And also reflowing and scrolling the contents.
|
// moving, resizing. And also reflowing and scrolling the contents.
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::OnCompositionTimer(), calling "
|
("TSF: 0x%p nsTextStore::OnLayoutChange(), calling "
|
||||||
"mSink->OnLayoutChange()...", this));
|
"mSink->OnLayoutChange()...", this));
|
||||||
HRESULT hr = mSink->OnLayoutChange(TS_LC_CHANGE, TEXTSTORE_DEFAULT_VIEW);
|
HRESULT hr = mSink->OnLayoutChange(TS_LC_CHANGE, TEXTSTORE_DEFAULT_VIEW);
|
||||||
NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE);
|
||||||
@@ -2933,19 +2921,20 @@ nsTextStore::CommitCompositionInternal(bool aDiscard)
|
|||||||
{
|
{
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
|
||||||
("TSF: 0x%p nsTextStore::CommitCompositionInternal(aDiscard=%s), "
|
("TSF: 0x%p nsTextStore::CommitCompositionInternal(aDiscard=%s), "
|
||||||
"mLock=%s, mSink=0x%p, mContext=0x%p, mCompositionView=0x%p, "
|
"mLock=%s, mSink=0x%p, mContext=0x%p, mComposition.mView=0x%p, "
|
||||||
"mCompositionString=\"%s\"",
|
"mComposition.mString=\"%s\"",
|
||||||
this, GetBoolName(aDiscard), GetLockFlagNameStr(mLock).get(),
|
this, GetBoolName(aDiscard), GetLockFlagNameStr(mLock).get(),
|
||||||
mSink.get(), mContext.get(), mCompositionView.get(),
|
mSink.get(), mContext.get(), mComposition.mView.get(),
|
||||||
NS_ConvertUTF16toUTF8(mCompositionString).get()));
|
NS_ConvertUTF16toUTF8(mComposition.mString).get()));
|
||||||
|
|
||||||
if (mCompositionView && aDiscard) {
|
if (mComposition.mView && aDiscard) {
|
||||||
mCompositionString.Truncate(0);
|
mComposition.mString.Truncate(0);
|
||||||
if (mSink && !mLock) {
|
if (mSink && !mLock) {
|
||||||
TS_TEXTCHANGE textChange;
|
TS_TEXTCHANGE textChange;
|
||||||
textChange.acpStart = mCompositionStart;
|
textChange.acpStart = mComposition.mStart;
|
||||||
textChange.acpOldEnd = mCompositionStart + mCompositionLength;
|
textChange.acpOldEnd =
|
||||||
textChange.acpNewEnd = mCompositionStart;
|
mComposition.mStart + mComposition.mLength;
|
||||||
|
textChange.acpNewEnd = mComposition.mStart;
|
||||||
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
|
||||||
("TSF: 0x%p nsTextStore::CommitCompositionInternal(), calling"
|
("TSF: 0x%p nsTextStore::CommitCompositionInternal(), calling"
|
||||||
"mSink->OnTextChange(0, { acpStart=%ld, acpOldEnd=%ld, "
|
"mSink->OnTextChange(0, { acpStart=%ld, acpOldEnd=%ld, "
|
||||||
@@ -3178,6 +3167,51 @@ nsTextStore::Terminate(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************/
|
||||||
|
/* nsTextStore::Composition */
|
||||||
|
/******************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextStore::Composition::StartLayoutChangeTimer(nsTextStore* aTextStore)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!mLayoutChangeTimer);
|
||||||
|
mLayoutChangeTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||||
|
mLayoutChangeTimer->InitWithFuncCallback(TimerCallback, aTextStore,
|
||||||
|
GetLayoutChangeIntervalTime(), nsITimer::TYPE_REPEATING_SLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTextStore::Composition::EnsureLayoutChangeTimerStopped()
|
||||||
|
{
|
||||||
|
if (!mLayoutChangeTimer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mLayoutChangeTimer->Cancel();
|
||||||
|
mLayoutChangeTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void
|
||||||
|
nsTextStore::Composition::TimerCallback(nsITimer* aTimer, void* aClosure)
|
||||||
|
{
|
||||||
|
nsTextStore *ts = static_cast<nsTextStore*>(aClosure);
|
||||||
|
ts->OnLayoutChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
uint32_t
|
||||||
|
nsTextStore::Composition::GetLayoutChangeIntervalTime()
|
||||||
|
{
|
||||||
|
static int32_t sTime = -1;
|
||||||
|
if (sTime > 0) {
|
||||||
|
return static_cast<uint32_t>(sTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
sTime = std::max(10,
|
||||||
|
Preferences::GetInt("intl.tsf.on_layout_change_interval", 100));
|
||||||
|
return static_cast<uint32_t>(sTime);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// static
|
// static
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -139,12 +139,6 @@ public:
|
|||||||
|
|
||||||
static nsIMEUpdatePreference GetIMEUpdatePreference();
|
static nsIMEUpdatePreference GetIMEUpdatePreference();
|
||||||
|
|
||||||
static void CompositionTimerCallbackFunc(nsITimer *aTimer, void *aClosure)
|
|
||||||
{
|
|
||||||
nsTextStore *ts = static_cast<nsTextStore*>(aClosure);
|
|
||||||
ts->OnCompositionTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CanOptimizeKeyAndIMEMessages()
|
static bool CanOptimizeKeyAndIMEMessages()
|
||||||
{
|
{
|
||||||
// TODO: We need to implement this for ATOK.
|
// TODO: We need to implement this for ATOK.
|
||||||
@@ -185,7 +179,7 @@ public:
|
|||||||
|
|
||||||
static bool IsComposing()
|
static bool IsComposing()
|
||||||
{
|
{
|
||||||
return (sTsfTextStore && sTsfTextStore->mCompositionView != nullptr);
|
return (sTsfTextStore && sTsfTextStore->mComposition.mView != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsComposingOn(nsWindowBase* aWidget)
|
static bool IsComposingOn(nsWindowBase* aWidget)
|
||||||
@@ -239,7 +233,7 @@ protected:
|
|||||||
HRESULT UpdateCompositionExtent(ITfRange* pRangeNew);
|
HRESULT UpdateCompositionExtent(ITfRange* pRangeNew);
|
||||||
HRESULT SendTextEventForCompositionString();
|
HRESULT SendTextEventForCompositionString();
|
||||||
HRESULT SaveTextEvent(const nsTextEvent* aEvent);
|
HRESULT SaveTextEvent(const nsTextEvent* aEvent);
|
||||||
nsresult OnCompositionTimer();
|
nsresult OnLayoutChange();
|
||||||
HRESULT ProcessScopeRequest(DWORD dwFlags,
|
HRESULT ProcessScopeRequest(DWORD dwFlags,
|
||||||
ULONG cFilterAttrs,
|
ULONG cFilterAttrs,
|
||||||
const TS_ATTRID *paFilterAttrs);
|
const TS_ATTRID *paFilterAttrs);
|
||||||
@@ -263,32 +257,53 @@ protected:
|
|||||||
DWORD mLockQueued;
|
DWORD mLockQueued;
|
||||||
// Cumulative text change offsets since the last notification
|
// Cumulative text change offsets since the last notification
|
||||||
TS_TEXTCHANGE mTextChange;
|
TS_TEXTCHANGE mTextChange;
|
||||||
// NULL if no composition is active, otherwise the current composition
|
|
||||||
nsRefPtr<ITfCompositionView> mCompositionView;
|
class Composition MOZ_FINAL
|
||||||
// Current copy of the active composition string. Only mCompositionString is
|
{
|
||||||
// changed during a InsertTextAtSelection call if we have a composition.
|
public:
|
||||||
// mCompositionString acts as a buffer until OnUpdateComposition is called
|
// NULL if no composition is active, otherwise the current composition
|
||||||
// and mCompositionString is flushed to editor through NS_TEXT_TEXT. This
|
nsRefPtr<ITfCompositionView> mView;
|
||||||
// way all changes are updated in batches to avoid inconsistencies/artifacts.
|
|
||||||
nsString mCompositionString;
|
// Current copy of the active composition string. Only mString is
|
||||||
// "Current selection" during a composition, in ACP offsets.
|
// changed during a InsertTextAtSelection call if we have a composition.
|
||||||
// We use a fake selection during a composition because editor code doesn't
|
// mString acts as a buffer until OnUpdateComposition is called
|
||||||
// like us accessing the actual selection during a composition. So we leave
|
// and mString is flushed to editor through NS_TEXT_TEXT. This
|
||||||
// the actual selection alone and get/set mCompositionSelection instead
|
// way all changes are updated in batches to avoid
|
||||||
// during GetSelection/SetSelection calls.
|
// inconsistencies/artifacts.
|
||||||
TS_SELECTION_ACP mCompositionSelection;
|
nsString mString;
|
||||||
// The start and length of the current active composition, in ACP offsets
|
|
||||||
LONG mCompositionStart;
|
// The latest composition string which was dispatched by composition update
|
||||||
LONG mCompositionLength;
|
// event.
|
||||||
|
nsString mLastData;
|
||||||
|
|
||||||
|
// "Current selection" during a composition, in ACP offsets.
|
||||||
|
// We use a fake selection during a composition because editor code doesn't
|
||||||
|
// like us accessing the actual selection during a composition. So we leave
|
||||||
|
// the actual selection alone and get/set mSelection instead
|
||||||
|
// during GetSelection/SetSelection calls.
|
||||||
|
TS_SELECTION_ACP mSelection;
|
||||||
|
|
||||||
|
// The start and length of the current active composition, in ACP offsets
|
||||||
|
LONG mStart;
|
||||||
|
LONG mLength;
|
||||||
|
|
||||||
|
void StartLayoutChangeTimer(nsTextStore* aTextStore);
|
||||||
|
void EnsureLayoutChangeTimerStopped();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Timer for calling ITextStoreACPSink::OnLayoutChange(). This is only used
|
||||||
|
// during composing.
|
||||||
|
nsCOMPtr<nsITimer> mLayoutChangeTimer;
|
||||||
|
|
||||||
|
static void TimerCallback(nsITimer* aTimer, void *aClosure);
|
||||||
|
static uint32_t GetLayoutChangeIntervalTime();
|
||||||
|
};
|
||||||
|
// Storing current composition.
|
||||||
|
Composition mComposition;
|
||||||
|
|
||||||
// The latest text event which was dispatched for composition string
|
// The latest text event which was dispatched for composition string
|
||||||
// of the current composing transaction.
|
// of the current composing transaction.
|
||||||
nsTextEvent* mLastDispatchedTextEvent;
|
nsTextEvent* mLastDispatchedTextEvent;
|
||||||
// The latest composition string which was dispatched by composition update
|
|
||||||
// event.
|
|
||||||
nsString mLastDispatchedCompositionString;
|
|
||||||
// Timer for calling ITextStoreACPSink::OnLayoutChange. This is only used
|
|
||||||
// during composing.
|
|
||||||
nsCOMPtr<nsITimer> mCompositionTimer;
|
|
||||||
// The input scopes for this context, defaults to IS_DEFAULT.
|
// The input scopes for this context, defaults to IS_DEFAULT.
|
||||||
nsTArray<InputScope> mInputScopes;
|
nsTArray<InputScope> mInputScopes;
|
||||||
bool mInputScopeDetected;
|
bool mInputScopeDetected;
|
||||||
|
|||||||
Reference in New Issue
Block a user