diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /editor/libeditor/HTMLEditorEventListener.cpp | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'editor/libeditor/HTMLEditorEventListener.cpp')
-rw-r--r-- | editor/libeditor/HTMLEditorEventListener.cpp | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/editor/libeditor/HTMLEditorEventListener.cpp b/editor/libeditor/HTMLEditorEventListener.cpp new file mode 100644 index 000000000..8fb9459c2 --- /dev/null +++ b/editor/libeditor/HTMLEditorEventListener.cpp @@ -0,0 +1,215 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "HTMLEditorEventListener.h" + +#include "HTMLEditUtils.h" +#include "mozilla/HTMLEditor.h" +#include "mozilla/dom/Event.h" +#include "mozilla/dom/Selection.h" +#include "nsCOMPtr.h" +#include "nsDebug.h" +#include "nsError.h" +#include "nsIDOMElement.h" +#include "nsIDOMEvent.h" +#include "nsIDOMEventTarget.h" +#include "nsIDOMMouseEvent.h" +#include "nsIDOMNode.h" +#include "nsIEditor.h" +#include "nsIHTMLInlineTableEditor.h" +#include "nsIHTMLObjectResizer.h" +#include "nsISupportsImpl.h" +#include "nsLiteralString.h" +#include "nsQueryObject.h" +#include "nsRange.h" + +namespace mozilla { + +using namespace dom; + +#ifdef DEBUG +nsresult +HTMLEditorEventListener::Connect(EditorBase* aEditorBase) +{ + nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryObject(aEditorBase); + nsCOMPtr<nsIHTMLInlineTableEditor> htmlInlineTableEditor = + do_QueryObject(aEditorBase); + NS_PRECONDITION(htmlEditor && htmlInlineTableEditor, + "Set HTMLEditor or its sub class"); + return EditorEventListener::Connect(aEditorBase); +} +#endif + +HTMLEditor* +HTMLEditorEventListener::GetHTMLEditor() +{ + // mEditor must be HTMLEditor or its subclass. + return static_cast<HTMLEditor*>(mEditorBase); +} + +nsresult +HTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent) +{ + HTMLEditor* htmlEditor = GetHTMLEditor(); + + nsCOMPtr<nsIDOMEventTarget> target; + nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER); + nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target); + + int32_t clientX, clientY; + aMouseEvent->GetClientX(&clientX); + aMouseEvent->GetClientY(&clientY); + htmlEditor->MouseUp(clientX, clientY, element); + + return EditorEventListener::MouseUp(aMouseEvent); +} + +nsresult +HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent) +{ + HTMLEditor* htmlEditor = GetHTMLEditor(); + // Contenteditable should disregard mousedowns outside it. + // IsAcceptableInputEvent() checks it for a mouse event. + if (!htmlEditor->IsAcceptableInputEvent(aMouseEvent->AsEvent())) { + // If it's not acceptable mousedown event (including when mousedown event + // is fired outside of the active editing host), we need to commit + // composition because it will be change the selection to the clicked + // point. Then, we won't be able to commit the composition. + return EditorEventListener::MouseDown(aMouseEvent); + } + + // Detect only "context menu" click + // XXX This should be easier to do! + // But eDOMEvents_contextmenu and eContextMenu is not exposed in any event + // interface :-( + int16_t buttonNumber; + nsresult rv = aMouseEvent->GetButton(&buttonNumber); + NS_ENSURE_SUCCESS(rv, rv); + + bool isContextClick = buttonNumber == 2; + + int32_t clickCount; + rv = aMouseEvent->GetDetail(&clickCount); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIDOMEventTarget> target; + rv = aMouseEvent->AsEvent()->GetExplicitOriginalTarget(getter_AddRefs(target)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER); + nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target); + + if (isContextClick || (buttonNumber == 0 && clickCount == 2)) { + RefPtr<Selection> selection = mEditorBase->GetSelection(); + NS_ENSURE_TRUE(selection, NS_OK); + + // Get location of mouse within target node + nsCOMPtr<nsIDOMNode> parent; + rv = aMouseEvent->GetRangeParent(getter_AddRefs(parent)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(parent, NS_ERROR_FAILURE); + + int32_t offset = 0; + rv = aMouseEvent->GetRangeOffset(&offset); + NS_ENSURE_SUCCESS(rv, rv); + + // Detect if mouse point is within current selection for context click + bool nodeIsInSelection = false; + if (isContextClick && !selection->Collapsed()) { + int32_t rangeCount; + rv = selection->GetRangeCount(&rangeCount); + NS_ENSURE_SUCCESS(rv, rv); + + for (int32_t i = 0; i < rangeCount; i++) { + RefPtr<nsRange> range = selection->GetRangeAt(i); + if (!range) { + // Don't bail yet, iterate through them all + continue; + } + + range->IsPointInRange(parent, offset, &nodeIsInSelection); + + // Done when we find a range that we are in + if (nodeIsInSelection) { + break; + } + } + } + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(target); + if (node && !nodeIsInSelection) { + if (!element) { + if (isContextClick) { + // Set the selection to the point under the mouse cursor: + selection->Collapse(parent, offset); + } else { + // Get enclosing link if in text so we can select the link + nsCOMPtr<nsIDOMElement> linkElement; + rv = htmlEditor->GetElementOrParentByTagName( + NS_LITERAL_STRING("href"), node, + getter_AddRefs(linkElement)); + NS_ENSURE_SUCCESS(rv, rv); + if (linkElement) { + element = linkElement; + } + } + } + // Select entire element clicked on if NOT within an existing selection + // and not the entire body, or table-related elements + if (element) { + nsCOMPtr<nsIDOMNode> selectAllNode = + htmlEditor->FindUserSelectAllNode(element); + + if (selectAllNode) { + nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(selectAllNode); + if (newElement) { + node = selectAllNode; + element = newElement; + } + } + + if (isContextClick && !HTMLEditUtils::IsImage(node)) { + selection->Collapse(parent, offset); + } else { + htmlEditor->SelectElement(element); + } + } + } + // HACK !!! Context click places the caret but the context menu consumes + // the event; so we need to check resizing state ourselves + htmlEditor->CheckSelectionStateForAnonymousButtons(selection); + + // Prevent bubbling if we changed selection or + // for all context clicks + if (element || isContextClick) { + aMouseEvent->AsEvent()->PreventDefault(); + return NS_OK; + } + } else if (!isContextClick && buttonNumber == 0 && clickCount == 1) { + // if the target element is an image, we have to display resizers + int32_t clientX, clientY; + aMouseEvent->GetClientX(&clientX); + aMouseEvent->GetClientY(&clientY); + htmlEditor->MouseDown(clientX, clientY, element, aMouseEvent->AsEvent()); + } + + return EditorEventListener::MouseDown(aMouseEvent); +} + +nsresult +HTMLEditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent) +{ + nsCOMPtr<nsIDOMEventTarget> target; + nsresult rv = aMouseEvent->AsEvent()->GetTarget(getter_AddRefs(target)); + NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER); + nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target); + + GetHTMLEditor()->DoInlineTableEditingAction(element); + + return EditorEventListener::MouseClick(aMouseEvent); +} + +} // namespace mozilla |