diff --git a/accessible/base/FocusManager.cpp b/accessible/base/FocusManager.cpp index dbbf2416cde5..42088c4fe5c9 100644 --- a/accessible/base/FocusManager.cpp +++ b/accessible/base/FocusManager.cpp @@ -27,6 +27,46 @@ FocusManager::~FocusManager() { } +Accessible* +FocusManager::FocusedAccessible() const +{ + if (mActiveItem) + return mActiveItem; + + nsINode* focusedNode = FocusedDOMNode(); + if (focusedNode) { + DocAccessible* doc = + GetAccService()->GetDocAccessible(focusedNode->OwnerDoc()); + return doc ? doc->GetAccessibleEvenIfNotInMapOrContainer(focusedNode) : nullptr; + } + + return nullptr; +} + +bool +FocusManager::IsFocused(const Accessible* aAccessible) const +{ + if (mActiveItem) + return mActiveItem == aAccessible; + + nsINode* focusedNode = FocusedDOMNode(); + if (focusedNode) { + // XXX: Before getting an accessible for node having a DOM focus make sure + // they belong to the same document because it can trigger unwanted document + // accessible creation for temporary about:blank document. Without this + // peculiarity we would end up with plain implementation based on + // FocusedAccessible() method call. Make sure this issue is fixed in + // bug 638465. + if (focusedNode->OwnerDoc() == aAccessible->GetNode()->OwnerDoc()) { + DocAccessible* doc = + GetAccService()->GetDocAccessible(focusedNode->OwnerDoc()); + return aAccessible == + (doc ? doc->GetAccessibleEvenIfNotInMapOrContainer(focusedNode) : nullptr); + } + } + return false; +} + bool FocusManager::IsFocusWithin(const Accessible* aContainer) const { @@ -153,23 +193,9 @@ FocusManager::ActiveItemChanged(Accessible* aItem, bool aCheckIfActive) // If active item is changed then fire accessible focus event on it, otherwise // if there's no an active item then fire focus event to accessible having // DOM focus. - Accessible* target = nullptr; - if (aItem) { - target = aItem; - } else { - nsINode* focusedNode = FocusedDOMNode(); - if (focusedNode) { - DocAccessible* doc = - GetAccService()->GetDocAccessible(focusedNode->OwnerDoc()); - if (doc) { - target = doc->GetAccessibleEvenIfNotInMapOrContainer(focusedNode); - } - } - } - - if (target) { + Accessible* target = FocusedAccessible(); + if (target) DispatchFocusEvent(target->Document(), target); - } } void @@ -270,9 +296,6 @@ FocusManager::ProcessFocusEvent(AccEvent* aEvent) } } - mFocusedAcc = target; - mFocusedProxy = nullptr; - // Fire menu start/end events for ARIA menus. if (target->IsARIARole(nsGkAtoms::menuitem)) { // The focus was moved into menu. diff --git a/accessible/base/FocusManager.h b/accessible/base/FocusManager.h index 1cee713c22d1..6638cafc78e4 100644 --- a/accessible/base/FocusManager.h +++ b/accessible/base/FocusManager.h @@ -16,7 +16,6 @@ namespace a11y { class AccEvent; class Accessible; -class ProxyAccessible; class DocAccessible; /** @@ -30,18 +29,13 @@ public: /** * Return a focused accessible. */ - Accessible* FocusedAccessible() const { return mFocusedAcc; } - - /** - * Return remote focused accessible. - */ - ProxyAccessible* FocusedRemoteAccessible() const { return mFocusedProxy; } + Accessible* FocusedAccessible() const; /** * Return true if given accessible is focused. */ - bool IsFocused(const Accessible* aAccessible) const - { return aAccessible == mFocusedAcc; } + bool IsFocused(const Accessible* aAccessible) const; + /** * Return true if the given accessible is an active item, i.e. an item that * is current within the active widget. @@ -91,11 +85,6 @@ public: */ void ActiveItemChanged(Accessible* aItem, bool aCheckIfActive = true); - /** - * Called when focused item in child process is changed. - */ - void RemoteFocusChanged(ProxyAccessible* aProxy) { mFocusedProxy = aProxy; } - /** * Dispatch delayed focus event for the current focus accessible. */ @@ -135,8 +124,6 @@ private: nsIDocument* FocusedDOMDocument() const; private: - RefPtr mFocusedAcc; - ProxyAccessible* mFocusedProxy; RefPtr mActiveItem; RefPtr mActiveARIAMenubar; }; diff --git a/accessible/ipc/DocAccessibleChild.cpp b/accessible/ipc/DocAccessibleChild.cpp index 686af0143b00..3d203501fbb8 100644 --- a/accessible/ipc/DocAccessibleChild.cpp +++ b/accessible/ipc/DocAccessibleChild.cpp @@ -1888,6 +1888,24 @@ DocAccessibleChild::RecvEmbeddedChildAt(const uint64_t& aID, return true; } +bool +DocAccessibleChild::RecvFocusedChild(const uint64_t& aID, + uint64_t* aChild, + bool* aOk) +{ + *aChild = 0; + *aOk = false; + Accessible* acc = IdToAccessible(aID); + if (acc) { + Accessible* child = acc->FocusedChild(); + if (child) { + *aChild = reinterpret_cast(child->UniqueID()); + *aOk = true; + } + } + return true; +} + bool DocAccessibleChild::RecvLanguage(const uint64_t& aID, nsString* aLocale) diff --git a/accessible/ipc/DocAccessibleChild.h b/accessible/ipc/DocAccessibleChild.h index 0a260ca6786f..8d5336ae5d7e 100644 --- a/accessible/ipc/DocAccessibleChild.h +++ b/accessible/ipc/DocAccessibleChild.h @@ -464,6 +464,10 @@ public: virtual bool RecvEmbeddedChildAt(const uint64_t& aID, const uint32_t& aIdx, uint64_t* aChildID) override final; + virtual bool RecvFocusedChild(const uint64_t& aID, + uint64_t* aChild, + bool* aOk) override; + virtual bool RecvLanguage(const uint64_t& aID, nsString* aLocale) override; virtual bool RecvDocType(const uint64_t& aID, nsString* aType) override; virtual bool RecvTitle(const uint64_t& aID, nsString* aTitle) override; diff --git a/accessible/ipc/DocAccessibleParent.cpp b/accessible/ipc/DocAccessibleParent.cpp index 0fac4fa9b90e..1e581fd0908c 100644 --- a/accessible/ipc/DocAccessibleParent.cpp +++ b/accessible/ipc/DocAccessibleParent.cpp @@ -147,14 +147,6 @@ DocAccessibleParent::RecvEvent(const uint64_t& aID, const uint32_t& aEventType) return true; } - switch(aEventType) { - case nsIAccessibleEvent::EVENT_FOCUS: - FocusMgr()->RemoteFocusChanged(proxy); - break; - default: - break; - } - ProxyEvent(proxy, aEventType); if (!nsCoreUtils::AccEventObserversExist()) { diff --git a/accessible/ipc/PDocAccessible.ipdl b/accessible/ipc/PDocAccessible.ipdl index b1813a70494c..9d4930da7e40 100644 --- a/accessible/ipc/PDocAccessible.ipdl +++ b/accessible/ipc/PDocAccessible.ipdl @@ -242,6 +242,8 @@ child: returns(uint32_t childIdx); prio(high) sync EmbeddedChildAt(uint64_t aID, uint32_t aChildIdx) returns(uint64_t aChild); + prio(high) sync FocusedChild(uint64_t aID) + returns(uint64_t aChild, bool aOk); prio(high) sync Language(uint64_t aID) returns(nsString aLocale); prio(high) sync DocType(uint64_t aID) returns(nsString aType); diff --git a/accessible/ipc/ProxyAccessible.cpp b/accessible/ipc/ProxyAccessible.cpp index 38795a54ea1c..3e4a1fceb048 100644 --- a/accessible/ipc/ProxyAccessible.cpp +++ b/accessible/ipc/ProxyAccessible.cpp @@ -1068,16 +1068,10 @@ ProxyAccessible::EmbeddedChildAt(size_t aChildIdx) ProxyAccessible* ProxyAccessible::FocusedChild() { - ProxyAccessible* focus = FocusMgr()->FocusedRemoteAccessible(); - if (IsDoc()) { - return focus; - } - - if (focus && (focus == this || focus->Parent() == this)) { - return focus; - } - - return nullptr; + uint64_t childID = 0; + bool ok = false; + Unused << mDoc->SendFocusedChild(mID, &childID, &ok); + return ok ? mDoc->GetAccessible(childID) : nullptr; } ProxyAccessible*