nsresult nsQueryContentEventHandler::OnQueryCharacterRect(nsQueryContentEvent* aEvent) { nsresult rv = Init(aEvent); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIRange> range = new nsRange(); NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY); rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 1, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); if (range->Collapsed()) { // There is no character at the offset. return NS_OK; } return QueryRectFor(aEvent, range, nsnull); }
nsresult nsQueryContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent) { nsresult rv = Init(aEvent); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsICaret> caret; rv = mPresShell->GetCaret(getter_AddRefs(caret)); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(caret, "GetCaret succeeded, but the result is null"); // When the selection is collapsed and the queried offset is current caret // position, we should return the "real" caret rect. PRBool selectionIsCollapsed; rv = mSelection->GetIsCollapsed(&selectionIsCollapsed); NS_ENSURE_SUCCESS(rv, rv); if (selectionIsCollapsed) { PRUint32 offset; rv = GetFlatTextOffsetOfRange(mFirstSelectedRange, &offset); NS_ENSURE_SUCCESS(rv, rv); if (offset == aEvent->mInput.mOffset) { PRBool isCollapsed; rv = caret->GetCaretCoordinates(nsICaret::eTopLevelWindowCoordinates, mSelection, &aEvent->mReply.mRect, &isCollapsed, nsnull); NS_ENSURE_SUCCESS(rv, rv); aEvent->mSucceeded = PR_TRUE; return NS_OK; } } // Otherwise, we should set the guessed caret rect. nsCOMPtr<nsIRange> range = new nsRange(); NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY); rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); return QueryRectFor(aEvent, range, caret); }
nsresult nsContentEventHandler::OnQueryTextContent(nsQueryContentEvent* aEvent) { nsresult rv = Init(aEvent); if (NS_FAILED(rv)) return rv; NS_ASSERTION(aEvent->mReply.mString.IsEmpty(), "The reply string must be empty"); nsRefPtr<nsRange> range = new nsRange(); rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, aEvent->mInput.mLength, false); NS_ENSURE_SUCCESS(rv, rv); rv = GenerateFlatTextContent(range, aEvent->mReply.mString); NS_ENSURE_SUCCESS(rv, rv); aEvent->mSucceeded = true; return NS_OK; }
nsresult nsContentEventHandler::OnSelectionEvent(nsSelectionEvent* aEvent) { aEvent->mSucceeded = PR_FALSE; // Get selection to manipulate // XXX why do we need to get them from ISM? This method should work fine // without ISM. nsresult rv = nsIMEStateManager:: GetFocusSelectionAndRoot(getter_AddRefs(mSelection), getter_AddRefs(mRootContent)); if (rv != NS_ERROR_NOT_AVAILABLE) { NS_ENSURE_SUCCESS(rv, rv); } else { rv = Init(aEvent); NS_ENSURE_SUCCESS(rv, rv); } // Get range from offset and length nsRefPtr<nsRange> range = new nsRange(); NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY); rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset, aEvent->mLength, aEvent->mExpandToClusterBoundary); NS_ENSURE_SUCCESS(rv, rv); nsINode* startNode = range->GetStartParent(); nsINode* endNode = range->GetEndParent(); PRInt32 startOffset = range->StartOffset(); PRInt32 endOffset = range->EndOffset(); AdjustRangeForSelection(mRootContent, &startNode, &startOffset); AdjustRangeForSelection(mRootContent, &endNode, &endOffset); nsCOMPtr<nsIDOMNode> startDomNode(do_QueryInterface(startNode)); nsCOMPtr<nsIDOMNode> endDomNode(do_QueryInterface(endNode)); NS_ENSURE_TRUE(startDomNode && endDomNode, NS_ERROR_UNEXPECTED); nsCOMPtr<nsISelectionPrivate> selPrivate = do_QueryInterface(mSelection); NS_ENSURE_TRUE(selPrivate, NS_ERROR_UNEXPECTED); selPrivate->StartBatchChanges(); // Clear selection first before setting rv = mSelection->RemoveAllRanges(); // Need to call EndBatchChanges at the end even if call failed if (NS_SUCCEEDED(rv)) { if (aEvent->mReversed) { rv = mSelection->Collapse(endDomNode, endOffset); } else { rv = mSelection->Collapse(startDomNode, startOffset); } if (NS_SUCCEEDED(rv) && (startDomNode != endDomNode || startOffset != endOffset)) { if (aEvent->mReversed) { rv = mSelection->Extend(startDomNode, startOffset); } else { rv = mSelection->Extend(endDomNode, endOffset); } } } selPrivate->EndBatchChanges(); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsISelection2>(do_QueryInterface(mSelection))->ScrollIntoView( nsISelectionController::SELECTION_FOCUS_REGION, PR_FALSE, -1, -1); aEvent->mSucceeded = PR_TRUE; return NS_OK; }
nsresult nsContentEventHandler::OnQueryCaretRect(nsQueryContentEvent* aEvent) { nsresult rv = Init(aEvent); if (NS_FAILED(rv)) return rv; nsRefPtr<nsCaret> caret = mPresShell->GetCaret(); NS_ASSERTION(caret, "GetCaret returned null"); // When the selection is collapsed and the queried offset is current caret // position, we should return the "real" caret rect. PRBool selectionIsCollapsed; rv = mSelection->GetIsCollapsed(&selectionIsCollapsed); NS_ENSURE_SUCCESS(rv, rv); if (selectionIsCollapsed) { PRUint32 offset; rv = GetFlatTextOffsetOfRange(mRootContent, mFirstSelectedRange, &offset); NS_ENSURE_SUCCESS(rv, rv); if (offset == aEvent->mInput.mOffset) { nsRect rect; nsIFrame* caretFrame = caret->GetGeometry(mSelection, &rect); if (!caretFrame) return NS_ERROR_FAILURE; rv = ConvertToRootViewRelativeOffset(caretFrame, rect); NS_ENSURE_SUCCESS(rv, rv); aEvent->mReply.mRect = rect.ToOutsidePixels(caretFrame->PresContext()->AppUnitsPerDevPixel()); aEvent->mSucceeded = PR_TRUE; return NS_OK; } } // Otherwise, we should set the guessed caret rect. nsCOMPtr<nsIRange> range = new nsRange(); NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY); rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, 0, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); PRInt32 offsetInFrame; nsIFrame* frame; rv = GetStartFrameAndOffset(range, &frame, &offsetInFrame); NS_ENSURE_SUCCESS(rv, rv); nsPoint posInFrame; rv = frame->GetPointFromOffset(range->StartOffset(), &posInFrame); NS_ENSURE_SUCCESS(rv, rv); nsRect rect; rect.x = posInFrame.x; rect.y = posInFrame.y; rect.width = caret->GetCaretRect().width; rect.height = frame->GetSize().height; rv = ConvertToRootViewRelativeOffset(frame, rect); NS_ENSURE_SUCCESS(rv, rv); aEvent->mReply.mRect = rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()); aEvent->mSucceeded = PR_TRUE; return NS_OK; }
nsresult nsContentEventHandler::OnQueryTextRect(nsQueryContentEvent* aEvent) { nsresult rv = Init(aEvent); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIRange> range = new nsRange(); if (!range) { return NS_ERROR_OUT_OF_MEMORY; } rv = SetRangeFromFlatTextOffset(range, aEvent->mInput.mOffset, aEvent->mInput.mLength, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); // used to iterate over all contents and their frames nsCOMPtr<nsIContentIterator> iter; rv = NS_NewContentIterator(getter_AddRefs(iter)); NS_ENSURE_SUCCESS(rv, rv); iter->Init(range); NS_ENSURE_SUCCESS(rv, rv); // get the starting frame PRInt32 offset = range->StartOffset(); nsINode* node = iter->GetCurrentNode(); if (!node) { node = AdjustTextRectNode(range->GetStartParent(), offset); } nsIFrame* firstFrame = nsnull; rv = GetFrameForTextRect(node, offset, PR_TRUE, &firstFrame); NS_ENSURE_SUCCESS(rv, rv); // get the starting frame rect nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size()); rv = ConvertToRootViewRelativeOffset(firstFrame, rect); NS_ENSURE_SUCCESS(rv, rv); nsRect frameRect = rect; nsPoint ptOffset; firstFrame->GetPointFromOffset(offset, &ptOffset); // minus 1 to avoid creating an empty rect rect.x += ptOffset.x - 1; rect.width -= ptOffset.x - 1; // get the ending frame offset = range->EndOffset(); node = AdjustTextRectNode(range->GetEndParent(), offset); nsIFrame* lastFrame = nsnull; rv = GetFrameForTextRect(node, offset, range->Collapsed(), &lastFrame); NS_ENSURE_SUCCESS(rv, rv); // iterate over all covered frames for (nsIFrame* frame = firstFrame; frame != lastFrame;) { frame = frame->GetNextContinuation(); if (!frame) { do { iter->Next(); node = iter->GetCurrentNode(); if (!node || !node->IsNodeOfType(nsINode::eCONTENT)) continue; frame = static_cast<nsIContent*>(node)->GetPrimaryFrame(); } while (!frame && !iter->IsDone()); if (!frame) { // this can happen when the end offset of the range is 0. frame = lastFrame; } } frameRect.SetRect(nsPoint(0, 0), frame->GetRect().Size()); rv = ConvertToRootViewRelativeOffset(frame, frameRect); NS_ENSURE_SUCCESS(rv, rv); if (frame != lastFrame) { // not last frame, so just add rect to previous result rect.UnionRect(rect, frameRect); } } // get the ending frame rect lastFrame->GetPointFromOffset(offset, &ptOffset); // minus 1 to avoid creating an empty rect frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1; if (firstFrame == lastFrame) { rect.IntersectRect(rect, frameRect); } else { rect.UnionRect(rect, frameRect); } aEvent->mReply.mRect = rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()); aEvent->mSucceeded = PR_TRUE; return NS_OK; }