mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1215959
- (GeckoCaret2) Upgrade Core and AccessibleCaret, r=smaug
This commit is contained in:
parent
5ddecc922e
commit
e7b070ed41
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user