From 6ab28ab8040ea967c53e6953e5447572d5254ae1 Mon Sep 17 00:00:00 2001 From: Masayuki Nakano Date: Thu, 11 Jul 2013 16:46:35 +0900 Subject: [PATCH] Bug 875674 part.4 Implement firstRectForCharacterRange:actualRange: of NSTextInputClient r=roc+smichaud --- content/events/src/nsContentEventHandler.cpp | 23 +++++++++++++-- content/events/src/nsContentEventHandler.h | 3 +- widget/cocoa/TextInputHandler.h | 5 +++- widget/cocoa/TextInputHandler.mm | 30 +++++++++++++++----- widget/cocoa/nsChildView.mm | 7 +++++ 5 files changed, 56 insertions(+), 12 deletions(-) diff --git a/content/events/src/nsContentEventHandler.cpp b/content/events/src/nsContentEventHandler.cpp index 3d552fd9cd1a..727cb9b5d627 100644 --- a/content/events/src/nsContentEventHandler.cpp +++ b/content/events/src/nsContentEventHandler.cpp @@ -372,8 +372,13 @@ nsContentEventHandler::SetRangeFromFlatTextOffset( nsRange* aRange, uint32_t aNativeOffset, uint32_t aNativeLength, - bool aExpandToClusterBoundaries) + bool aExpandToClusterBoundaries, + uint32_t* aNewNativeOffset) { + if (aNewNativeOffset) { + *aNewNativeOffset = aNativeOffset; + } + nsCOMPtr iter = NS_NewPreContentIterator(); nsresult rv = iter->Init(mRootContent); NS_ENSURE_SUCCESS(rv, rv); @@ -404,8 +409,12 @@ nsContentEventHandler::SetRangeFromFlatTextOffset( ConvertToXPOffset(content, aNativeOffset - nativeOffset) : 0; if (aExpandToClusterBoundaries) { + uint32_t oldXPOffset = xpOffset; rv = ExpandToClusterBoundary(content, false, &xpOffset); NS_ENSURE_SUCCESS(rv, rv); + if (aNewNativeOffset) { + *aNewNativeOffset -= (oldXPOffset - xpOffset); + } } rv = aRange->SetStart(domNode, int32_t(xpOffset)); @@ -456,6 +465,9 @@ nsContentEventHandler::SetRangeFromFlatTextOffset( MOZ_ASSERT(!mRootContent->IsNodeOfType(nsINode::eTEXT)); rv = aRange->SetStart(domNode, int32_t(mRootContent->GetChildCount())); NS_ENSURE_SUCCESS(rv, rv); + if (aNewNativeOffset) { + *aNewNativeOffset = nativeOffset; + } } rv = aRange->SetEnd(domNode, int32_t(mRootContent->GetChildCount())); NS_ASSERTION(NS_SUCCEEDED(rv), "nsIDOMRange::SetEnd failed"); @@ -574,7 +586,10 @@ nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent) nsRefPtr range = new nsRange(mRootContent); rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, - aEvent->mInput.mLength, true); + aEvent->mInput.mLength, true, + &aEvent->mReply.mOffset); + NS_ENSURE_SUCCESS(rv, rv); + rv = GenerateFlatTextContent(range, aEvent->mReply.mString); NS_ENSURE_SUCCESS(rv, rv); // used to iterate over all contents and their frames @@ -717,6 +732,7 @@ nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent) NS_ENSURE_SUCCESS(rv, rv); aEvent->mReply.mRect = rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel()); + aEvent->mReply.mOffset = aEvent->mInput.mOffset; aEvent->mSucceeded = true; return NS_OK; } @@ -724,7 +740,8 @@ nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent) // Otherwise, we should set the guessed caret rect. nsRefPtr range = new nsRange(mRootContent); - rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, true); + rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, true, + &aEvent->mReply.mOffset); NS_ENSURE_SUCCESS(rv, rv); int32_t offsetInFrame; diff --git a/content/events/src/nsContentEventHandler.h b/content/events/src/nsContentEventHandler.h index 4c4f492e9b33..493ee3288623 100644 --- a/content/events/src/nsContentEventHandler.h +++ b/content/events/src/nsContentEventHandler.h @@ -91,7 +91,8 @@ protected: nsresult SetRangeFromFlatTextOffset(nsRange* aRange, uint32_t aNativeOffset, uint32_t aNativeLength, - bool aExpandToClusterBoundaries); + bool aExpandToClusterBoundaries, + uint32_t* aNewNativeOffset = nullptr); // Find the first textframe for the range, and get the start offset in // the frame. nsresult GetStartFrameAndOffset(nsRange* aRange, diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h index 8f4b0fb76f3d..2eaef0ae1a9a 100644 --- a/widget/cocoa/TextInputHandler.h +++ b/widget/cocoa/TextInputHandler.h @@ -874,12 +874,15 @@ public: * @param aRange A range of text to examine. Its position is * an offset from the beginning of the focused * editor or document. + * @param aActualRange If this is not null, this returns the actual + * range used for computing the result. * @return An NSRect containing the first character in * aRange, in screen coordinates. * If the length of aRange is 0, the width will * be 0. */ - NSRect FirstRectForCharacterRange(NSRange& aRange); + NSRect FirstRectForCharacterRange(NSRange& aRange, + NSRange* aActualRange = nullptr); /** * CharacterIndexForPoint() returns an offset of a character at aPoint. diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index 72b849aa52b7..4193b835fe43 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -2893,20 +2893,26 @@ IMEInputHandler::SelectedRange() } NSRect -IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange) +IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange, + NSRange* aActualRange) { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; PR_LOG(gLog, PR_LOG_ALWAYS, - ("%p IMEInputHandler::FirstRectForCharacterRange, Destroyed()=%s" - "aRange={ location=%llu, length=%llu }", - this, TrueOrFalse(Destroyed()), aRange.location, aRange.length)); + ("%p IMEInputHandler::FirstRectForCharacterRange, Destroyed()=%s, " + "aRange={ location=%llu, length=%llu }, aActualRange=%p }", + this, TrueOrFalse(Destroyed()), aRange.location, aRange.length, + aActualRange)); // XXX this returns first character rect or caret rect, it is limitation of // now. We need more work for returns first line rect. But current // implementation is enough for IMEs. - NSRect rect; + NSRect rect = NSMakeRect(0.0, 0.0, 0.0, 0.0); + NSRange actualRange = NSMakeRange(NSNotFound, 0); + if (aActualRange) { + *aActualRange = actualRange; + } if (Destroyed() || aRange.location == NSNotFound) { return rect; } @@ -2921,6 +2927,8 @@ IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange) DispatchEvent(charRect); if (charRect.mSucceeded) { r = charRect.mReply.mRect; + actualRange.location = charRect.mReply.mOffset; + actualRange.length = charRect.mReply.mString.Length(); } else { useCaretRect = true; } @@ -2935,6 +2943,8 @@ IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange) } r = caretRect.mReply.mRect; r.width = 0; + actualRange.location = caretRect.mReply.mOffset; + actualRange.length = 0; } nsIWidget* rootWidget = mWidget->GetTopLevelWidget(); @@ -2949,11 +2959,17 @@ IMEInputHandler::FirstRectForCharacterRange(NSRange& aRange) rect = [rootView convertRect:rect toView:nil]; rect.origin = [rootWindow convertBaseToScreen:rect.origin]; + if (aActualRange) { + *aActualRange = actualRange; + } + PR_LOG(gLog, PR_LOG_ALWAYS, ("%p IMEInputHandler::FirstRectForCharacterRange, " - "useCaretRect=%s rect={ x=%f, y=%f, width=%f, height=%f }", + "useCaretRect=%s rect={ x=%f, y=%f, width=%f, height=%f }, " + "actualRange={ location=%llu, length=%llu }", this, TrueOrFalse(useCaretRect), rect.origin.x, rect.origin.y, - rect.size.width, rect.size.height)); + rect.size.width, rect.size.height, actualRange.location, + actualRange.length)); return rect; diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 7424acdf2144..ccead189d23e 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -5095,6 +5095,13 @@ static int32_t RoundUp(double aDouble) #pragma mark - // NSTextInputClient implementation +- (NSRect)firstRectForCharacterRange:(NSRange)aRange + actualRange:(NSRangePointer)actualRange +{ + NS_ENSURE_TRUE(mTextInputHandler, NSMakeRect(0.0, 0.0, 0.0, 0.0)); + return mTextInputHandler->FirstRectForCharacterRange(aRange, actualRange); +} + - (NSInteger)windowLevel { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;