Bug 1215959 - (GeckoCaret2) Upgrade Core and AccessibleCaret, r=smaug

This commit is contained in:
Mark Capella 2015-12-01 15:25:06 -05:00
Родитель 5ddecc922e
Коммит e7b070ed41
13 изменённых файлов: 137 добавлений и 23 удалений

Просмотреть файл

@ -8,7 +8,7 @@
interface nsIDOMDocument;
interface nsISelection;
[scriptable, uuid(280cd784-23c2-468d-8624-354e0b3804bd)]
[scriptable, uuid(45686299-ae2b-46bc-9502-c56c35691ab9)]
interface nsISelectionListener : nsISupports
{
const short NO_REASON=0;
@ -19,6 +19,7 @@ interface nsISelectionListener : nsISupports
const short SELECTALL_REASON=16;
const short COLLAPSETOSTART_REASON=32;
const short COLLAPSETOEND_REASON=64;
const short IME_REASON=128;
void notifySelectionChanged(in nsIDOMDocument doc, in nsISelection sel, in short reason);
};

Просмотреть файл

@ -28,7 +28,7 @@ template<class T> class nsTArray;
native nsDirection(nsDirection);
native ScrollAxis(nsIPresShell::ScrollAxis);
[scriptable, builtinclass, uuid(5a82ee9a-35ce-11e4-8c3e-b7043d68ad70)]
[scriptable, builtinclass, uuid(0c9f4f74-ee7e-4fe9-be6b-0ba856368178)]
interface nsISelectionPrivate : nsISelection
{
const short ENDOFPRECEDINGLINE=0;
@ -40,12 +40,12 @@ interface nsISelectionPrivate : nsISelection
/* startBatchChanges
match this up with endbatchChanges. will stop ui updates while multiple selection methods are called
*/
[noscript] void startBatchChanges();
[noscript] void startBatchChanges();
/* endBatchChanges
match this up with startBatchChanges
*/
[noscript] void endBatchChanges();
[noscript] void endBatchChanges();
DOMString toStringWithFormat(in string formatType, in unsigned long flags, in int32_t wrapColumn);
void addSelectionListener(in nsISelectionListener newListener);

Просмотреть файл

@ -1658,7 +1658,10 @@ ContentEventHandler::OnSelectionEvent(WidgetSelectionEvent* aEvent)
}
}
}
mSelection->EndBatchChanges();
// Pass the eSetSelection events reason along with the BatchChange-end
// selection change notifications.
mSelection->EndBatchChangesInternal(aEvent->mReason);
NS_ENSURE_SUCCESS(rv, rv);
mSelection->ScrollIntoViewInternal(

Просмотреть файл

@ -18,6 +18,7 @@ dictionary CaretStateChangedEventInit : EventInit {
DOMRectReadOnly? boundingClientRect = null;
CaretChangedReason reason = "visibilitychange";
boolean caretVisible = false;
boolean caretVisuallyVisible = false;
boolean selectionVisible = false;
boolean selectionEditable = false;
DOMString selectedTextContent = "";
@ -30,6 +31,7 @@ interface CaretStateChangedEvent : Event {
readonly attribute DOMRectReadOnly? boundingClientRect;
readonly attribute CaretChangedReason reason;
readonly attribute boolean caretVisible;
readonly attribute boolean caretVisuallyVisible;
readonly attribute boolean selectionVisible;
readonly attribute boolean selectionEditable;
readonly attribute DOMString selectedTextContent;

Просмотреть файл

@ -7,6 +7,7 @@
#include "mozilla/dom/Selection.h" // local var
#include "mozilla/dom/Text.h" // mTextNode
#include "mozilla/Preferences.h" // nsCaret Visibility
#include "nsAString.h" // params
#include "nsDebug.h" // for NS_ASSERTION, etc
#include "nsEditor.h" // mEditor
@ -18,6 +19,10 @@
using namespace mozilla;
using namespace mozilla::dom;
/*static*/ bool
IMETextTxn::sCaretsExtendedVisibility = false;
IMETextTxn::IMETextTxn(Text& aTextNode, uint32_t aOffset,
uint32_t aReplaceLength,
TextRangeArray* aTextRangeArray,
@ -32,6 +37,12 @@ IMETextTxn::IMETextTxn(Text& aTextNode, uint32_t aOffset,
, mEditor(aEditor)
, mFixed(false)
{
static bool addedPrefs = false;
if (!addedPrefs) {
mozilla::Preferences::AddBoolVarCache(&sCaretsExtendedVisibility,
"layout.accessiblecaret.extendedvisibility");
addedPrefs = true;
}
}
IMETextTxn::~IMETextTxn()
@ -297,11 +308,16 @@ IMETextTxn::SetIMESelection(nsEditor& aEditor,
rv = selection->Collapse(aTextNode, caretOffset);
NS_ASSERTION(NS_SUCCEEDED(rv),
"Failed to set caret at the end of composition string");
// If caret range isn't specified explicitly, we should hide the caret.
aEditor.HideCaret(true);
// Hiding the caret benefits a Windows build (see bug 555642 comment #6),
// but causes loss of Fennec AccessibleCaret visibility during Caret drag.
if (!sCaretsExtendedVisibility) {
aEditor.HideCaret(true);
}
}
rv = selection->EndBatchChanges();
rv = selection->EndBatchChangesInternal();
NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to end batch changes");
return rv;

Просмотреть файл

@ -83,6 +83,13 @@ private:
nsEditor& mEditor;
bool mFixed;
/*
* AccessibleCaret visibility preference. Used to avoid hiding caret during
* handle drag, caused by dynamic eCompositionCommit events generated by
* the keyboard IME for autoSuggest/autoCorrect support.
*/
static bool sCaretsExtendedVisibility;
};
NS_DEFINE_STATIC_IID_ACCESSOR(IMETextTxn, NS_IMETEXTTXN_IID)

Просмотреть файл

@ -61,14 +61,27 @@ std::ostream& operator<<(std::ostream& aStream,
}
#undef AC_PROCESS_ENUM_TO_STREAM
/*static*/ bool
AccessibleCaretManager::sCaretsExtendedVisibility = false;
AccessibleCaretManager::AccessibleCaretManager(nsIPresShell* aPresShell)
: mPresShell(aPresShell)
{
if (mPresShell) {
mFirstCaret = MakeUnique<AccessibleCaret>(mPresShell);
mSecondCaret = MakeUnique<AccessibleCaret>(mPresShell);
if (!mPresShell) {
return;
}
mCaretTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
mFirstCaret = MakeUnique<AccessibleCaret>(mPresShell);
mSecondCaret = MakeUnique<AccessibleCaret>(mPresShell);
mCaretTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1");
static bool addedPrefs = false;
if (!addedPrefs) {
Preferences::AddBoolVarCache(&sCaretsExtendedVisibility,
"layout.accessiblecaret.extendedvisibility");
addedPrefs = true;
}
}
@ -81,15 +94,39 @@ nsresult
AccessibleCaretManager::OnSelectionChanged(nsIDOMDocument* aDoc,
nsISelection* aSel, int16_t aReason)
{
Selection* selection = GetSelection();
AC_LOG("%s: aSel: %p, GetSelection(): %p, aReason: %d", __FUNCTION__,
aSel, GetSelection(), aReason);
if (aSel != GetSelection()) {
aSel, selection, aReason);
if (aSel != selection) {
return NS_OK;
}
// Move the cursor by Javascript.
// eSetSelection events from the Fennec widget IME can be generated
// by autoSuggest, autoCorrect, and nsCaret position changes.
if (aReason & nsISelectionListener::IME_REASON) {
if (GetCaretMode() == CaretMode::Cursor) {
// Caret position changes need us to open/update,
// or hide the AccessibleCaret.
FlushLayout();
UpdateCarets();
} else {
// Ignore transient autoSuggest selection styling,
// or autoCorrect text updates.
}
return NS_OK;
}
// Move the cursor by Javascript / or unknown internal.
if (aReason == nsISelectionListener::NO_REASON) {
// Extended visibility won't make hidden carets visible. Visible carets will
// be updated or hidden as appropriate.
if (sCaretsExtendedVisibility &&
(mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible())) {
FlushLayout();
UpdateCarets();
return NS_OK;
}
// Default for NO_REASON is to make hidden.
HideCarets();
return NS_OK;
}
@ -130,6 +167,18 @@ AccessibleCaretManager::HideCarets()
}
}
void
AccessibleCaretManager::DoNotShowCarets()
{
if (mFirstCaret->IsLogicallyVisible() || mSecondCaret->IsLogicallyVisible()) {
AC_LOG("%s", __FUNCTION__);
mFirstCaret->SetAppearance(Appearance::NormalNotShown);
mSecondCaret->SetAppearance(Appearance::NormalNotShown);
DispatchCaretStateChangedEvent(CaretChangedReason::Visibilitychange);
CancelCaretTimeoutTimer();
}
}
void
AccessibleCaretManager::UpdateCarets(UpdateCaretsHint aHint)
{
@ -459,7 +508,12 @@ AccessibleCaretManager::OnScrollStart()
mFirstCaretAppearanceOnScrollStart = mFirstCaret->GetAppearance();
}
HideCarets();
// Hide the carets. (Extended visibility makes them "NormalNotShown").
if (sCaretsExtendedVisibility) {
DoNotShowCarets();
} else {
HideCarets();
}
}
void
@ -1091,6 +1145,8 @@ AccessibleCaretManager::DispatchCaretStateChangedEvent(CaretChangedReason aReaso
init.mCollapsed = sel->IsCollapsed();
init.mCaretVisible = mFirstCaret->IsLogicallyVisible() ||
mSecondCaret->IsLogicallyVisible();
init.mCaretVisuallyVisible = mFirstCaret->IsVisuallyVisible() ||
mSecondCaret->IsVisuallyVisible();
sel->Stringify(init.mSelectedTextContent);
RefPtr<CaretStateChangedEvent> event =

Просмотреть файл

@ -130,6 +130,10 @@ protected:
// Force hiding all carets regardless of the current selection status.
void HideCarets();
// Force carets to be "present" logically, but not visible. Allows ActionBar
// to stay open when carets visibility is supressed during scroll.
void DoNotShowCarets();
void UpdateCaretsForCursorMode(UpdateCaretsHint aHint);
void UpdateCaretsForSelectionMode(UpdateCaretsHint aHint);
@ -239,6 +243,11 @@ protected:
// boundary by 61 app units, which is 1 pixel + 1 app unit as defined in
// AppUnit.h.
static const int32_t kBoundaryAppUnits = 61;
// AccessibleCaret visibility preference. Used to avoid hiding caret during
// (NO_REASON) selection change notifications generated by keyboard IME, and to
// maintain a visible ActionBar while carets NotShown during scroll.
static bool sCaretsExtendedVisibility;
};
std::ostream& operator<<(std::ostream& aStream,

Просмотреть файл

@ -13,6 +13,7 @@
#include "mozilla/TextRange.h"
#include "nsISelection.h"
#include "nsISelectionController.h"
#include "nsISelectionListener.h"
#include "nsISelectionPrivate.h"
#include "nsRange.h"
#include "nsThreadUtils.h"
@ -64,6 +65,8 @@ public:
NS_DECL_NSISELECTION
NS_DECL_NSISELECTIONPRIVATE
nsresult EndBatchChangesInternal(int16_t aReason = nsISelectionListener::NO_REASON);
nsIDocument* GetParentObject() const;
// utility methods for scrolling the selection into view
@ -345,7 +348,7 @@ public:
~SelectionBatcher()
{
if (mSelection) {
mSelection->EndBatchChanges();
mSelection->EndBatchChangesInternal();
}
}
};

Просмотреть файл

@ -597,7 +597,8 @@ public:
nsFrameSelection();
void StartBatchChanges();
void EndBatchChanges();
void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
/*unsafe*/
nsresult DeleteFromDocument();

Просмотреть файл

@ -55,7 +55,6 @@ static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
#include "SelectionCarets.h"
#include "AccessibleCaretEventHub.h"
#include "AccessibleCaretManager.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TextEvents.h"
@ -2243,11 +2242,14 @@ nsFrameSelection::StartBatchChanges()
}
void
nsFrameSelection::EndBatchChanges()
nsFrameSelection::EndBatchChanges(int16_t aReason)
{
mBatching--;
NS_ASSERTION(mBatching >=0,"Bad mBatching");
if (mBatching == 0 && mChangesDuringBatching){
if (mBatching == 0 && mChangesDuringBatching) {
int16_t postReason = PopReason() | aReason;
PostReason(postReason);
mChangesDuringBatching = false;
NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL);
}
@ -5995,9 +5997,15 @@ Selection::StartBatchChanges()
NS_IMETHODIMP
Selection::EndBatchChanges()
{
if (mFrameSelection)
mFrameSelection->EndBatchChanges();
return EndBatchChangesInternal();
}
nsresult
Selection::EndBatchChangesInternal(int16_t aReason)
{
if (mFrameSelection) {
mFrameSelection->EndBatchChanges(aReason);
}
return NS_OK;
}

Просмотреть файл

@ -16,6 +16,7 @@
#include "mozilla/FontRange.h"
#include "nsCOMPtr.h"
#include "nsIDOMKeyEvent.h"
#include "nsISelectionListener.h"
#include "nsITransferable.h"
#include "nsRect.h"
#include "nsStringGlue.h"
@ -662,6 +663,7 @@ public:
, mExpandToClusterBoundary(true)
, mSucceeded(false)
, mUseNativeLineBreak(true)
, mReason(nsISelectionListener::NO_REASON)
{
}
@ -686,6 +688,9 @@ public:
bool mSucceeded;
// true if native line breaks are used for mOffset and mLength
bool mUseNativeLineBreak;
// Fennec provides eSetSelection reason codes for downstream
// use in AccessibleCaret visibility logic.
int16_t mReason;
};
/******************************************************************************

Просмотреть файл

@ -2317,6 +2317,7 @@ nsWindow::Natives::OnImeReplaceText(int32_t aStart, int32_t aEnd,
event.mOffset = uint32_t(aStart);
event.mLength = uint32_t(aEnd - aStart);
event.mExpandToClusterBoundary = false;
event.mReason = nsISelectionListener::IME_REASON;
window.DispatchEvent(&event);
}
@ -2445,6 +2446,7 @@ nsWindow::Natives::OnImeUpdateComposition(int32_t aStart, int32_t aEnd)
selEvent.mLength = std::max(aStart, aEnd) - selEvent.mOffset;
selEvent.mReversed = aStart > aEnd;
selEvent.mExpandToClusterBoundary = false;
selEvent.mReason = nsISelectionListener::IME_REASON;
window.DispatchEvent(&selEvent);
return;
@ -2483,6 +2485,7 @@ nsWindow::Natives::OnImeUpdateComposition(int32_t aStart, int32_t aEnd)
event.mOffset = uint32_t(aStart);
event.mLength = uint32_t(aEnd - aStart);
event.mExpandToClusterBoundary = false;
event.mReason = nsISelectionListener::IME_REASON;
window.DispatchEvent(&event);
}