Bug 1741792 part 1: Cache the caret in the parent process using caret events. r=eeejay

As well as the caret offset, we also need to cache whether the caret is at the end of a line.
Therefore, this information has been added to caret events.

Differential Revision: https://phabricator.services.mozilla.com/D132097
This commit is contained in:
James Teh 2021-12-01 04:48:33 +00:00
Родитель 8166483436
Коммит 934c9cb61c
11 изменённых файлов: 77 добавлений и 28 удалений

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

@ -244,9 +244,9 @@ already_AddRefed<nsIAccessibleEvent> a11y::MakeXPCEvent(AccEvent* aEvent) {
if (eventGroup & (1 << AccEvent::eCaretMoveEvent)) { if (eventGroup & (1 << AccEvent::eCaretMoveEvent)) {
AccCaretMoveEvent* cm = downcast_accEvent(aEvent); AccCaretMoveEvent* cm = downcast_accEvent(aEvent);
xpEvent = new xpcAccCaretMoveEvent(type, ToXPC(acc), ToXPCDocument(doc), xpEvent = new xpcAccCaretMoveEvent(
node, fromUser, cm->GetCaretOffset(), type, ToXPC(acc), ToXPCDocument(doc), node, fromUser,
cm->IsSelectionCollapsed()); cm->GetCaretOffset(), cm->IsSelectionCollapsed(), cm->IsAtEndOfLine());
return xpEvent.forget(); return xpEvent.forget();
} }

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

@ -341,12 +341,13 @@ class AccReorderEvent : public AccTreeMutationEvent {
class AccCaretMoveEvent : public AccEvent { class AccCaretMoveEvent : public AccEvent {
public: public:
AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset, AccCaretMoveEvent(LocalAccessible* aAccessible, int32_t aCaretOffset,
bool aIsSelectionCollapsed, bool aIsSelectionCollapsed, bool aIsAtEndOfLine,
EIsFromUserInput aIsFromUserInput = eAutoDetect) EIsFromUserInput aIsFromUserInput = eAutoDetect)
: AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, : AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible,
aIsFromUserInput), aIsFromUserInput),
mCaretOffset(aCaretOffset), mCaretOffset(aCaretOffset),
mIsSelectionCollapsed(aIsSelectionCollapsed) {} mIsSelectionCollapsed(aIsSelectionCollapsed),
mIsAtEndOfLine(aIsAtEndOfLine) {}
virtual ~AccCaretMoveEvent() {} virtual ~AccCaretMoveEvent() {}
// AccEvent // AccEvent
@ -359,11 +360,13 @@ class AccCaretMoveEvent : public AccEvent {
int32_t GetCaretOffset() const { return mCaretOffset; } int32_t GetCaretOffset() const { return mCaretOffset; }
bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; } bool IsSelectionCollapsed() const { return mIsSelectionCollapsed; }
bool IsAtEndOfLine() { return mIsAtEndOfLine; }
private: private:
int32_t mCaretOffset; int32_t mCaretOffset;
bool mIsSelectionCollapsed; bool mIsSelectionCollapsed;
bool mIsAtEndOfLine;
}; };
/** /**

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

@ -148,9 +148,9 @@ void SelectionManager::ProcessTextSelChangeEvent(AccEvent* aEvent) {
selection->FocusOffset()); selection->FocusOffset());
mAccWithCaret = caretCntr; mAccWithCaret = caretCntr;
if (mCaretOffset != -1) { if (mCaretOffset != -1) {
RefPtr<AccCaretMoveEvent> caretMoveEvent = RefPtr<AccCaretMoveEvent> caretMoveEvent = new AccCaretMoveEvent(
new AccCaretMoveEvent(caretCntr, mCaretOffset, selection->IsCollapsed(), caretCntr, mCaretOffset, selection->IsCollapsed(),
aEvent->FromUserInput()); caretCntr->IsCaretAtEndOfLine(), aEvent->FromUserInput());
nsEventShell::FireEvent(caretMoveEvent); nsEventShell::FireEvent(caretMoveEvent);
} }
} }

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

@ -954,7 +954,8 @@ nsresult LocalAccessible::HandleAccEvent(AccEvent* aEvent) {
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: { case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED: {
AccCaretMoveEvent* event = downcast_accEvent(aEvent); AccCaretMoveEvent* event = downcast_accEvent(aEvent);
ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset(), ipcDoc->SendCaretMoveEvent(id, event->GetCaretOffset(),
event->IsSelectionCollapsed()); event->IsSelectionCollapsed(),
event->IsAtEndOfLine());
break; break;
} }
case nsIAccessibleEvent::EVENT_TEXT_INSERTED: case nsIAccessibleEvent::EVENT_TEXT_INSERTED:

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

@ -20,4 +20,9 @@ interface nsIAccessibleCaretMoveEvent: nsIAccessibleEvent
* Return true if there is no selection. * Return true if there is no selection.
*/ */
readonly attribute bool isSelectionCollapsed; readonly attribute bool isSelectionCollapsed;
/**
* Return true if the caret is at the end of a line.
*/
readonly attribute bool isAtEndOfLine;
}; };

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

@ -300,7 +300,8 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
#if defined(XP_WIN) #if defined(XP_WIN)
const LayoutDeviceIntRect& aCaretRect, const LayoutDeviceIntRect& aCaretRect,
#endif // defined (XP_WIN) #endif // defined (XP_WIN)
const int32_t& aOffset, const bool& aIsSelectionCollapsed) { const int32_t& aOffset, const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine) {
if (mShutdown) { if (mShutdown) {
return IPC_OK(); return IPC_OK();
} }
@ -311,6 +312,10 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
return IPC_OK(); return IPC_OK();
} }
mCaretId = aID;
mCaretOffset = aOffset;
mIsCaretAtEndOfLine = aIsAtEndOfLine;
#if defined(XP_WIN) #if defined(XP_WIN)
ProxyCaretMoveEvent(proxy, aCaretRect); ProxyCaretMoveEvent(proxy, aCaretRect);
#else #else
@ -326,8 +331,9 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvCaretMoveEvent(
nsINode* node = nullptr; nsINode* node = nullptr;
bool fromUser = true; // XXX fix me bool fromUser = true; // XXX fix me
uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED; uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED;
RefPtr<xpcAccCaretMoveEvent> event = new xpcAccCaretMoveEvent( RefPtr<xpcAccCaretMoveEvent> event =
type, xpcAcc, doc, node, fromUser, aOffset, aIsSelectionCollapsed); new xpcAccCaretMoveEvent(type, xpcAcc, doc, node, fromUser, aOffset,
aIsSelectionCollapsed, aIsAtEndOfLine);
nsCoreUtils::DispatchAccEvent(std::move(event)); nsCoreUtils::DispatchAccEvent(std::move(event));
return IPC_OK(); return IPC_OK();

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

@ -42,7 +42,10 @@ class DocAccessibleParent : public RemoteAccessible,
mTopLevel(false), mTopLevel(false),
mTopLevelInContentProcess(false), mTopLevelInContentProcess(false),
mShutdown(false), mShutdown(false),
mFocus(0) { mFocus(0),
mCaretId(0),
mCaretOffset(-1),
mIsCaretAtEndOfLine(false) {
sMaxDocID++; sMaxDocID++;
mActorID = sMaxDocID; mActorID = sMaxDocID;
MOZ_ASSERT(!LiveDocs().Get(mActorID)); MOZ_ASSERT(!LiveDocs().Get(mActorID));
@ -103,7 +106,8 @@ class DocAccessibleParent : public RemoteAccessible,
#if defined(XP_WIN) #if defined(XP_WIN)
const LayoutDeviceIntRect& aCaretRect, const LayoutDeviceIntRect& aCaretRect,
#endif #endif
const int32_t& aOffset, const bool& aIsSelectionCollapsed) final; const int32_t& aOffset, const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine) final;
virtual mozilla::ipc::IPCResult RecvTextChangeEvent( virtual mozilla::ipc::IPCResult RecvTextChangeEvent(
const uint64_t& aID, const nsString& aStr, const int32_t& aStart, const uint64_t& aID, const nsString& aStr, const int32_t& aStart,
@ -288,6 +292,25 @@ class DocAccessibleParent : public RemoteAccessible,
return const_cast<DocAccessibleParent*>(this)->GetAccessible(mFocus); return const_cast<DocAccessibleParent*>(this)->GetAccessible(mFocus);
} }
/**
* Get the HyperText Accessible containing the caret and the offset of the
* caret within. If there is no caret in this document, returns
* {nullptr, -1}.
*/
std::pair<RemoteAccessible*, int32_t> GetCaret() const {
if (mCaretOffset == -1) {
return {nullptr, -1};
}
RemoteAccessible* acc =
const_cast<DocAccessibleParent*>(this)->GetAccessible(mCaretId);
if (!acc) {
return {nullptr, -1};
}
return {acc, mCaretOffset};
}
bool IsCaretAtEndOfLine() const { return mIsCaretAtEndOfLine; }
private: private:
~DocAccessibleParent() { ~DocAccessibleParent() {
LiveDocs().Remove(mActorID); LiveDocs().Remove(mActorID);
@ -352,6 +375,9 @@ class DocAccessibleParent : public RemoteAccessible,
nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs; nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs;
uint64_t mFocus; uint64_t mFocus;
uint64_t mCaretId;
int32_t mCaretOffset;
bool mIsCaretAtEndOfLine;
static uint64_t sMaxDocID; static uint64_t sMaxDocID;
static nsTHashMap<nsUint64HashKey, DocAccessibleParent*>& LiveDocs() { static nsTHashMap<nsUint64HashKey, DocAccessibleParent*>& LiveDocs() {

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

@ -96,7 +96,8 @@ parent:
async ShowEvent(ShowEventData data, bool aFromuser); async ShowEvent(ShowEventData data, bool aFromuser);
async HideEvent(uint64_t aRootID, bool aFromUser); async HideEvent(uint64_t aRootID, bool aFromUser);
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
async CaretMoveEvent(uint64_t aID, int32_t aOffset, bool aIsSelectionCollapsed); async CaretMoveEvent(uint64_t aID, int32_t aOffset,
bool aIsSelectionCollapsed, bool aIsAtEndOfLine);
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen, async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
bool aIsInsert, bool aFromUser); bool aIsInsert, bool aFromUser);
async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType); async SelectionEvent(uint64_t aID, uint64_t aWidgetID, uint32_t aType);

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

@ -199,21 +199,23 @@ bool DocAccessibleChild::SendFocusEvent(const uint64_t& aID,
bool DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID, bool DocAccessibleChild::SendCaretMoveEvent(const uint64_t& aID,
const int32_t& aOffset, const int32_t& aOffset,
const bool& aIsSelectionCollapsed) { const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine) {
return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset, return SendCaretMoveEvent(aID, GetCaretRectFor(aID), aOffset,
aIsSelectionCollapsed); aIsSelectionCollapsed, aIsAtEndOfLine);
} }
bool DocAccessibleChild::SendCaretMoveEvent( bool DocAccessibleChild::SendCaretMoveEvent(
const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect, const uint64_t& aID, const LayoutDeviceIntRect& aCaretRect,
const int32_t& aOffset, const bool& aIsSelectionCollapsed) { const int32_t& aOffset, const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine) {
if (IsConstructedInParentProcess()) { if (IsConstructedInParentProcess()) {
return PDocAccessibleChild::SendCaretMoveEvent(aID, aCaretRect, aOffset, return PDocAccessibleChild::SendCaretMoveEvent(
aIsSelectionCollapsed); aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine);
} }
PushDeferredEvent(MakeUnique<SerializedCaretMove>( PushDeferredEvent(MakeUnique<SerializedCaretMove>(
this, aID, aCaretRect, aOffset, aIsSelectionCollapsed)); this, aID, aCaretRect, aOffset, aIsSelectionCollapsed, aIsAtEndOfLine));
return true; return true;
} }

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

@ -51,11 +51,13 @@ class DocAccessibleChild : public DocAccessibleChildBase {
bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState, bool SendStateChangeEvent(const uint64_t& aID, const uint64_t& aState,
const bool& aEnabled); const bool& aEnabled);
bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset, bool SendCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset,
const bool& aIsSelectionCollapsed); const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine);
bool SendCaretMoveEvent(const uint64_t& aID, bool SendCaretMoveEvent(const uint64_t& aID,
const LayoutDeviceIntRect& aCaretRect, const LayoutDeviceIntRect& aCaretRect,
const int32_t& aOffset, const int32_t& aOffset,
const bool& aIsSelectionCollapsed); const bool& aIsSelectionCollapsed,
const bool& aIsAtEndOfLine);
bool SendFocusEvent(const uint64_t& aID); bool SendFocusEvent(const uint64_t& aID);
bool SendFocusEvent(const uint64_t& aID, bool SendFocusEvent(const uint64_t& aID,
const LayoutDeviceIntRect& aCaretRect); const LayoutDeviceIntRect& aCaretRect);
@ -173,22 +175,24 @@ class DocAccessibleChild : public DocAccessibleChildBase {
struct SerializedCaretMove final : public DeferredEvent { struct SerializedCaretMove final : public DeferredEvent {
SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID, SerializedCaretMove(DocAccessibleChild* aTarget, uint64_t aID,
const LayoutDeviceIntRect& aCaretRect, int32_t aOffset, const LayoutDeviceIntRect& aCaretRect, int32_t aOffset,
bool aIsSelectionCollapsed) bool aIsSelectionCollapsed, bool aIsAtEndOfLine)
: DeferredEvent(aTarget), : DeferredEvent(aTarget),
mID(aID), mID(aID),
mCaretRect(aCaretRect), mCaretRect(aCaretRect),
mOffset(aOffset), mOffset(aOffset),
mIsSelectionCollapsed(aIsSelectionCollapsed) {} mIsSelectionCollapsed(aIsSelectionCollapsed),
mIsAtEndOfLine(aIsAtEndOfLine) {}
void Dispatch(DocAccessibleChild* aIPCDoc) override { void Dispatch(DocAccessibleChild* aIPCDoc) override {
Unused << aIPCDoc->SendCaretMoveEvent(mID, mCaretRect, mOffset, Unused << aIPCDoc->SendCaretMoveEvent(
mIsSelectionCollapsed); mID, mCaretRect, mOffset, mIsSelectionCollapsed, mIsAtEndOfLine);
} }
uint64_t mID; uint64_t mID;
LayoutDeviceIntRect mCaretRect; LayoutDeviceIntRect mCaretRect;
int32_t mOffset; int32_t mOffset;
bool mIsSelectionCollapsed; bool mIsSelectionCollapsed;
bool mIsAtEndOfLine;
}; };
struct SerializedFocus final : public DeferredEvent { struct SerializedFocus final : public DeferredEvent {

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

@ -59,7 +59,8 @@ parent:
async HideEvent(uint64_t aRootID, bool aFromUser); async HideEvent(uint64_t aRootID, bool aFromUser);
async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled); async StateChangeEvent(uint64_t aID, uint64_t aState, bool aEnabled);
async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect, async CaretMoveEvent(uint64_t aID, LayoutDeviceIntRect aCaretRect,
int32_t aOffset, bool aIsSelectionCollapsed); int32_t aOffset, bool aIsAtEndOfLine,
bool aIsSelectionCollapsed);
async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen, async TextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, uint32_t aLen,
bool aIsInsert, bool aFromUser); bool aIsInsert, bool aFromUser);
sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart, sync SyncTextChangeEvent(uint64_t aID, nsString aStr, int32_t aStart,