Bug 1586471 - Part 1. Handle WidgetDragEvent by DispatchInputEvent. r=botond

Main thread and APZ controller thread are different on GeckoView. Some
drag events cannot be converted to InputData and aren't handled by APZ.

So we need consider drag events more for GeckoView.

Differential Revision: https://phabricator.services.mozilla.com/D197329
This commit is contained in:
Makoto Kato 2024-01-28 07:49:53 +00:00
parent 07de26de17
commit 7c13fc91e5
3 changed files with 43 additions and 9 deletions

View file

@ -431,6 +431,10 @@ class WidgetDragEvent : public WidgetMouseEvent {
mInHTMLEditorEventListener = false; mInHTMLEditorEventListener = false;
} }
bool CanConvertToInputData() const {
return mMessage == eDragStart || mMessage == eDragEnd;
}
/** /**
* Should be called before dispatching the DOM tree if this event is * Should be called before dispatching the DOM tree if this event is
* synthesized for tests because drop effect is initialized before * synthesized for tests because drop effect is initialized before

View file

@ -703,7 +703,9 @@ nsBaseDragService::FireDragEventAtSource(EventMessage aEventMessage,
} }
event.mModifiers = aKeyModifiers; event.mModifiers = aKeyModifiers;
if (widget) { // Most drag events aren't able to converted to MouseEvent except to
// eDragStart and eDragEnd.
if (widget && event.CanConvertToInputData()) {
// Send the drag event to APZ, which needs to know about them to be // Send the drag event to APZ, which needs to know about them to be
// able to accurately detect the end of a drag gesture. // able to accurately detect the end of a drag gesture.
widget->DispatchEventToAPZOnly(&event); widget->DispatchEventToAPZOnly(&event);

View file

@ -1174,18 +1174,22 @@ class DispatchEventOnMainThread : public Runnable {
template <class InputType, class EventType> template <class InputType, class EventType>
class DispatchInputOnControllerThread : public Runnable { class DispatchInputOnControllerThread : public Runnable {
public: public:
enum class APZOnly { Yes, No };
DispatchInputOnControllerThread(const EventType& aEvent, DispatchInputOnControllerThread(const EventType& aEvent,
IAPZCTreeManager* aAPZC, IAPZCTreeManager* aAPZC,
nsBaseWidget* aWidget) nsBaseWidget* aWidget,
APZOnly aAPZOnly = APZOnly::No)
: mozilla::Runnable("DispatchInputOnControllerThread"), : mozilla::Runnable("DispatchInputOnControllerThread"),
mMainMessageLoop(MessageLoop::current()), mMainMessageLoop(MessageLoop::current()),
mInput(aEvent), mInput(aEvent),
mAPZC(aAPZC), mAPZC(aAPZC),
mWidget(aWidget) {} mWidget(aWidget),
mAPZOnly(aAPZOnly) {}
NS_IMETHOD Run() override { NS_IMETHOD Run() override {
APZEventResult result = mAPZC->InputBridge()->ReceiveInputEvent(mInput); APZEventResult result = mAPZC->InputBridge()->ReceiveInputEvent(mInput);
if (result.GetStatus() == nsEventStatus_eConsumeNoDefault) { if (mAPZOnly == APZOnly::Yes ||
result.GetStatus() == nsEventStatus_eConsumeNoDefault) {
return NS_OK; return NS_OK;
} }
RefPtr<Runnable> r = new DispatchEventOnMainThread<InputType, EventType>( RefPtr<Runnable> r = new DispatchEventOnMainThread<InputType, EventType>(
@ -1199,6 +1203,7 @@ class DispatchInputOnControllerThread : public Runnable {
InputType mInput; InputType mInput;
RefPtr<IAPZCTreeManager> mAPZC; RefPtr<IAPZCTreeManager> mAPZC;
nsBaseWidget* mWidget; nsBaseWidget* mWidget;
const APZOnly mAPZOnly;
}; };
void nsBaseWidget::DispatchTouchInput(MultiTouchInput& aInput, void nsBaseWidget::DispatchTouchInput(MultiTouchInput& aInput,
@ -1266,7 +1271,12 @@ nsIWidget::ContentAndAPZEventStatus nsBaseWidget::DispatchInputEvent(
WidgetInputEvent* aEvent) { WidgetInputEvent* aEvent) {
nsIWidget::ContentAndAPZEventStatus status; nsIWidget::ContentAndAPZEventStatus status;
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (mAPZC) {
// Most drag events aren't able to converted to MouseEvent except to
// eDragStart and eDragEnd.
const bool canDispatchToApzc =
!aEvent->AsDragEvent() || aEvent->AsDragEvent()->CanConvertToInputData();
if (mAPZC && canDispatchToApzc) {
if (APZThreadUtils::IsControllerThread()) { if (APZThreadUtils::IsControllerThread()) {
APZEventResult result = mAPZC->InputBridge()->ReceiveInputEvent(*aEvent); APZEventResult result = mAPZC->InputBridge()->ReceiveInputEvent(*aEvent);
status.mApzStatus = result.GetStatus(); status.mApzStatus = result.GetStatus();
@ -1302,8 +1312,12 @@ nsIWidget::ContentAndAPZEventStatus nsBaseWidget::DispatchInputEvent(
status.mContentStatus = nsEventStatus_eConsumeDoDefault; status.mContentStatus = nsEventStatus_eConsumeDoDefault;
return status; return status;
} }
// Allow dispatching keyboard events on Gecko thread. // Allow dispatching keyboard/drag events on Gecko thread
MOZ_ASSERT(aEvent->AsKeyboardEvent()); // without sending them to APZ
// FIXME: APZ can handle keyboard events now, we should
// be sending them to APZ here
MOZ_ASSERT(aEvent->AsKeyboardEvent() || aEvent->AsDragEvent());
} }
DispatchEvent(aEvent, status.mContentStatus); DispatchEvent(aEvent, status.mContentStatus);
@ -1313,8 +1327,22 @@ nsIWidget::ContentAndAPZEventStatus nsBaseWidget::DispatchInputEvent(
void nsBaseWidget::DispatchEventToAPZOnly(mozilla::WidgetInputEvent* aEvent) { void nsBaseWidget::DispatchEventToAPZOnly(mozilla::WidgetInputEvent* aEvent) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (mAPZC) { if (mAPZC) {
MOZ_ASSERT(APZThreadUtils::IsControllerThread()); if (APZThreadUtils::IsControllerThread()) {
mAPZC->InputBridge()->ReceiveInputEvent(*aEvent); mAPZC->InputBridge()->ReceiveInputEvent(*aEvent);
return;
}
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
RefPtr<Runnable> r =
new DispatchInputOnControllerThread<MouseInput, WidgetMouseEvent>(
*mouseEvent, mAPZC, this,
DispatchInputOnControllerThread<MouseInput,
WidgetMouseEvent>::APZOnly::Yes);
APZThreadUtils::RunOnControllerThread(std::move(r));
return;
}
MOZ_ASSERT_UNREACHABLE("Not implemented yet");
} }
} }