Bug 1890689 apply drift correction to input rate instead of output rate r=pehrsons
[gecko.git] / layout / base / AccessibleCaretEventHub.cpp
blobd9cd91d866697e81747e083fcb5a1f6ce9fec379
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AccessibleCaretEventHub.h"
9 #include "AccessibleCaretLogger.h"
10 #include "AccessibleCaretManager.h"
12 #include "mozilla/AutoRestore.h"
13 #include "mozilla/PresShell.h"
14 #include "mozilla/StaticPrefs_layout.h"
15 #include "mozilla/StaticPrefs_ui.h"
16 #include "mozilla/TextEvents.h"
17 #include "mozilla/TouchEvents.h"
18 #include "mozilla/dom/Document.h"
19 #include "mozilla/dom/MouseEventBinding.h"
20 #include "mozilla/dom/Selection.h"
21 #include "nsCanvasFrame.h"
22 #include "nsDocShell.h"
23 #include "nsFocusManager.h"
24 #include "nsFrameSelection.h"
25 #include "nsITimer.h"
26 #include "nsLayoutUtils.h"
27 #include "nsPresContext.h"
29 using namespace mozilla;
30 using namespace mozilla::dom;
32 namespace mozilla {
34 #undef AC_LOG
35 #define AC_LOG(message, ...) \
36 AC_LOG_BASE("AccessibleCaretEventHub (%p): " message, this, ##__VA_ARGS__);
38 #undef AC_LOGV
39 #define AC_LOGV(message, ...) \
40 AC_LOGV_BASE("AccessibleCaretEventHub (%p): " message, this, ##__VA_ARGS__);
42 NS_IMPL_ISUPPORTS(AccessibleCaretEventHub, nsIReflowObserver, nsIScrollObserver,
43 nsISupportsWeakReference);
45 // -----------------------------------------------------------------------------
46 // NoActionState
48 class AccessibleCaretEventHub::NoActionState
49 : public AccessibleCaretEventHub::State {
50 public:
51 const char* Name() const override { return "NoActionState"; }
53 MOZ_CAN_RUN_SCRIPT
54 nsEventStatus OnPress(AccessibleCaretEventHub* aContext,
55 const nsPoint& aPoint, int32_t aTouchId,
56 EventClassID aEventClass) override {
57 nsEventStatus rv = nsEventStatus_eIgnore;
59 if (NS_SUCCEEDED(aContext->mManager->PressCaret(aPoint, aEventClass))) {
60 aContext->SetState(AccessibleCaretEventHub::PressCaretState());
61 rv = nsEventStatus_eConsumeNoDefault;
62 } else {
63 aContext->SetState(AccessibleCaretEventHub::PressNoCaretState());
66 aContext->mPressPoint = aPoint;
67 aContext->mActiveTouchId = aTouchId;
69 return rv;
72 MOZ_CAN_RUN_SCRIPT
73 void OnScrollStart(AccessibleCaretEventHub* aContext) override {
74 aContext->mManager->OnScrollStart();
75 aContext->SetState(AccessibleCaretEventHub::ScrollState());
78 MOZ_CAN_RUN_SCRIPT
79 void OnScrollPositionChanged(AccessibleCaretEventHub* aContext) override {
80 aContext->mManager->OnScrollPositionChanged();
83 MOZ_CAN_RUN_SCRIPT
84 void OnSelectionChanged(AccessibleCaretEventHub* aContext, Document* aDoc,
85 dom::Selection* aSel, int16_t aReason) override {
86 aContext->mManager->OnSelectionChanged(aDoc, aSel, aReason);
89 MOZ_CAN_RUN_SCRIPT
90 void OnBlur(AccessibleCaretEventHub* aContext,
91 bool aIsLeavingDocument) override {
92 aContext->mManager->OnBlur();
95 MOZ_CAN_RUN_SCRIPT
96 void OnReflow(AccessibleCaretEventHub* aContext) override {
97 aContext->mManager->OnReflow();
100 void Enter(AccessibleCaretEventHub* aContext) override {
101 aContext->mPressPoint = nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
102 aContext->mActiveTouchId = kInvalidTouchId;
106 // -----------------------------------------------------------------------------
107 // PressCaretState: Because we've pressed on the caret, always consume the
108 // event, both real and synthesized, so that other event handling code won't
109 // have a chance to do something else to interrupt caret dragging.
111 class AccessibleCaretEventHub::PressCaretState
112 : public AccessibleCaretEventHub::State {
113 public:
114 const char* Name() const override { return "PressCaretState"; }
116 MOZ_CAN_RUN_SCRIPT
117 nsEventStatus OnMove(AccessibleCaretEventHub* aContext, const nsPoint& aPoint,
118 WidgetMouseEvent::Reason aReason) override {
119 if (aReason == WidgetMouseEvent::eReal &&
120 aContext->MoveDistanceIsLarge(aPoint)) {
121 if (NS_SUCCEEDED(aContext->mManager->DragCaret(aPoint))) {
122 aContext->SetState(AccessibleCaretEventHub::DragCaretState());
126 return nsEventStatus_eConsumeNoDefault;
129 MOZ_CAN_RUN_SCRIPT
130 nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override {
131 aContext->mManager->ReleaseCaret();
132 aContext->mManager->TapCaret(aContext->mPressPoint);
133 aContext->SetState(AccessibleCaretEventHub::NoActionState());
135 return nsEventStatus_eConsumeNoDefault;
138 nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
139 const nsPoint& aPoint) override {
140 return nsEventStatus_eConsumeNoDefault;
144 // -----------------------------------------------------------------------------
145 // DragCaretState: Because we've pressed on the caret, always consume the event,
146 // both real and synthesized, so that other event handling code won't have a
147 // chance to do something else to interrupt caret dragging.
149 class AccessibleCaretEventHub::DragCaretState
150 : public AccessibleCaretEventHub::State {
151 public:
152 const char* Name() const override { return "DragCaretState"; }
154 MOZ_CAN_RUN_SCRIPT
155 nsEventStatus OnMove(AccessibleCaretEventHub* aContext, const nsPoint& aPoint,
156 WidgetMouseEvent::Reason aReason) override {
157 if (aReason == WidgetMouseEvent::eReal) {
158 aContext->mManager->DragCaret(aPoint);
161 return nsEventStatus_eConsumeNoDefault;
164 MOZ_CAN_RUN_SCRIPT
165 nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override {
166 aContext->mManager->ReleaseCaret();
167 aContext->SetState(AccessibleCaretEventHub::NoActionState());
169 return nsEventStatus_eConsumeNoDefault;
173 // -----------------------------------------------------------------------------
174 // PressNoCaretState
176 class AccessibleCaretEventHub::PressNoCaretState
177 : public AccessibleCaretEventHub::State {
178 public:
179 const char* Name() const override { return "PressNoCaretState"; }
181 nsEventStatus OnMove(AccessibleCaretEventHub* aContext, const nsPoint& aPoint,
182 WidgetMouseEvent::Reason aReason) override {
183 if (aContext->MoveDistanceIsLarge(aPoint)) {
184 aContext->SetState(AccessibleCaretEventHub::NoActionState());
187 return nsEventStatus_eIgnore;
190 nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override {
191 aContext->SetState(AccessibleCaretEventHub::NoActionState());
193 return nsEventStatus_eIgnore;
196 MOZ_CAN_RUN_SCRIPT
197 nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
198 const nsPoint& aPoint) override {
199 aContext->SetState(AccessibleCaretEventHub::LongTapState());
201 return aContext->GetState()->OnLongTap(aContext, aPoint);
204 MOZ_CAN_RUN_SCRIPT
205 void OnScrollStart(AccessibleCaretEventHub* aContext) override {
206 aContext->mManager->OnScrollStart();
207 aContext->SetState(AccessibleCaretEventHub::ScrollState());
210 MOZ_CAN_RUN_SCRIPT
211 void OnBlur(AccessibleCaretEventHub* aContext,
212 bool aIsLeavingDocument) override {
213 aContext->mManager->OnBlur();
214 if (aIsLeavingDocument) {
215 aContext->SetState(AccessibleCaretEventHub::NoActionState());
219 MOZ_CAN_RUN_SCRIPT
220 void OnSelectionChanged(AccessibleCaretEventHub* aContext, Document* aDoc,
221 dom::Selection* aSel, int16_t aReason) override {
222 aContext->mManager->OnSelectionChanged(aDoc, aSel, aReason);
225 MOZ_CAN_RUN_SCRIPT
226 void OnReflow(AccessibleCaretEventHub* aContext) override {
227 aContext->mManager->OnReflow();
230 void Enter(AccessibleCaretEventHub* aContext) override {
231 aContext->LaunchLongTapInjector();
234 void Leave(AccessibleCaretEventHub* aContext) override {
235 aContext->CancelLongTapInjector();
239 // -----------------------------------------------------------------------------
240 // ScrollState
242 class AccessibleCaretEventHub::ScrollState
243 : public AccessibleCaretEventHub::State {
244 public:
245 const char* Name() const override { return "ScrollState"; }
247 MOZ_CAN_RUN_SCRIPT
248 void OnScrollEnd(AccessibleCaretEventHub* aContext) override {
249 aContext->mManager->OnScrollEnd();
250 aContext->SetState(AccessibleCaretEventHub::NoActionState());
253 MOZ_CAN_RUN_SCRIPT
254 void OnScrollPositionChanged(AccessibleCaretEventHub* aContext) override {
255 aContext->mManager->OnScrollPositionChanged();
258 MOZ_CAN_RUN_SCRIPT
259 void OnBlur(AccessibleCaretEventHub* aContext,
260 bool aIsLeavingDocument) override {
261 aContext->mManager->OnBlur();
262 if (aIsLeavingDocument) {
263 aContext->SetState(AccessibleCaretEventHub::NoActionState());
268 // -----------------------------------------------------------------------------
269 // LongTapState
271 class AccessibleCaretEventHub::LongTapState
272 : public AccessibleCaretEventHub::State {
273 public:
274 const char* Name() const override { return "LongTapState"; }
276 MOZ_CAN_RUN_SCRIPT
277 nsEventStatus OnLongTap(AccessibleCaretEventHub* aContext,
278 const nsPoint& aPoint) override {
279 // In general text selection is lower-priority than the context menu. If
280 // we consume this long-press event, then it prevents the context menu from
281 // showing up on desktop Firefox (because that happens on long-tap-up, if
282 // the long-tap was not cancelled). So we return eIgnore instead.
283 aContext->mManager->SelectWordOrShortcut(aPoint);
284 return nsEventStatus_eIgnore;
287 nsEventStatus OnRelease(AccessibleCaretEventHub* aContext) override {
288 aContext->SetState(AccessibleCaretEventHub::NoActionState());
290 // Do not consume the release since the press is not consumed in
291 // PressNoCaretState either.
292 return nsEventStatus_eIgnore;
295 MOZ_CAN_RUN_SCRIPT
296 void OnScrollStart(AccessibleCaretEventHub* aContext) override {
297 aContext->mManager->OnScrollStart();
298 aContext->SetState(AccessibleCaretEventHub::ScrollState());
301 MOZ_CAN_RUN_SCRIPT
302 void OnReflow(AccessibleCaretEventHub* aContext) override {
303 aContext->mManager->OnReflow();
307 // -----------------------------------------------------------------------------
308 // Implementation of AccessibleCaretEventHub methods
310 AccessibleCaretEventHub::State* AccessibleCaretEventHub::GetState() const {
311 return mState;
314 void AccessibleCaretEventHub::SetState(State* aState) {
315 MOZ_ASSERT(aState);
317 AC_LOG("%s -> %s", mState->Name(), aState->Name());
319 mState->Leave(this);
320 mState = aState;
321 mState->Enter(this);
324 MOZ_IMPL_STATE_CLASS_GETTER(NoActionState)
325 MOZ_IMPL_STATE_CLASS_GETTER(PressCaretState)
326 MOZ_IMPL_STATE_CLASS_GETTER(DragCaretState)
327 MOZ_IMPL_STATE_CLASS_GETTER(PressNoCaretState)
328 MOZ_IMPL_STATE_CLASS_GETTER(ScrollState)
329 MOZ_IMPL_STATE_CLASS_GETTER(LongTapState)
331 AccessibleCaretEventHub::AccessibleCaretEventHub(PresShell* aPresShell)
332 : mPresShell(aPresShell) {}
334 void AccessibleCaretEventHub::Init() {
335 if (mInitialized || !mPresShell) {
336 return;
339 // Without nsAutoScriptBlocker, the script might be run after constructing
340 // mFirstCaret in AccessibleCaretManager's constructor, which might destructs
341 // the whole frame tree. Therefore we'll fail to construct mSecondCaret
342 // because we cannot get root frame or canvas frame from mPresShell to inject
343 // anonymous content. To avoid that, we protect Init() by nsAutoScriptBlocker.
344 // To reproduce, run "./mach crashtest layout/base/crashtests/897852.html"
345 // without the following scriptBlocker.
346 nsAutoScriptBlocker scriptBlocker;
348 nsPresContext* presContext = mPresShell->GetPresContext();
349 MOZ_ASSERT(presContext, "PresContext should be given in PresShell::Init()");
351 nsDocShell* docShell = presContext->GetDocShell();
352 if (!docShell) {
353 return;
356 docShell->AddWeakReflowObserver(this);
357 docShell->AddWeakScrollObserver(this);
359 mDocShell = static_cast<nsDocShell*>(docShell);
361 if (StaticPrefs::layout_accessiblecaret_use_long_tap_injector()) {
362 mLongTapInjectorTimer = NS_NewTimer();
365 mManager = MakeUnique<AccessibleCaretManager>(mPresShell);
367 mInitialized = true;
370 void AccessibleCaretEventHub::Terminate() {
371 if (!mInitialized) {
372 return;
375 if (mDocShell) {
376 mDocShell->RemoveWeakReflowObserver(this);
377 mDocShell->RemoveWeakScrollObserver(this);
380 if (mLongTapInjectorTimer) {
381 mLongTapInjectorTimer->Cancel();
384 mManager->Terminate();
385 mPresShell = nullptr;
386 mInitialized = false;
389 nsEventStatus AccessibleCaretEventHub::HandleEvent(WidgetEvent* aEvent) {
390 nsEventStatus status = nsEventStatus_eIgnore;
392 if (!mInitialized) {
393 return status;
396 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
398 switch (aEvent->mClass) {
399 case eMouseEventClass:
400 status = HandleMouseEvent(aEvent->AsMouseEvent());
401 break;
403 case eTouchEventClass:
404 status = HandleTouchEvent(aEvent->AsTouchEvent());
405 break;
407 case eKeyboardEventClass:
408 status = HandleKeyboardEvent(aEvent->AsKeyboardEvent());
409 break;
411 default:
412 MOZ_ASSERT_UNREACHABLE(
413 "PresShell should've filtered unwanted event classes!");
414 break;
417 return status;
420 nsEventStatus AccessibleCaretEventHub::HandleMouseEvent(
421 WidgetMouseEvent* aEvent) {
422 nsEventStatus rv = nsEventStatus_eIgnore;
424 if (aEvent->mButton != MouseButton::ePrimary) {
425 return rv;
428 int32_t id =
429 (mActiveTouchId == kInvalidTouchId ? kDefaultTouchId : mActiveTouchId);
430 nsPoint point = GetMouseEventPosition(aEvent);
432 if (aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp ||
433 aEvent->mMessage == eMouseClick ||
434 aEvent->mMessage == eMouseDoubleClick ||
435 aEvent->mMessage == eMouseLongTap) {
436 // Don't reset the source on mouse movement since that can
437 // happen anytime, even randomly during a touch sequence.
438 mManager->SetLastInputSource(aEvent->mInputSource);
441 switch (aEvent->mMessage) {
442 case eMouseDown:
443 AC_LOGV("Before eMouseDown, state: %s", mState->Name());
444 rv = mState->OnPress(this, point, id, eMouseEventClass);
445 AC_LOGV("After eMouseDown, state: %s, consume: %d", mState->Name(), rv);
446 break;
448 case eMouseMove:
449 AC_LOGV("Before eMouseMove, state: %s", mState->Name());
450 // The mouse move events synthesized from the touch move events can have
451 // wrong point (bug 1549355). Workaround it by ignoring the events when
452 // dragging the caret because the caret doesn't really need them.
453 rv = mState->OnMove(this, point, aEvent->mReason);
454 AC_LOGV("After eMouseMove, state: %s, consume: %d", mState->Name(), rv);
455 break;
457 case eMouseUp:
458 AC_LOGV("Before eMouseUp, state: %s", mState->Name());
459 rv = mState->OnRelease(this);
460 AC_LOGV("After eMouseUp, state: %s, consume: %d", mState->Name(), rv);
461 break;
463 case eMouseLongTap:
464 AC_LOGV("Before eMouseLongTap, state: %s", mState->Name());
465 rv = mState->OnLongTap(this, point);
466 AC_LOGV("After eMouseLongTap, state: %s, consume: %d", mState->Name(),
467 rv);
468 break;
470 default:
471 break;
474 return rv;
477 nsEventStatus AccessibleCaretEventHub::HandleTouchEvent(
478 WidgetTouchEvent* aEvent) {
479 if (aEvent->mTouches.IsEmpty()) {
480 AC_LOG("%s: Receive a touch event without any touch data!", __FUNCTION__);
481 return nsEventStatus_eIgnore;
484 nsEventStatus rv = nsEventStatus_eIgnore;
486 int32_t id =
487 (mActiveTouchId == kInvalidTouchId ? aEvent->mTouches[0]->Identifier()
488 : mActiveTouchId);
489 nsPoint point = GetTouchEventPosition(aEvent, id);
491 mManager->SetLastInputSource(MouseEvent_Binding::MOZ_SOURCE_TOUCH);
493 switch (aEvent->mMessage) {
494 case eTouchStart:
495 AC_LOGV("Before eTouchStart, state: %s", mState->Name());
496 rv = mState->OnPress(this, point, id, eTouchEventClass);
497 AC_LOGV("After eTouchStart, state: %s, consume: %d", mState->Name(), rv);
498 break;
500 case eTouchMove:
501 AC_LOGV("Before eTouchMove, state: %s", mState->Name());
502 // There is no synthesized touch move event.
503 rv = mState->OnMove(this, point, WidgetMouseEvent::eReal);
504 AC_LOGV("After eTouchMove, state: %s, consume: %d", mState->Name(), rv);
505 break;
507 case eTouchEnd:
508 AC_LOGV("Before eTouchEnd, state: %s", mState->Name());
509 rv = mState->OnRelease(this);
510 AC_LOGV("After eTouchEnd, state: %s, consume: %d", mState->Name(), rv);
511 break;
513 case eTouchCancel:
514 AC_LOGV("Got eTouchCancel, state: %s", mState->Name());
515 // Do nothing since we don't really care eTouchCancel anyway.
516 break;
518 default:
519 break;
522 return rv;
525 nsEventStatus AccessibleCaretEventHub::HandleKeyboardEvent(
526 WidgetKeyboardEvent* aEvent) {
527 mManager->SetLastInputSource(MouseEvent_Binding::MOZ_SOURCE_KEYBOARD);
529 switch (aEvent->mMessage) {
530 case eKeyUp:
531 AC_LOGV("eKeyUp, state: %s", mState->Name());
532 mManager->OnKeyboardEvent();
533 break;
535 case eKeyDown:
536 AC_LOGV("eKeyDown, state: %s", mState->Name());
537 mManager->OnKeyboardEvent();
538 break;
540 case eKeyPress:
541 AC_LOGV("eKeyPress, state: %s", mState->Name());
542 mManager->OnKeyboardEvent();
543 break;
545 default:
546 break;
549 return nsEventStatus_eIgnore;
552 bool AccessibleCaretEventHub::MoveDistanceIsLarge(const nsPoint& aPoint) const {
553 nsPoint delta = aPoint - mPressPoint;
554 return NS_hypot(delta.x, delta.y) >
555 AppUnitsPerCSSPixel() * kMoveStartToleranceInPixel;
558 void AccessibleCaretEventHub::LaunchLongTapInjector() {
559 if (!mLongTapInjectorTimer) {
560 return;
563 int32_t longTapDelay = StaticPrefs::ui_click_hold_context_menus_delay();
564 mLongTapInjectorTimer->InitWithNamedFuncCallback(
565 FireLongTap, this, longTapDelay, nsITimer::TYPE_ONE_SHOT,
566 "AccessibleCaretEventHub::LaunchLongTapInjector");
569 void AccessibleCaretEventHub::CancelLongTapInjector() {
570 if (!mLongTapInjectorTimer) {
571 return;
574 mLongTapInjectorTimer->Cancel();
577 /* static */
578 void AccessibleCaretEventHub::FireLongTap(nsITimer* aTimer,
579 void* aAccessibleCaretEventHub) {
580 RefPtr<AccessibleCaretEventHub> self =
581 static_cast<AccessibleCaretEventHub*>(aAccessibleCaretEventHub);
582 self->mState->OnLongTap(self, self->mPressPoint);
585 NS_IMETHODIMP
586 AccessibleCaretEventHub::Reflow(DOMHighResTimeStamp aStart,
587 DOMHighResTimeStamp aEnd) {
588 if (!mInitialized) {
589 return NS_OK;
592 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
594 if (mIsInReflowCallback) {
595 return NS_OK;
598 AutoRestore<bool> autoRestoreIsInReflowCallback(mIsInReflowCallback);
599 mIsInReflowCallback = true;
601 AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
602 mState->OnReflow(this);
603 return NS_OK;
606 NS_IMETHODIMP
607 AccessibleCaretEventHub::ReflowInterruptible(DOMHighResTimeStamp aStart,
608 DOMHighResTimeStamp aEnd) {
609 // Defer the error checking to Reflow().
610 return Reflow(aStart, aEnd);
613 void AccessibleCaretEventHub::AsyncPanZoomStarted() {
614 if (!mInitialized) {
615 return;
618 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
620 AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
621 mState->OnScrollStart(this);
624 void AccessibleCaretEventHub::AsyncPanZoomStopped() {
625 if (!mInitialized) {
626 return;
629 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
631 AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
632 mState->OnScrollEnd(this);
635 void AccessibleCaretEventHub::ScrollPositionChanged() {
636 if (!mInitialized) {
637 return;
640 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
642 AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
643 mState->OnScrollPositionChanged(this);
646 void AccessibleCaretEventHub::OnSelectionChange(Document* aDoc,
647 dom::Selection* aSel,
648 int16_t aReason) {
649 if (!mInitialized) {
650 return;
653 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
655 AC_LOG("%s, state: %s, reason: %d", __FUNCTION__, mState->Name(), aReason);
657 // XXX Here we may be in a hot path. So, if we could avoid this virtual call,
658 // we should do so.
659 mState->OnSelectionChanged(this, aDoc, aSel, aReason);
662 bool AccessibleCaretEventHub::ShouldDisableApz() const {
663 return mManager && mManager->ShouldDisableApz();
666 void AccessibleCaretEventHub::NotifyBlur(bool aIsLeavingDocument) {
667 if (!mInitialized) {
668 return;
671 MOZ_ASSERT(mRefCnt.get() > 1, "Expect caller holds us as well!");
673 AC_LOG("%s, state: %s", __FUNCTION__, mState->Name());
674 mState->OnBlur(this, aIsLeavingDocument);
677 nsPoint AccessibleCaretEventHub::GetTouchEventPosition(
678 WidgetTouchEvent* aEvent, int32_t aIdentifier) const {
679 for (dom::Touch* touch : aEvent->mTouches) {
680 if (touch->Identifier() == aIdentifier) {
681 LayoutDeviceIntPoint touchIntPoint = touch->mRefPoint;
683 // Get event coordinate relative to root frame.
684 nsIFrame* rootFrame = mPresShell->GetRootFrame();
685 return nsLayoutUtils::GetEventCoordinatesRelativeTo(
686 aEvent, touchIntPoint, RelativeTo{rootFrame});
689 return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
692 nsPoint AccessibleCaretEventHub::GetMouseEventPosition(
693 WidgetMouseEvent* aEvent) const {
694 LayoutDeviceIntPoint mouseIntPoint = aEvent->AsGUIEvent()->mRefPoint;
696 // Get event coordinate relative to root frame.
697 nsIFrame* rootFrame = mPresShell->GetRootFrame();
698 return nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, mouseIntPoint,
699 RelativeTo{rootFrame});
702 } // namespace mozilla