/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ContentEventHandler.h" #include "mozilla/IMEStateManager.h" #include "mozilla/TextEvents.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/Selection.h" #include "nsCaret.h" #include "nsCOMPtr.h" #include "nsContentUtils.h" #include "nsCopySupport.h" #include "nsFocusManager.h" #include "nsFontMetrics.h" #include "nsFrameSelection.h" #include "nsIContentIterator.h" #include "nsIPresShell.h" #include "nsISelection.h" #include "nsISelectionController.h" #include "nsIFrame.h" #include "nsIObjectFrame.h" #include "nsLayoutUtils.h" #include "nsPresContext.h" #include "nsRange.h" #include "nsTextFragment.h" #include "nsTextFrame.h" #include "nsView.h" #include namespace mozilla { using namespace dom; using namespace widget; /******************************************************************/ /* ContentEventHandler */ /******************************************************************/ ContentEventHandler::ContentEventHandler(nsPresContext* aPresContext) : mPresContext(aPresContext) , mPresShell(aPresContext->GetPresShell()) , mSelection(nullptr) , mFirstSelectedRange(nullptr) , mRootContent(nullptr) { } nsresult ContentEventHandler::InitBasic() { NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE); // If text frame which has overflowing selection underline is dirty, // we need to flush the pending reflow here. mPresShell->FlushPendingNotifications(Flush_Layout); // Flushing notifications can cause mPresShell to be destroyed (bug 577963). NS_ENSURE_TRUE(!mPresShell->IsDestroying(), NS_ERROR_FAILURE); return NS_OK; } nsresult ContentEventHandler::InitCommon() { if (mSelection) { return NS_OK; } nsresult rv = InitBasic(); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr sel; nsCopySupport::GetSelectionForCopy(mPresShell->GetDocument(), getter_AddRefs(sel)); mSelection = static_cast(sel.get()); if (NS_WARN_IF(!mSelection)) { return NS_ERROR_NOT_AVAILABLE; } if (!mSelection->RangeCount()) { // If there is no selection range, we should compute the selection root // from ancestor limiter or root content of the document. rv = mSelection->GetAncestorLimiter(getter_AddRefs(mRootContent)); if (NS_WARN_IF(NS_FAILED(rv))) { return NS_ERROR_FAILURE; } if (!mRootContent) { mRootContent = mPresShell->GetDocument()->GetRootElement(); if (NS_WARN_IF(!mRootContent)) { return NS_ERROR_NOT_AVAILABLE; } } // Assume that there is selection at beginning of the root content. rv = nsRange::CreateRange(mRootContent, 0, mRootContent, 0, getter_AddRefs(mFirstSelectedRange)); if (NS_WARN_IF(NS_FAILED(rv)) || NS_WARN_IF(!mFirstSelectedRange)) { return NS_ERROR_UNEXPECTED; } return NS_OK; } mFirstSelectedRange = mSelection->GetRangeAt(0); if (NS_WARN_IF(!mFirstSelectedRange)) { return NS_ERROR_UNEXPECTED; } // If there is a selection, we should retrieve the selection root from // the range since when the window is inactivated, the ancestor limiter // of mSelection was cleared by blur event handler of nsEditor but the // selection range still keeps storing the nodes. If the active element of // the deactive window is or