Issue #12 Part 2: Stop using nsIDOMEvent in IsAcceptableInputEvent.

This commit is contained in:
wolfbeast 2018-06-26 13:53:12 +02:00 • committed by Roy Tam
commit 550c8977c1
9 changed files with 87 additions and 54 deletions

View file

@ -280,16 +280,10 @@ Event::GetType(nsAString& aType)
return NS_OK; return NS_OK;
} }
static EventTarget*
GetDOMEventTarget(nsIDOMEventTarget* aTarget)
{
return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
}
EventTarget* EventTarget*
Event::GetTarget() const Event::GetTarget() const
{ {
return GetDOMEventTarget(mEvent->mTarget); return mEvent->GetDOMEventTarget();
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -302,7 +296,7 @@ Event::GetTarget(nsIDOMEventTarget** aTarget)
EventTarget* EventTarget*
Event::GetCurrentTarget() const Event::GetCurrentTarget() const
{ {
return GetDOMEventTarget(mEvent->mCurrentTarget); return mEvent->GetCurrentDOMEventTarget();
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -349,11 +343,7 @@ Event::GetExplicitOriginalTarget(nsIDOMEventTarget** aRealEventTarget)
EventTarget* EventTarget*
Event::GetOriginalTarget() const Event::GetOriginalTarget() const
{ {
if (mEvent->mOriginalTarget) { return mEvent->GetOriginalDOMEventTarget();
return GetDOMEventTarget(mEvent->mOriginalTarget);
}
return GetTarget();
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -5092,19 +5092,16 @@ EditorBase::IsActiveInDOMWindow()
} }
bool bool
EditorBase::IsAcceptableInputEvent(nsIDOMEvent* aEvent) EditorBase::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
{ {
// If the event is trusted, the event should always cause input. // If the event is trusted, the event should always cause input.
NS_ENSURE_TRUE(aEvent, false); if (NS_WARN_IF(!aGUIEvent)) {
WidgetEvent* widgetEvent = aEvent->WidgetEventPtr();
if (NS_WARN_IF(!widgetEvent)) {
return false; return false;
} }
// If this is dispatched by using cordinates but this editor doesn't have // If this is dispatched by using cordinates but this editor doesn't have
// focus, we shouldn't handle it. // focus, we shouldn't handle it.
if (widgetEvent->IsUsingCoordinates()) { if (aGUIEvent->IsUsingCoordinates()) {
nsCOMPtr<nsIContent> focusedContent = GetFocusedContent(); nsCOMPtr<nsIContent> focusedContent = GetFocusedContent();
if (!focusedContent) { if (!focusedContent) {
return false; return false;
@ -5117,8 +5114,7 @@ EditorBase::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
// Note that if we allow to handle such events, editor may be confused by // Note that if we allow to handle such events, editor may be confused by
// strange event order. // strange event order.
bool needsWidget = false; bool needsWidget = false;
WidgetGUIEvent* widgetGUIEvent = nullptr; switch (aGUIEvent->mMessage) {
switch (widgetEvent->mMessage) {
case eUnidentifiedEvent: case eUnidentifiedEvent:
// If events are not created with proper event interface, their message // If events are not created with proper event interface, their message
// are initialized with eUnidentifiedEvent. Let's ignore such event. // are initialized with eUnidentifiedEvent. Let's ignore such event.
@ -5130,25 +5126,26 @@ EditorBase::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
case eCompositionCommitAsIs: case eCompositionCommitAsIs:
// Don't allow composition events whose internal event are not // Don't allow composition events whose internal event are not
// WidgetCompositionEvent. // WidgetCompositionEvent.
widgetGUIEvent = aEvent->WidgetEventPtr()->AsCompositionEvent(); if (!aGUIEvent->AsCompositionEvent()) {
return false;
}
needsWidget = true; needsWidget = true;
break; break;
default: default:
break; break;
} }
if (needsWidget && if (needsWidget && !aGUIEvent->mWidget) {
(!widgetGUIEvent || !widgetGUIEvent->mWidget)) {
return false; return false;
} }
// Accept all trusted events. // Accept all trusted events.
if (widgetEvent->IsTrusted()) { if (aGUIEvent->IsTrusted()) {
return true; return true;
} }
// Ignore untrusted mouse event. // Ignore untrusted mouse event.
// XXX Why are we handling other untrusted input events? // XXX Why are we handling other untrusted input events?
if (widgetEvent->AsMouseEventBase()) { if (aGUIEvent->AsMouseEventBase()) {
return false; return false;
} }

View file

@ -871,12 +871,12 @@ public:
virtual bool IsActiveInDOMWindow(); virtual bool IsActiveInDOMWindow();
/** /**
* Whether the aEvent should be handled by this editor or not. When this * Whether the aGUIEvent should be handled by this editor or not. When this
* returns FALSE, The aEvent shouldn't be handled on this editor, * returns false, The aGUIEvent shouldn't be handled on this editor,
* i.e., The aEvent should be handled by another inner editor or ancestor * i.e., The aGUIEvent should be handled by another inner editor or ancestor
* elements. * elements.
*/ */
virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent); virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent);
/** /**
* FindSelectionRoot() returns a selection root of this editor when aNode * FindSelectionRoot() returns a selection root of this editor when aNode

View file

@ -590,7 +590,11 @@ EditorEventListener::KeyPress(nsIDOMKeyEvent* aKeyEvent)
{ {
NS_ENSURE_TRUE(aKeyEvent, NS_OK); NS_ENSURE_TRUE(aKeyEvent, NS_OK);
if (!mEditorBase->IsAcceptableInputEvent(aKeyEvent->AsEvent())) { WidgetKeyboardEvent* keypressEvent =
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
MOZ_ASSERT(keypressEvent,
"DOM key event's internal event must be WidgetKeyboardEvent");
if (!mEditorBase->IsAcceptableInputEvent(keypressEvent)) {
return NS_OK; return NS_OK;
} }
@ -619,11 +623,7 @@ EditorEventListener::KeyPress(nsIDOMKeyEvent* aKeyEvent)
} }
// Now, ask the native key bindings to handle the event. // Now, ask the native key bindings to handle the event.
WidgetKeyboardEvent* keyEvent = nsIWidget* widget = keypressEvent->mWidget;
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
MOZ_ASSERT(keyEvent,
"DOM key event's internal event must be WidgetKeyboardEvent");
nsIWidget* widget = keyEvent->mWidget;
// If the event is created by chrome script, the widget is always nullptr. // If the event is created by chrome script, the widget is always nullptr.
if (!widget) { if (!widget) {
nsCOMPtr<nsIPresShell> ps = GetPresShell(); nsCOMPtr<nsIPresShell> ps = GetPresShell();
@ -635,7 +635,7 @@ EditorEventListener::KeyPress(nsIDOMKeyEvent* aKeyEvent)
nsCOMPtr<nsIDocument> doc = mEditorBase->GetDocument(); nsCOMPtr<nsIDocument> doc = mEditorBase->GetDocument();
bool handled = widget->ExecuteNativeKeyBinding( bool handled = widget->ExecuteNativeKeyBinding(
nsIWidget::NativeKeyBindingsForRichTextEditor, nsIWidget::NativeKeyBindingsForRichTextEditor,
*keyEvent, DoCommandCallback, doc); *keypressEvent, DoCommandCallback, doc);
if (handled) { if (handled) {
aKeyEvent->AsEvent()->PreventDefault(); aKeyEvent->AsEvent()->PreventDefault();
} }
@ -646,8 +646,10 @@ nsresult
EditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent) EditorEventListener::MouseClick(nsIDOMMouseEvent* aMouseEvent)
{ {
// nothing to do if editor isn't editable or clicked on out of the editor. // nothing to do if editor isn't editable or clicked on out of the editor.
WidgetMouseEvent* clickEvent =
aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
if (mEditorBase->IsReadonly() || mEditorBase->IsDisabled() || if (mEditorBase->IsReadonly() || mEditorBase->IsDisabled() ||
!mEditorBase->IsAcceptableInputEvent(aMouseEvent->AsEvent())) { !mEditorBase->IsAcceptableInputEvent(clickEvent)) {
return NS_OK; return NS_OK;
} }
@ -782,7 +784,9 @@ EditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
nsresult nsresult
EditorEventListener::HandleText(nsIDOMEvent* aTextEvent) EditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
{ {
if (!mEditorBase->IsAcceptableInputEvent(aTextEvent)) { WidgetCompositionEvent* compositionChangeEvent =
aTextEvent->WidgetEventPtr()->AsCompositionEvent();
if (!mEditorBase->IsAcceptableInputEvent(compositionChangeEvent)) {
return NS_OK; return NS_OK;
} }
@ -793,8 +797,6 @@ EditorEventListener::HandleText(nsIDOMEvent* aTextEvent)
// AsCompositionEvent() should always return non-nullptr. Anyway, it'll be // AsCompositionEvent() should always return non-nullptr. Anyway, it'll be
// checked in TextEditor::UpdateIMEComposition(). // checked in TextEditor::UpdateIMEComposition().
WidgetCompositionEvent* compositionChangeEvent =
aTextEvent->WidgetEventPtr()->AsCompositionEvent();
return mEditorBase->UpdateIMEComposition(compositionChangeEvent); return mEditorBase->UpdateIMEComposition(compositionChangeEvent);
} }
@ -1036,18 +1038,20 @@ EditorEventListener::CanDrop(nsIDOMDragEvent* aEvent)
nsresult nsresult
EditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent) EditorEventListener::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
{ {
if (!mEditorBase->IsAcceptableInputEvent(aCompositionEvent)) {
return NS_OK;
}
WidgetCompositionEvent* compositionStart = WidgetCompositionEvent* compositionStart =
aCompositionEvent->WidgetEventPtr()->AsCompositionEvent(); aCompositionEvent->WidgetEventPtr()->AsCompositionEvent();
if (!mEditorBase->IsAcceptableInputEvent(compositionStart)) {
return NS_OK;
}
return mEditorBase->BeginIMEComposition(compositionStart); return mEditorBase->BeginIMEComposition(compositionStart);
} }
void void
EditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent) EditorEventListener::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
{ {
if (!mEditorBase->IsAcceptableInputEvent(aCompositionEvent)) { WidgetCompositionEvent* compositionEnd =
aCompositionEvent->WidgetEventPtr()->AsCompositionEvent();
if (!mEditorBase->IsAcceptableInputEvent(compositionEnd)) {
return; return;
} }

View file

@ -5161,23 +5161,22 @@ HTMLEditor::OurWindowHasFocus()
} }
bool bool
HTMLEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent) HTMLEditor::IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent)
{ {
if (!EditorBase::IsAcceptableInputEvent(aEvent)) { if (!EditorBase::IsAcceptableInputEvent(aGUIEvent)) {
return false; return false;
} }
// While there is composition, all composition events in its top level window // While there is composition, all composition events in its top level window
// are always fired on the composing editor. Therefore, if this editor has // are always fired on the composing editor. Therefore, if this editor has
// composition, the composition events should be handled in this editor. // composition, the composition events should be handled in this editor.
if (mComposition && aEvent->WidgetEventPtr()->AsCompositionEvent()) { if (mComposition && aGUIEvent->AsCompositionEvent()) {
return true; return true;
} }
NS_ENSURE_TRUE(mDocWeak, false); NS_ENSURE_TRUE(mDocWeak, false);
nsCOMPtr<nsIDOMEventTarget> target; nsCOMPtr<nsIDOMEventTarget> target = aGUIEvent->GetDOMEventTarget();
aEvent->GetTarget(getter_AddRefs(target));
NS_ENSURE_TRUE(target, false); NS_ENSURE_TRUE(target, false);
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak); nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocWeak);
@ -5201,8 +5200,7 @@ HTMLEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
// If the event is a mouse event, we need to check if the target content is // If the event is a mouse event, we need to check if the target content is
// the focused editing host or its descendant. // the focused editing host or its descendant.
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent); if (aGUIEvent->AsMouseEventBase()) {
if (mouseEvent) {
nsIContent* editingHost = GetActiveEditingHost(); nsIContent* editingHost = GetActiveEditingHost();
// If there is no active editing host, we cannot handle the mouse event // If there is no active editing host, we cannot handle the mouse event
// correctly. // correctly.

View file

@ -114,7 +114,7 @@ public:
virtual Element* GetEditorRoot() override; virtual Element* GetEditorRoot() override;
virtual already_AddRefed<nsIContent> FindSelectionRoot( virtual already_AddRefed<nsIContent> FindSelectionRoot(
nsINode *aNode) override; nsINode *aNode) override;
virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent) override; virtual bool IsAcceptableInputEvent(WidgetGUIEvent* aGUIEvent) override;
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override; virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
virtual bool IsEditable(nsINode* aNode) override; virtual bool IsEditable(nsINode* aNode) override;
using EditorBase::IsEditable; using EditorBase::IsEditable;

View file

@ -7,6 +7,7 @@
#include "HTMLEditUtils.h" #include "HTMLEditUtils.h"
#include "mozilla/HTMLEditor.h" #include "mozilla/HTMLEditor.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/dom/Event.h" #include "mozilla/dom/Event.h"
#include "mozilla/dom/Selection.h" #include "mozilla/dom/Selection.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
@ -71,10 +72,13 @@ HTMLEditorEventListener::MouseUp(nsIDOMMouseEvent* aMouseEvent)
nsresult nsresult
HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent) HTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
{ {
WidgetMouseEvent* mousedownEvent =
aMouseEvent->AsEvent()->WidgetEventPtr()->AsMouseEvent();
HTMLEditor* htmlEditor = GetHTMLEditor(); HTMLEditor* htmlEditor = GetHTMLEditor();
// Contenteditable should disregard mousedowns outside it. // Contenteditable should disregard mousedowns outside it.
// IsAcceptableInputEvent() checks it for a mouse event. // IsAcceptableInputEvent() checks it for a mouse event.
if (!htmlEditor->IsAcceptableInputEvent(aMouseEvent->AsEvent())) { if (!htmlEditor->IsAcceptableInputEvent(mousedownEvent)) {
// If it's not acceptable mousedown event (including when mousedown event // If it's not acceptable mousedown event (including when mousedown event
// is fired outside of the active editing host), we need to commit // is fired outside of the active editing host), we need to commit
// composition because it will be change the selection to the clicked // composition because it will be change the selection to the clicked

View file

@ -407,10 +407,16 @@ public:
nsString mSpecifiedEventTypeString; nsString mSpecifiedEventTypeString;
// Event targets, needed by DOM Events // Event targets, needed by DOM Events
// Note that when you need event target for DOM event, you should use
// Get*DOMEventTarget() instead of accessing these members directly.
nsCOMPtr<dom::EventTarget> mTarget; nsCOMPtr<dom::EventTarget> mTarget;
nsCOMPtr<dom::EventTarget> mCurrentTarget; nsCOMPtr<dom::EventTarget> mCurrentTarget;
nsCOMPtr<dom::EventTarget> mOriginalTarget; nsCOMPtr<dom::EventTarget> mOriginalTarget;
dom::EventTarget* GetDOMEventTarget() const;
dom::EventTarget* GetCurrentDOMEventTarget() const;
dom::EventTarget* GetOriginalDOMEventTarget() const;
void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets)
{ {
// mClass should be initialized with the constructor. // mClass should be initialized with the constructor.

View file

@ -12,6 +12,7 @@
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/TextEvents.h" #include "mozilla/TextEvents.h"
#include "mozilla/TouchEvents.h" #include "mozilla/TouchEvents.h"
#include "nsIDOMEventTarget.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
namespace mozilla { namespace mozilla {
@ -410,6 +411,39 @@ WidgetEvent::IsAllowedToDispatchDOMEvent() const
} }
} }
/******************************************************************************
* mozilla::WidgetEvent
*
* Misc methods.
******************************************************************************/
static dom::EventTarget*
GetTargetForDOMEvent(nsIDOMEventTarget* aTarget)
{
return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
}
dom::EventTarget*
WidgetEvent::GetDOMEventTarget() const
{
return GetTargetForDOMEvent(mTarget);
}
dom::EventTarget*
WidgetEvent::GetCurrentDOMEventTarget() const
{
return GetTargetForDOMEvent(mCurrentTarget);
}
dom::EventTarget*
WidgetEvent::GetOriginalDOMEventTarget() const
{
if (mOriginalTarget) {
return GetTargetForDOMEvent(mOriginalTarget);
}
return GetDOMEventTarget();
}
/****************************************************************************** /******************************************************************************
* mozilla::WidgetInputEvent * mozilla::WidgetInputEvent
******************************************************************************/ ******************************************************************************/