Bug 1293483 - Keep the carets hidden when the user is using a mouse to modify the selection. r?TYLin
MozReview-Commit-ID: zOIORfhYO
--- a/layout/base/AccessibleCaretEventHub.cpp
+++ b/layout/base/AccessibleCaretEventHub.cpp
@@ -509,16 +509,26 @@ AccessibleCaretEventHub::HandleMouseEven
if (aEvent->button != WidgetMouseEvent::eLeftButton) {
return rv;
}
int32_t id =
(mActiveTouchId == kInvalidTouchId ? kDefaultTouchId : mActiveTouchId);
nsPoint point = GetMouseEventPosition(aEvent);
+ if (aEvent->mMessage == eMouseDown ||
+ aEvent->mMessage == eMouseUp ||
+ aEvent->mMessage == eMouseClick ||
+ aEvent->mMessage == eMouseDoubleClick ||
+ aEvent->mMessage == eMouseLongTap) {
+ // Don't reset the source on mouse movement since that can
+ // happen anytime, even randomly during a touch sequence
+ mManager->SetLastInputSource(aEvent->inputSource);
+ }
+
switch (aEvent->mMessage) {
case eMouseDown:
AC_LOGV("Before eMouseDown, state: %s", mState->Name());
rv = mState->OnPress(this, point, id, eMouseEventClass);
AC_LOGV("After eMouseDown, state: %s, consume: %d", mState->Name(), rv);
break;
case eMouseMove:
@@ -557,16 +567,18 @@ AccessibleCaretEventHub::HandleTouchEven
nsEventStatus rv = nsEventStatus_eIgnore;
int32_t id =
(mActiveTouchId == kInvalidTouchId ? aEvent->mTouches[0]->Identifier()
: mActiveTouchId);
nsPoint point = GetTouchEventPosition(aEvent, id);
+ mManager->SetLastInputSource(nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
+
switch (aEvent->mMessage) {
case eTouchStart:
AC_LOGV("Before eTouchStart, state: %s", mState->Name());
rv = mState->OnPress(this, point, id, eTouchEventClass);
AC_LOGV("After eTouchStart, state: %s, consume: %d", mState->Name(), rv);
break;
case eTouchMove:
@@ -591,16 +603,18 @@ AccessibleCaretEventHub::HandleTouchEven
}
return rv;
}
nsEventStatus
AccessibleCaretEventHub::HandleKeyboardEvent(WidgetKeyboardEvent* aEvent)
{
+ mManager->SetLastInputSource(nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD);
+
switch (aEvent->mMessage) {
case eKeyUp:
AC_LOGV("eKeyUp, state: %s", mState->Name());
mManager->OnKeyboardEvent();
break;
case eKeyDown:
AC_LOGV("eKeyDown, state: %s", mState->Name());
--- a/layout/base/AccessibleCaretManager.cpp
+++ b/layout/base/AccessibleCaretManager.cpp
@@ -78,16 +78,18 @@ AccessibleCaretManager::sCaretsAlwaysSho
/*static*/ bool
AccessibleCaretManager::sCaretsScriptUpdates = false;
/*static*/ bool
AccessibleCaretManager::sCaretsAllowDraggingAcrossOtherCaret = true;
/*static*/ bool
AccessibleCaretManager::sHapticFeedback = false;
/*static*/ bool
AccessibleCaretManager::sExtendSelectionForPhoneNumber = false;
+/*static*/ bool
+AccessibleCaretManager::sHideCaretsForMouseInput = true;
AccessibleCaretManager::AccessibleCaretManager(nsIPresShell* aPresShell)
: mPresShell(aPresShell)
{
if (!mPresShell) {
return;
}
@@ -109,16 +111,18 @@ AccessibleCaretManager::AccessibleCaretM
Preferences::AddBoolVarCache(&sCaretsScriptUpdates,
"layout.accessiblecaret.allow_script_change_updates");
Preferences::AddBoolVarCache(&sCaretsAllowDraggingAcrossOtherCaret,
"layout.accessiblecaret.allow_dragging_across_other_caret", true);
Preferences::AddBoolVarCache(&sHapticFeedback,
"layout.accessiblecaret.hapticfeedback");
Preferences::AddBoolVarCache(&sExtendSelectionForPhoneNumber,
"layout.accessiblecaret.extend_selection_for_phone_number");
+ Preferences::AddBoolVarCache(&sHideCaretsForMouseInput,
+ "layout.accessiblecaret.hide_carets_for_mouse_input");
addedPrefs = true;
}
}
AccessibleCaretManager::~AccessibleCaretManager()
{
}
@@ -180,16 +184,23 @@ AccessibleCaretManager::OnSelectionChang
// Range will collapse after cutting or copying text.
if (aReason & (nsISelectionListener::COLLAPSETOSTART_REASON |
nsISelectionListener::COLLAPSETOEND_REASON)) {
HideCarets();
return NS_OK;
}
+ // For mouse input we don't want to show the carets.
+ if (sHideCaretsForMouseInput &&
+ mLastInputSource == nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {
+ HideCarets();
+ return NS_OK;
+ }
+
UpdateCarets();
return NS_OK;
}
void
AccessibleCaretManager::HideCarets()
{
if (mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible()) {
@@ -667,16 +678,24 @@ AccessibleCaretManager::OnScrollEnd()
if (GetCaretMode() == CaretMode::Cursor) {
if (!mFirstCaret->IsLogicallyVisible()) {
// If the caret is hidden (Appearance::None) due to timeout or blur, no
// need to update it.
return;
}
}
+ // For mouse input we don't want to show the carets.
+ if (sHideCaretsForMouseInput &&
+ mLastInputSource == nsIDOMMouseEvent::MOZ_SOURCE_MOUSE) {
+ AC_LOG("%s: HideCarets()", __FUNCTION__);
+ HideCarets();
+ return;
+ }
+
AC_LOG("%s: UpdateCarets()", __FUNCTION__);
UpdateCarets();
}
void
AccessibleCaretManager::OnScrollPositionChanged()
{
if (mLastUpdateCaretMode != GetCaretMode()) {
@@ -720,16 +739,22 @@ AccessibleCaretManager::OnKeyboardEvent(
void
AccessibleCaretManager::OnFrameReconstruction()
{
mFirstCaret->EnsureApzAware();
mSecondCaret->EnsureApzAware();
}
+void
+AccessibleCaretManager::SetLastInputSource(uint16_t aInputSource)
+{
+ mLastInputSource = aInputSource;
+}
+
Selection*
AccessibleCaretManager::GetSelection() const
{
RefPtr<nsFrameSelection> fs = GetFrameSelection();
if (!fs) {
return nullptr;
}
return fs->GetSelection(SelectionType::eNormal);
--- a/layout/base/AccessibleCaretManager.h
+++ b/layout/base/AccessibleCaretManager.h
@@ -5,16 +5,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef AccessibleCaretManager_h
#define AccessibleCaretManager_h
#include "AccessibleCaret.h"
#include "nsCOMPtr.h"
#include "nsCoord.h"
+#include "nsIDOMMouseEvent.h"
#include "nsIFrame.h"
#include "nsISelectionListener.h"
#include "mozilla/RefPtr.h"
#include "nsWeakReference.h"
#include "mozilla/dom/CaretStateChangedEvent.h"
#include "mozilla/EventForwards.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
@@ -97,16 +98,20 @@ public:
int16_t aReason);
// Handle key event.
virtual void OnKeyboardEvent();
// The canvas frame holding the accessible caret anonymous content elements
// was reconstructed, resulting in the content elements getting cloned.
virtual void OnFrameReconstruction();
+ // Update the manager with the last input source that was observed. This
+ // is used in part to determine if the carets should be shown or hidden.
+ void SetLastInputSource(uint16_t aInputSource);
+
protected:
// This enum representing the number of AccessibleCarets on the screen.
enum class CaretMode : uint8_t {
// No caret on the screen.
None,
// One caret, i.e. the selection is collapsed.
Cursor,
@@ -271,16 +276,22 @@ protected:
// Store the appearance of the carets when calling OnScrollStart() so that it
// can be restored in OnScrollEnd().
AccessibleCaret::Appearance mFirstCaretAppearanceOnScrollStart =
AccessibleCaret::Appearance::None;
AccessibleCaret::Appearance mSecondCaretAppearanceOnScrollStart =
AccessibleCaret::Appearance::None;
+ // The last input source that the event hub saw. We use this to decide whether
+ // or not show the carets when the selection is updated, as we want to hide
+ // the carets for mouse-triggered selection changes but show them for other
+ // input types such as touch.
+ uint16_t mLastInputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
+
static const int32_t kAutoScrollTimerDelay = 30;
// Clicking on the boundary of input or textarea will move the caret to the
// front or end of the content. To avoid this, we need to deflate the content
// boundary by 61 app units, which is 1 pixel + 1 app unit as defined in
// AppUnit.h.
static const int32_t kBoundaryAppUnits = 61;
@@ -314,16 +325,20 @@ protected:
// Preference to allow one caret to be dragged across the other caret without
// any limitation. When set to false, one caret cannot be dragged across the
// other one.
static bool sCaretsAllowDraggingAcrossOtherCaret;
// AccessibleCaret pref for haptic feedback behaviour on longPress.
static bool sHapticFeedback;
+
+ // Preference to keep carets hidden when the selection is being manipulated
+ // by mouse input (as opposed to touch/pen/etc.).
+ static bool sHideCaretsForMouseInput;
};
std::ostream& operator<<(std::ostream& aStream,
const AccessibleCaretManager::CaretMode& aCaretMode);
std::ostream& operator<<(std::ostream& aStream,
const AccessibleCaretManager::UpdateCaretsHint& aResult);
--- a/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
+++ b/layout/base/tests/marionette/test_accessiblecaret_cursor_mode.py
@@ -30,19 +30,21 @@ class AccessibleCaretCursorModeTestCase(
# Test html files.
_cursor_html = 'test_carets_cursor.html'
def setUp(self):
# Code to execute before every test is running.
super(AccessibleCaretCursorModeTestCase, self).setUp()
self.caret_tested_pref = 'layout.accessiblecaret.enabled'
self.caret_timeout_ms_pref = 'layout.accessiblecaret.timeout_ms'
+ self.hide_carets_for_mouse = 'layout.accessiblecaret.hide_carets_for_mouse_input'
self.prefs = {
self.caret_tested_pref: True,
self.caret_timeout_ms_pref: 0,
+ self.hide_carets_for_mouse: False,
}
self.marionette.set_prefs(self.prefs)
self.actions = Actions(self.marionette)
def open_test_html(self, test_html):
self.marionette.navigate(self.marionette.absolute_url(test_html))
@parameterized(_input_id, el_id=_input_id)
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5248,16 +5248,19 @@ pref("layout.accessiblecaret.allow_scrip
pref("layout.accessiblecaret.allow_dragging_across_other_caret", true);
// Optionally provide haptic feedback on longPress selection events.
pref("layout.accessiblecaret.hapticfeedback", false);
// Smart phone-number selection on long-press is not enabled by default.
pref("layout.accessiblecaret.extend_selection_for_phone_number", false);
+// Keep the accessible carets hidden when the user is using mouse input.
+pref("layout.accessiblecaret.hide_carets_for_mouse_input", true);
+
// Wakelock is disabled by default.
pref("dom.wakelock.enabled", false);
// The URL of the Firefox Accounts auth server backend
pref("identity.fxaccounts.auth.uri", "https://api.accounts.firefox.com/v1");
// disable mozsample size for now
pref("image.mozsamplesize.enabled", false);