mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
about:startup - merge with trunk
This commit is contained in:
commit
362fafd9da
16
Makefile.in
16
Makefile.in
@ -68,6 +68,10 @@ ifndef LIBXUL_SDK
|
||||
tier_base_dirs += \
|
||||
memory \
|
||||
$(NULL)
|
||||
ifeq ($(OS_TARGET),Android)
|
||||
tier_base_dirs += other-licenses/android
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifdef COMPILE_ENVIRONMENT
|
||||
@ -120,9 +124,6 @@ export::
|
||||
ifdef ENABLE_TESTS
|
||||
# Additional makefile targets to call automated test suites
|
||||
include $(topsrcdir)/testing/testsuite-targets.mk
|
||||
else
|
||||
# OS X Universal builds will want to call this, so stub it out
|
||||
package-tests:
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
@ -171,7 +172,7 @@ EXTRA_BUILDID := -$(MOZ_SYMBOLS_EXTRA_BUILDID)
|
||||
endif
|
||||
|
||||
SYMBOL_INDEX_NAME = \
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_ARCH)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
|
||||
$(MOZ_APP_NAME)-$(MOZ_APP_VERSION)-$(OS_TARGET)-$(BUILDID)$(EXTRA_BUILDID)-symbols.txt
|
||||
|
||||
buildsymbols:
|
||||
ifdef MOZ_CRASHREPORTER
|
||||
@ -231,3 +232,10 @@ maybe_clobber_profiledbuild:
|
||||
endif
|
||||
|
||||
.PHONY: maybe_clobber_profiledbuild
|
||||
|
||||
# Look for R_386_PC32 relocations in shared libs, these
|
||||
# break x86_64 builds and SELinux users.
|
||||
ifeq ($(OS_TARGET)_$(TARGET_XPCOM_ABI),Linux_x86-gcc3)
|
||||
scheck::
|
||||
@relcount=`find $(DIST)/bin -name "*.so" | xargs objdump -R | grep R_386_PC32 | wc -l` && if test $$relcount -gt 0; then echo "FAILED: R_386_PC32 relocations detected in a shared library. Did you use a system header without adding it to config/system-headers?"; exit 1; else echo "PASSED"; fi
|
||||
endif
|
||||
|
@ -91,6 +91,7 @@ ifeq ($(OS_ARCH),WINNT)
|
||||
OS_LIBS += \
|
||||
oleaut32.lib \
|
||||
version.lib \
|
||||
ole32.lib \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
@ -109,8 +109,7 @@ public:
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell,
|
||||
const nsAString& aBulletText) = 0;
|
||||
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell) = 0;
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
@ -141,27 +140,19 @@ public:
|
||||
virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible) = 0;
|
||||
|
||||
/**
|
||||
* Used to describe sort of changes leading to accessible tree invalidation.
|
||||
* Notification used to update the accessible tree when new content is
|
||||
* inserted.
|
||||
*/
|
||||
enum {
|
||||
NODE_APPEND = 0x01,
|
||||
NODE_REMOVE = 0x02,
|
||||
NODE_SIGNIFICANT_CHANGE = 0x03,
|
||||
FRAME_SHOW = 0x04,
|
||||
FRAME_HIDE = 0x05,
|
||||
FRAME_SIGNIFICANT_CHANGE = 0x06
|
||||
};
|
||||
virtual void ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild) = 0;
|
||||
|
||||
/**
|
||||
* Invalidate the accessible tree when DOM tree or frame tree is changed.
|
||||
*
|
||||
* @param aPresShell [in] the presShell where changes occurred
|
||||
* @param aContent [in] the affected DOM content
|
||||
* @param aChangeType [in] the change type (see constants declared above)
|
||||
* Notification used to update the accessible tree when content is removed.
|
||||
*/
|
||||
virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
|
||||
nsIContent *aContent,
|
||||
PRUint32 aChangeType) = 0;
|
||||
virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
|
||||
nsIContent* aChild) = 0;
|
||||
|
||||
/**
|
||||
* Notify accessibility that anchor jump has been accomplished to the given
|
||||
@ -175,6 +166,12 @@ public:
|
||||
*/
|
||||
virtual void PresShellDestroyed(nsIPresShell *aPresShell) = 0;
|
||||
|
||||
/**
|
||||
* Recreate an accessible for the given content node in the presshell.
|
||||
*/
|
||||
virtual void RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent) = 0;
|
||||
|
||||
/**
|
||||
* Fire accessible event of the given type for the given target.
|
||||
*
|
||||
|
@ -75,5 +75,7 @@ endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
GARBAGE += $(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) $(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX).fake
|
||||
|
||||
libs::
|
||||
$(INSTALL) $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX) $(wildcard $(PLATFORM_DIR)/$(LIB_PREFIX)accessibility_toolkit_s.$(LIB_SUFFIX).fake) .
|
||||
|
@ -64,19 +64,15 @@
|
||||
// AccEvent constructors
|
||||
|
||||
AccEvent::AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
|
||||
PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
|
||||
EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
|
||||
mAccessible(aAccessible)
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mAccessible(aAccessible)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
|
||||
AccEvent::AccEvent(PRUint32 aEventType, nsINode* aNode,
|
||||
PRBool aIsAsync, EIsFromUserInput aIsFromUserInput,
|
||||
EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mIsAsync(aIsAsync),
|
||||
mNode(aNode)
|
||||
EIsFromUserInput aIsFromUserInput, EEventRule aEventRule) :
|
||||
mEventType(aEventType), mEventRule(aEventRule), mNode(aNode)
|
||||
{
|
||||
CaptureIsFromUserInput(aIsFromUserInput);
|
||||
}
|
||||
@ -217,36 +213,6 @@ AccEvent::CaptureIsFromUserInput(EIsFromUserInput aIsFromUserInput)
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccReorderEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccReorderEvent::
|
||||
AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional, nsINode* aReasonNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_REORDER, aAccTarget,
|
||||
aIsAsynch, eAutoDetect, AccEvent::eCoalesceFromSameSubtree),
|
||||
mUnconditionalEvent(aIsUnconditional), mReasonNode(aReasonNode)
|
||||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
AccReorderEvent::IsUnconditionalEvent()
|
||||
{
|
||||
return mUnconditionalEvent;
|
||||
}
|
||||
|
||||
PRBool
|
||||
AccReorderEvent::HasAccessibleInReasonSubtree()
|
||||
{
|
||||
if (!mReasonNode)
|
||||
return PR_FALSE;
|
||||
|
||||
nsAccessible *accessible = GetAccService()->GetAccessible(mReasonNode);
|
||||
return accessible || nsAccUtils::HasAccessibleChildren(mReasonNode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccStateChangeEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -257,9 +223,8 @@ AccReorderEvent::HasAccessibleInReasonSubtree()
|
||||
AccStateChangeEvent::
|
||||
AccStateChangeEvent(nsAccessible* aAccessible,
|
||||
PRUint32 aState, PRBool aIsExtraState,
|
||||
PRBool aIsEnabled, PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible, aIsAsynch,
|
||||
PRBool aIsEnabled, EIsFromUserInput aIsFromUserInput):
|
||||
AccEvent(nsIAccessibleEvent::EVENT_STATE_CHANGE, aAccessible,
|
||||
aIsFromUserInput, eAllowDupes),
|
||||
mState(aState), mIsExtraState(aIsExtraState), mIsEnabled(aIsEnabled)
|
||||
{
|
||||
@ -315,11 +280,11 @@ AccStateChangeEvent::CreateXPCOMObject()
|
||||
AccTextChangeEvent::
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
: AccEvent(aIsInserted ?
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) :
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_REMOVED),
|
||||
aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes)
|
||||
aAccessible, aIsFromUserInput, eAllowDupes)
|
||||
, mStart(aStart)
|
||||
, mIsInserted(aIsInserted)
|
||||
, mModifiedText(aModifiedText)
|
||||
@ -335,37 +300,62 @@ AccTextChangeEvent::CreateXPCOMObject()
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccMutationEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccMutationEvent::
|
||||
AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
|
||||
nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput) :
|
||||
AccEvent(aEventType, aTarget, aIsFromUserInput, eCoalesceFromSameSubtree)
|
||||
{
|
||||
mNode = aTargetNode;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccHideEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccHideEvent::
|
||||
AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) :
|
||||
AccEvent(nsIAccessibleEvent::EVENT_HIDE, aTarget, aIsAsynch,
|
||||
aIsFromUserInput, eCoalesceFromSameSubtree)
|
||||
EIsFromUserInput aIsFromUserInput) :
|
||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_HIDE, aTarget, aTargetNode,
|
||||
aIsFromUserInput)
|
||||
{
|
||||
mNode = aTargetNode;
|
||||
mParent = mAccessible->GetCachedParent();
|
||||
mNextSibling = mAccessible->GetCachedNextSibling();
|
||||
mPrevSibling = mAccessible->GetCachedPrevSibling();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccShowEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccShowEvent::
|
||||
AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
EIsFromUserInput aIsFromUserInput) :
|
||||
AccMutationEvent(::nsIAccessibleEvent::EVENT_SHOW, aTarget, aTargetNode,
|
||||
aIsFromUserInput)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// AccCaretMoveEvent
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsAccessible* aAccessible, PRInt32 aCaretOffset) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible, PR_TRUE), // Currently always asynch
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aAccessible),
|
||||
mCaretOffset(aCaretOffset)
|
||||
{
|
||||
}
|
||||
|
||||
AccCaretMoveEvent::
|
||||
AccCaretMoveEvent(nsINode* aNode) :
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode, PR_TRUE), // Currently always asynch
|
||||
AccEvent(::nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED, aNode),
|
||||
mCaretOffset(-1)
|
||||
{
|
||||
}
|
||||
@ -385,9 +375,8 @@ AccCaretMoveEvent::CreateXPCOMObject()
|
||||
|
||||
AccTableChangeEvent::
|
||||
AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
|
||||
PRBool aIsAsynch) :
|
||||
AccEvent(aEventType, aAccessible, aIsAsynch),
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols) :
|
||||
AccEvent(aEventType, aAccessible),
|
||||
mRowOrColIndex(aRowOrColIndex), mNumRowsOrCols(aNumRowsOrCols)
|
||||
{
|
||||
}
|
||||
|
@ -41,6 +41,8 @@
|
||||
#ifndef _AccEvent_H_
|
||||
#define _AccEvent_H_
|
||||
|
||||
#include "nsIAccessibleEvent.h"
|
||||
|
||||
#include "nsAccessible.h"
|
||||
|
||||
class nsAccEvent;
|
||||
@ -90,11 +92,10 @@ public:
|
||||
|
||||
// Initialize with an nsIAccessible
|
||||
AccEvent(PRUint32 aEventType, nsAccessible* aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
// Initialize with an nsIDOMNode
|
||||
AccEvent(PRUint32 aEventType, nsINode* aNode, PRBool aIsAsynch = PR_FALSE,
|
||||
AccEvent(PRUint32 aEventType, nsINode* aNode,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect,
|
||||
EEventRule aEventRule = eRemoveDupes);
|
||||
virtual ~AccEvent() {}
|
||||
@ -102,7 +103,6 @@ public:
|
||||
// AccEvent
|
||||
PRUint32 GetEventType() const { return mEventType; }
|
||||
EEventRule GetEventRule() const { return mEventRule; }
|
||||
PRBool IsAsync() const { return mIsAsync; }
|
||||
PRBool IsFromUserInput() const { return mIsFromUserInput; }
|
||||
|
||||
nsAccessible *GetAccessible();
|
||||
@ -119,10 +119,11 @@ public:
|
||||
*/
|
||||
enum EventGroup {
|
||||
eGenericEvent,
|
||||
eReorderEvent,
|
||||
eStateChangeEvent,
|
||||
eTextChangeEvent,
|
||||
eMutationEvent,
|
||||
eHideEvent,
|
||||
eShowEvent,
|
||||
eCaretMoveEvent,
|
||||
eTableChangeEvent
|
||||
};
|
||||
@ -154,7 +155,6 @@ protected:
|
||||
PRBool mIsFromUserInput;
|
||||
PRUint32 mEventType;
|
||||
EEventRule mEventRule;
|
||||
PRPackedBool mIsAsync;
|
||||
nsRefPtr<nsAccessible> mAccessible;
|
||||
nsCOMPtr<nsINode> mNode;
|
||||
|
||||
@ -162,39 +162,6 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible reorder event.
|
||||
*/
|
||||
class AccReorderEvent : public AccEvent
|
||||
{
|
||||
public:
|
||||
AccReorderEvent(nsAccessible* aAccTarget, PRBool aIsAsynch,
|
||||
PRBool aIsUnconditional, nsINode* aReasonNode);
|
||||
|
||||
// AccEvent
|
||||
static const EventGroup kEventGroup = eReorderEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eReorderEvent);
|
||||
}
|
||||
|
||||
// AccReorderEvent
|
||||
/**
|
||||
* Return true if event is unconditional, i.e. must be fired.
|
||||
*/
|
||||
PRBool IsUnconditionalEvent();
|
||||
|
||||
/**
|
||||
* Return true if changed DOM node has accessible in its tree.
|
||||
*/
|
||||
PRBool HasAccessibleInReasonSubtree();
|
||||
|
||||
private:
|
||||
PRBool mUnconditionalEvent;
|
||||
nsCOMPtr<nsINode> mReasonNode;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible state change event.
|
||||
*/
|
||||
@ -203,7 +170,7 @@ class AccStateChangeEvent: public AccEvent
|
||||
public:
|
||||
AccStateChangeEvent(nsAccessible* aAccessible,
|
||||
PRUint32 aState, PRBool aIsExtraState,
|
||||
PRBool aIsEnabled, PRBool aIsAsynch = PR_FALSE,
|
||||
PRBool aIsEnabled,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
AccStateChangeEvent(nsINode* aNode, PRUint32 aState, PRBool aIsExtraState,
|
||||
@ -239,8 +206,7 @@ class AccTextChangeEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccTextChangeEvent(nsAccessible* aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText,
|
||||
PRBool aIsInserted, PRBool aIsAsynch = PR_FALSE,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
// AccEvent
|
||||
@ -269,31 +235,75 @@ private:
|
||||
|
||||
|
||||
/**
|
||||
* Accessible hide events.
|
||||
* Base class for show and hide accessible events.
|
||||
*/
|
||||
class AccHideEvent : public AccEvent
|
||||
class AccMutationEvent: public AccEvent
|
||||
{
|
||||
public:
|
||||
AccMutationEvent(PRUint32 aEventType, nsAccessible* aTarget,
|
||||
nsINode* aTargetNode, EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eMutationEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eMutationEvent);
|
||||
}
|
||||
|
||||
// MutationEvent
|
||||
bool IsShow() const { return mEventType == nsIAccessibleEvent::EVENT_SHOW; }
|
||||
bool IsHide() const { return mEventType == nsIAccessibleEvent::EVENT_HIDE; }
|
||||
|
||||
protected:
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
friend class nsAccEventQueue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible hide event.
|
||||
*/
|
||||
class AccHideEvent: public AccMutationEvent
|
||||
{
|
||||
public:
|
||||
AccHideEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput);
|
||||
EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eHideEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccEvent::GetEventGroups() | (1U << eHideEvent);
|
||||
return AccMutationEvent::GetEventGroups() | (1U << eHideEvent);
|
||||
}
|
||||
|
||||
protected:
|
||||
nsRefPtr<nsAccessible> mParent;
|
||||
nsRefPtr<nsAccessible> mNextSibling;
|
||||
nsRefPtr<nsAccessible> mPrevSibling;
|
||||
nsRefPtr<AccTextChangeEvent> mTextChangeEvent;
|
||||
|
||||
friend class nsAccEventQueue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible show event.
|
||||
*/
|
||||
class AccShowEvent: public AccMutationEvent
|
||||
{
|
||||
public:
|
||||
AccShowEvent(nsAccessible* aTarget, nsINode* aTargetNode,
|
||||
EIsFromUserInput aIsFromUserInput);
|
||||
|
||||
// Event
|
||||
static const EventGroup kEventGroup = eShowEvent;
|
||||
virtual unsigned int GetEventGroups() const
|
||||
{
|
||||
return AccMutationEvent::GetEventGroups() | (1U << eShowEvent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Accessible caret move event.
|
||||
*/
|
||||
@ -327,8 +337,7 @@ class AccTableChangeEvent : public AccEvent
|
||||
{
|
||||
public:
|
||||
AccTableChangeEvent(nsAccessible* aAccessible, PRUint32 aEventType,
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols,
|
||||
PRBool aIsAsynch);
|
||||
PRInt32 aRowOrColIndex, PRInt32 aNumRowsOrCols);
|
||||
|
||||
// AccEvent
|
||||
virtual already_AddRefed<nsAccEvent> CreateXPCOMObject();
|
||||
|
@ -72,8 +72,7 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
||||
// Ensure CacheChildren is called before we query cache.
|
||||
nsAccessNode::GetApplicationAccessible()->EnsureChildren();
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (docAcc)
|
||||
return docAcc;
|
||||
|
||||
@ -81,10 +80,10 @@ nsAccDocManager::GetDocAccessible(nsIDocument *aDocument)
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccDocManager::FindAccessibleInCache(void *aUniqueID) const
|
||||
nsAccDocManager::FindAccessibleInCache(nsINode* aNode) const
|
||||
{
|
||||
nsSearchAccessibleInCacheArg arg;
|
||||
arg.mUniqueID = aUniqueID;
|
||||
arg.mNode = aNode;
|
||||
|
||||
mDocAccessibleCache.EnumerateRead(SearchAccessibleInDocCache,
|
||||
static_cast<void*>(&arg));
|
||||
@ -136,8 +135,7 @@ nsAccDocManager::Shutdown()
|
||||
void
|
||||
nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
|
||||
{
|
||||
nsDocAccessible* docAccessible =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
nsDocAccessible* docAccessible = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (!docAccessible)
|
||||
return;
|
||||
|
||||
@ -146,7 +144,7 @@ nsAccDocManager::ShutdownDocAccessible(nsIDocument *aDocument)
|
||||
// are removed automatically when chrome event target goes away.
|
||||
|
||||
docAccessible->Shutdown();
|
||||
mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -215,8 +213,7 @@ nsAccDocManager::OnStateChange(nsIWebProgress *aWebProgress,
|
||||
if (!IsEventTargetDocument(document))
|
||||
return NS_OK;
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(document));
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(document);
|
||||
if (!docAcc)
|
||||
return NS_OK;
|
||||
|
||||
@ -346,9 +343,7 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
||||
{
|
||||
// Document accessible can be created before we were notified the DOM document
|
||||
// was loaded completely. However if it's not created yet then create it.
|
||||
nsDocAccessible *docAcc =
|
||||
mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
|
||||
nsDocAccessible* docAcc = mDocAccessibleCache.GetWeak(aDocument);
|
||||
if (!docAcc) {
|
||||
docAcc = CreateDocOrRootAccessible(aDocument);
|
||||
NS_ASSERTION(docAcc, "Can't create document accessible!");
|
||||
@ -365,16 +360,8 @@ nsAccDocManager::HandleDOMDocumentLoad(nsIDocument *aDocument,
|
||||
// documents
|
||||
// b) document load event on sub documents causes screen readers to act is if
|
||||
// entire page is reloaded.
|
||||
if (!IsEventTargetDocument(aDocument)) {
|
||||
// XXX: AT doesn't update their virtual buffer once frame is loaded and it
|
||||
// has dynamic content added after frame load. There's something wrong how
|
||||
// we handle this changes.
|
||||
if (!nsCoreUtils::IsRootDocument(aDocument)) {
|
||||
docAcc->InvalidateCacheSubtree(nsnull,
|
||||
nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE);
|
||||
}
|
||||
if (!IsEventTargetDocument(aDocument))
|
||||
return;
|
||||
}
|
||||
|
||||
// Fire complete/load stopped if the load event type is given.
|
||||
if (aLoadEventType) {
|
||||
@ -437,9 +424,10 @@ nsAccDocManager::AddListeners(nsIDocument *aDocument,
|
||||
nsDocAccessible*
|
||||
nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
{
|
||||
// Ignore temporary, hiding and svg resource documents.
|
||||
// Ignore temporary, hiding, resource documents and documents without
|
||||
// docshell.
|
||||
if (aDocument->IsInitialDocument() || !aDocument->IsVisible() ||
|
||||
aDocument->GetDisplayDocument())
|
||||
aDocument->IsResourceDoc() || !aDocument->IsActive())
|
||||
return nsnull;
|
||||
|
||||
// Ignore documents without presshell.
|
||||
@ -492,7 +480,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
return nsnull;
|
||||
|
||||
// Cache and addref document accessible.
|
||||
if (!mDocAccessibleCache.Put(static_cast<void*>(aDocument), docAcc)) {
|
||||
if (!mDocAccessibleCache.Put(aDocument, docAcc)) {
|
||||
delete docAcc;
|
||||
return nsnull;
|
||||
}
|
||||
@ -502,7 +490,7 @@ nsAccDocManager::CreateDocOrRootAccessible(nsIDocument *aDocument)
|
||||
// while initialized.
|
||||
if (!outerDocAcc->AppendChild(docAcc) ||
|
||||
!GetAccService()->InitAccessible(docAcc, nsAccUtils::GetRoleMapEntry(aDocument))) {
|
||||
mDocAccessibleCache.Remove(static_cast<void*>(aDocument));
|
||||
mDocAccessibleCache.Remove(aDocument);
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
@ -545,7 +533,7 @@ nsAccDocManager::ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
|
||||
// nsAccDocManager static
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::ClearDocCacheEntry(const void* aKey,
|
||||
nsAccDocManager::ClearDocCacheEntry(const nsIDocument* aKey,
|
||||
nsRefPtr<nsDocAccessible>& aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
@ -559,7 +547,7 @@ nsAccDocManager::ClearDocCacheEntry(const void* aKey,
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsAccDocManager::SearchAccessibleInDocCache(const void* aKey,
|
||||
nsAccDocManager::SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
nsDocAccessible* aDocAccessible,
|
||||
void* aUserArg)
|
||||
{
|
||||
@ -569,7 +557,7 @@ nsAccDocManager::SearchAccessibleInDocCache(const void* aKey,
|
||||
if (aDocAccessible) {
|
||||
nsSearchAccessibleInCacheArg* arg =
|
||||
static_cast<nsSearchAccessibleInCacheArg*>(aUserArg);
|
||||
arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mUniqueID);
|
||||
arg->mAccessible = aDocAccessible->GetCachedAccessible(arg->mNode);
|
||||
if (arg->mAccessible)
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public:
|
||||
* Search through all document accessibles for an accessible with the given
|
||||
* unique id.
|
||||
*/
|
||||
nsAccessible *FindAccessibleInCache(void *aUniqueID) const;
|
||||
nsAccessible* FindAccessibleInCache(nsINode* aNode) const;
|
||||
|
||||
/**
|
||||
* Shutdown document accessibles in the tree starting from the given one.
|
||||
@ -87,7 +87,7 @@ public:
|
||||
*/
|
||||
inline nsDocAccessible* GetDocAccessibleFromCache(nsIDocument* aDocument) const
|
||||
{
|
||||
return mDocAccessibleCache.GetWeak(static_cast<void*>(aDocument));
|
||||
return mDocAccessibleCache.GetWeak(aDocument);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -162,14 +162,14 @@ private:
|
||||
void ShutdownDocAccessiblesInTree(nsIDocShellTreeItem *aTreeItem,
|
||||
nsIDocument *aDocument);
|
||||
|
||||
typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible>
|
||||
typedef nsRefPtrHashtable<nsPtrHashKey<const nsIDocument>, nsDocAccessible>
|
||||
nsDocAccessibleHashtable;
|
||||
|
||||
/**
|
||||
* Shutdown and remove the document accessible from cache.
|
||||
*/
|
||||
static PLDHashOperator
|
||||
ClearDocCacheEntry(const void* aKey,
|
||||
ClearDocCacheEntry(const nsIDocument* aKey,
|
||||
nsRefPtr<nsDocAccessible>& aDocAccessible,
|
||||
void* aUserArg);
|
||||
|
||||
@ -184,11 +184,11 @@ private:
|
||||
struct nsSearchAccessibleInCacheArg
|
||||
{
|
||||
nsAccessible *mAccessible;
|
||||
void *mUniqueID;
|
||||
nsINode* mNode;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
SearchAccessibleInDocCache(const void* aKey,
|
||||
SearchAccessibleInDocCache(const nsIDocument* aKey,
|
||||
nsDocAccessible* aDocAccessible,
|
||||
void* aUserArg);
|
||||
|
||||
|
@ -74,9 +74,11 @@ nsAccTreeWalker::
|
||||
if (aContent)
|
||||
mState = new WalkState(aContent);
|
||||
|
||||
mChildType = aWalkAnonContent ? nsIContent::eAllChildren :
|
||||
mChildFilter = aWalkAnonContent ? nsIContent::eAllChildren :
|
||||
nsIContent::eAllButXBL;
|
||||
|
||||
mChildFilter |= nsIContent::eSkipPlaceholderContent;
|
||||
|
||||
MOZ_COUNT_CTOR(nsAccTreeWalker);
|
||||
}
|
||||
|
||||
@ -99,7 +101,7 @@ nsAccTreeWalker::GetNextChildInternal(PRBool aNoWalkUp)
|
||||
return nsnull;
|
||||
|
||||
if (!mState->childList)
|
||||
mState->childList = mState->content->GetChildren(mChildType);
|
||||
mState->childList = mState->content->GetChildren(mChildFilter);
|
||||
|
||||
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
|
||||
|
||||
|
@ -91,7 +91,7 @@ private:
|
||||
void PopState();
|
||||
|
||||
nsCOMPtr<nsIWeakReference> mWeakShell;
|
||||
PRInt32 mChildType;
|
||||
PRInt32 mChildFilter;
|
||||
WalkState* mState;
|
||||
};
|
||||
|
||||
|
@ -152,9 +152,12 @@ nsAccessNode::Shutdown()
|
||||
}
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHODIMP nsAccessNode::GetUniqueID(void **aUniqueID)
|
||||
NS_IMETHODIMP
|
||||
nsAccessNode::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
*aUniqueID = static_cast<void*>(GetNode());
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
|
||||
*aUniqueID = UniqueID();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -310,6 +313,12 @@ nsAccessNode::GetFrame()
|
||||
return mContent ? mContent->GetPrimaryFrame() : nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAccessNode::IsPrimaryForNode() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessNode
|
||||
|
||||
|
@ -181,6 +181,20 @@ public:
|
||||
*/
|
||||
nsIWeakReference* GetWeakShell() const { return mWeakShell; }
|
||||
|
||||
/**
|
||||
* Return the unique identifier of the accessible.
|
||||
*/
|
||||
void* UniqueID() { return static_cast<void*>(this); }
|
||||
|
||||
/**
|
||||
* Return true if the accessible is primary accessible for the given DOM node.
|
||||
*
|
||||
* Accessible hierarchy may be complex for single DOM node, in this case
|
||||
* these accessibles share the same DOM node. The primary accessible "owns"
|
||||
* that DOM node in terms it gets stored in the accessible to node map.
|
||||
*/
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
protected:
|
||||
nsPresContext* GetPresContext();
|
||||
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "nsRootAccessibleWrap.h"
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsXULAlertAccessible.h"
|
||||
@ -232,12 +233,10 @@ nsAccessibilityService::CreateHTMLButtonAccessible(nsIContent* aContent,
|
||||
|
||||
already_AddRefed<nsAccessible>
|
||||
nsAccessibilityService::CreateHTMLLIAccessible(nsIContent* aContent,
|
||||
nsIPresShell* aPresShell,
|
||||
const nsAString& aBulletText)
|
||||
nsIPresShell* aPresShell)
|
||||
{
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(aPresShell));
|
||||
nsAccessible* accessible = new nsHTMLLIAccessible(aContent, weakShell,
|
||||
aBulletText);
|
||||
nsAccessible* accessible = new nsHTMLLIAccessible(aContent, weakShell);
|
||||
NS_IF_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
@ -472,6 +471,62 @@ nsAccessibilityService::CreateHTMLCaptionAccessible(nsIContent* aContent,
|
||||
return accessible;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
nsAutoString tag;
|
||||
aStartChild->Tag()->ToString(tag);
|
||||
nsIAtom* id = aStartChild->GetID();
|
||||
nsCAutoString strid;
|
||||
if (id)
|
||||
id->ToUTF8String(strid);
|
||||
nsAutoString ctag;
|
||||
aContainer->Tag()->ToString(ctag);
|
||||
nsIAtom* cid = aContainer->GetID();
|
||||
nsCAutoString strcid;
|
||||
if (cid)
|
||||
cid->ToUTF8String(strcid);
|
||||
printf("\ncontent inserted: %s@id='%s', container: %s@id='%s', end node: %p\n\n",
|
||||
NS_ConvertUTF16toUTF8(tag).get(), strid.get(),
|
||||
NS_ConvertUTF16toUTF8(ctag).get(), strcid.get(), aEndChild);
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, also we need to
|
||||
// update a content node of the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aStartChild, aEndChild, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild)
|
||||
{
|
||||
#ifdef DEBUG_A11Y
|
||||
nsAutoString id;
|
||||
aChild->Tag()->ToString(id);
|
||||
printf("\ncontent removed: %s\n", NS_ConvertUTF16toUTF8(id).get());
|
||||
#endif
|
||||
|
||||
// XXX: bug 606082. aContainer is null when root element is inserted into
|
||||
// document, we need to handle this and update the tree, perhaps destroy
|
||||
// the document accessible.
|
||||
if (aContainer) {
|
||||
nsDocAccessible* docAccessible = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->UpdateTree(aContainer, aChild, aChild->GetNextSibling(),
|
||||
PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
{
|
||||
@ -491,14 +546,22 @@ nsAccessibilityService::PresShellDestroyed(nsIPresShell *aPresShell)
|
||||
ShutdownDocAccessible(doc);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent)
|
||||
{
|
||||
nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
|
||||
if (document)
|
||||
document->RecreateAccessible(aContent);
|
||||
}
|
||||
|
||||
// nsAccessibilityService protected
|
||||
nsAccessible *
|
||||
nsAccessibilityService::GetCachedAccessible(nsINode *aNode,
|
||||
nsIWeakReference *aWeakShell)
|
||||
{
|
||||
nsDocAccessible *docAccessible = GetDocAccessible(aNode->GetOwnerDoc());
|
||||
return docAccessible ?
|
||||
docAccessible->GetCachedAccessible(static_cast<void*>(aNode)) : nsnull;
|
||||
return docAccessible ? docAccessible->GetCachedAccessible(aNode) : nsnull;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -696,7 +759,7 @@ nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
|
||||
// "unofficially" shutdown document (i.e. not from nsAccDocManager) can still
|
||||
// exist in the document cache.
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
nsAccessible* accessible = FindAccessibleInCache(static_cast<void*>(node));
|
||||
nsAccessible* accessible = FindAccessibleInCache(node);
|
||||
if (!accessible) {
|
||||
nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
|
||||
if (document)
|
||||
@ -734,7 +797,7 @@ nsAccessibilityService::GetAccessible(nsINode* aNode)
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode)
|
||||
nsAccessibilityService::GetCachedAccessibleOrContainer(nsINode* aNode)
|
||||
{
|
||||
if (!aNode)
|
||||
return nsnull;
|
||||
@ -751,8 +814,8 @@ nsAccessibilityService::GetCachedContainerAccessible(nsINode* aNode)
|
||||
nsCOMPtr<nsIWeakReference> weakShell(do_GetWeakReference(presShell));
|
||||
|
||||
nsAccessible *accessible = nsnull;
|
||||
while ((currNode = currNode->GetNodeParent()) &&
|
||||
!(accessible = GetCachedAccessible(currNode, weakShell)));
|
||||
while (!(accessible = GetCachedAccessible(currNode, weakShell)) &&
|
||||
(currNode = currNode->GetNodeParent()));
|
||||
|
||||
return accessible;
|
||||
}
|
||||
@ -859,8 +922,7 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
nsWeakFrame weakFrame = content->GetPrimaryFrame();
|
||||
|
||||
// Check frame to see if it is hidden.
|
||||
if (!weakFrame.GetFrame() ||
|
||||
!weakFrame.GetFrame()->GetStyleVisibility()->IsVisible()) {
|
||||
if (!weakFrame.GetFrame()) {
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
|
||||
@ -1197,23 +1259,24 @@ nsAccessibilityService::GetAccessibleByRule(nsINode* aNode,
|
||||
if (!aNode || !aWeakShell)
|
||||
return nsnull;
|
||||
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc) {
|
||||
if (aWhatToGet & eGetAccForNode)
|
||||
if (aWhatToGet & eGetAccForNode) {
|
||||
nsAccessible* cachedAcc = GetCachedAccessible(aNode, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
return cachedAcc;
|
||||
|
||||
// XXX: while nsAccessible::GetParent() tries to repair broken tree and
|
||||
// may not return cached parent then we use GetAccessibleOrContainer().
|
||||
return GetAccessibleByRule(aNode->GetNodeParent(), aWeakShell,
|
||||
eGetAccForNodeOrContainer);
|
||||
}
|
||||
|
||||
// Go up looking for the nearest accessible container stored in cache.
|
||||
// Go up looking for the nearest accessible container having cached children.
|
||||
nsTArray<nsINode*> nodes;
|
||||
|
||||
nsINode* node = aNode;
|
||||
while ((node = node->GetNodeParent()) &&
|
||||
!(cachedAcc = GetCachedAccessible(node, aWeakShell)))
|
||||
nsAccessible* cachedAcc = nsnull;
|
||||
while ((node = node->GetNodeParent())) {
|
||||
cachedAcc = GetCachedAccessible(node, aWeakShell);
|
||||
if (cachedAcc && cachedAcc->IsBoundToParent())
|
||||
break;
|
||||
|
||||
nodes.AppendElement(node);
|
||||
}
|
||||
|
||||
// Node is not in accessible document.
|
||||
if (!cachedAcc)
|
||||
@ -1634,8 +1697,7 @@ nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
|
||||
// Normally for li, it is created by the list item frame (in nsBlockFrame)
|
||||
// which knows about the bullet frame; however, in this case the list item
|
||||
// must have been styled using display: foo
|
||||
nsAccessible* accessible = new nsHTMLLIAccessible(aContent, aWeakShell,
|
||||
EmptyString());
|
||||
nsAccessible* accessible = new nsHTMLLIAccessible(aContent, aWeakShell);
|
||||
NS_IF_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
@ -1716,29 +1778,6 @@ nsAccessibilityService::RemoveNativeRootAccessible(nsAccessible* aAccessible)
|
||||
#endif
|
||||
}
|
||||
|
||||
// Called from layout when the frame tree owned by a node changes significantly
|
||||
nsresult
|
||||
nsAccessibilityService::InvalidateSubtreeFor(nsIPresShell *aShell,
|
||||
nsIContent *aChangeContent,
|
||||
PRUint32 aChangeType)
|
||||
{
|
||||
NS_ASSERTION(aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE ||
|
||||
aChangeType == nsIAccessibilityService::FRAME_SHOW ||
|
||||
aChangeType == nsIAccessibilityService::FRAME_HIDE ||
|
||||
aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE ||
|
||||
aChangeType == nsIAccessibilityService::NODE_APPEND ||
|
||||
aChangeType == nsIAccessibilityService::NODE_REMOVE,
|
||||
"Incorrect aEvent passed in");
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aShell);
|
||||
|
||||
nsDocAccessible *docAccessible = GetDocAccessible(aShell->GetDocument());
|
||||
if (docAccessible)
|
||||
docAccessible->InvalidateCacheSubtree(aChangeContent, aChangeType);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NS_GetAccessibilityService
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -84,8 +84,7 @@ public:
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLabelAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell,
|
||||
const nsAString& aBulletText);
|
||||
CreateHTMLLIAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
CreateHTMLListboxAccessible(nsIContent* aContent, nsIPresShell* aPresShell);
|
||||
virtual already_AddRefed<nsAccessible>
|
||||
@ -111,14 +110,21 @@ public:
|
||||
virtual nsAccessible* AddNativeRootAccessible(void* aAtkAccessible);
|
||||
virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible);
|
||||
|
||||
virtual nsresult InvalidateSubtreeFor(nsIPresShell *aPresShell,
|
||||
nsIContent *aContent,
|
||||
PRUint32 aChangeType);
|
||||
virtual void ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild);
|
||||
|
||||
virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
|
||||
nsIContent* aChild);
|
||||
|
||||
virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
|
||||
|
||||
virtual void PresShellDestroyed(nsIPresShell* aPresShell);
|
||||
|
||||
virtual void RecreateAccessible(nsIPresShell* aPresShell,
|
||||
nsIContent* aContent);
|
||||
|
||||
virtual void FireAccessibleEvent(PRUint32 aEvent, nsAccessible* aTarget);
|
||||
|
||||
// nsAccessibiltiyService
|
||||
@ -179,12 +185,22 @@ public:
|
||||
return GetAccessibleByRule(aNode, aWeakShell, eGetAccForContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return cached accessible for the given DOM node or cached container
|
||||
* accessible if there's no cached accessible for the given node.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleOrContainer(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Return the first cached accessible parent of a DOM node.
|
||||
*
|
||||
* @param aDOMNode [in] the DOM node to get an accessible for
|
||||
*/
|
||||
nsAccessible* GetCachedContainerAccessible(nsINode *aNode);
|
||||
inline nsAccessible* GetCachedContainerAccessible(nsINode *aNode)
|
||||
{
|
||||
return aNode ?
|
||||
GetCachedAccessibleOrContainer(aNode->GetNodeParent()) : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize an accessible and cache it. The method should be called for
|
||||
|
@ -99,6 +99,7 @@
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsAttrName.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#include "nsIDOMCharacterData.h"
|
||||
@ -685,24 +686,23 @@ nsAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
if (aExtraState)
|
||||
*aExtraState = 0;
|
||||
|
||||
// Set STATE_UNAVAILABLE state based on disabled attribute
|
||||
// The disabled attribute is mostly used in XUL elements and HTML forms, but
|
||||
// if someone sets it on another attribute,
|
||||
// it seems reasonable to consider it unavailable
|
||||
PRBool isDisabled;
|
||||
if (mContent->IsHTML()) {
|
||||
// In HTML, just the presence of the disabled attribute means it is disabled,
|
||||
// therefore disabled="false" indicates disabled!
|
||||
isDisabled = mContent->HasAttr(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::disabled);
|
||||
}
|
||||
else {
|
||||
isDisabled = mContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::disabled,
|
||||
nsAccessibilityAtoms::_true,
|
||||
eCaseMatters);
|
||||
}
|
||||
if (isDisabled) {
|
||||
nsEventStates intrinsicState = mContent->IntrinsicState();
|
||||
|
||||
if (intrinsicState.HasState(NS_EVENT_STATE_INVALID))
|
||||
*aState |= nsIAccessibleStates::STATE_INVALID;
|
||||
|
||||
if (intrinsicState.HasState(NS_EVENT_STATE_REQUIRED))
|
||||
*aState |= nsIAccessibleStates::STATE_REQUIRED;
|
||||
|
||||
PRBool disabled = mContent->IsHTML() ?
|
||||
(intrinsicState.HasState(NS_EVENT_STATE_DISABLED)) :
|
||||
(mContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::disabled,
|
||||
nsAccessibilityAtoms::_true,
|
||||
eCaseMatters));
|
||||
|
||||
// Set unavailable state based on disabled state, otherwise set focus states
|
||||
if (disabled) {
|
||||
*aState |= nsIAccessibleStates::STATE_UNAVAILABLE;
|
||||
}
|
||||
else if (mContent->IsElement()) {
|
||||
@ -985,39 +985,49 @@ void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame
|
||||
|
||||
|
||||
/* void getBounds (out long x, out long y, out long width, out long height); */
|
||||
NS_IMETHODIMP nsAccessible::GetBounds(PRInt32 *x, PRInt32 *y, PRInt32 *width, PRInt32 *height)
|
||||
NS_IMETHODIMP
|
||||
nsAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
|
||||
PRInt32* aWidth, PRInt32* aHeight)
|
||||
{
|
||||
// This routine will get the entire rectange for all the frames in this node
|
||||
NS_ENSURE_ARG_POINTER(aX);
|
||||
*aX = 0;
|
||||
NS_ENSURE_ARG_POINTER(aY);
|
||||
*aY = 0;
|
||||
NS_ENSURE_ARG_POINTER(aWidth);
|
||||
*aWidth = 0;
|
||||
NS_ENSURE_ARG_POINTER(aHeight);
|
||||
*aHeight = 0;
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Flush layout so that all the frame construction, reflow, and styles are
|
||||
// up-to-date since we rely on frames, and styles when calculating state.
|
||||
// We don't flush the display because we don't care about painting.
|
||||
nsCOMPtr<nsIPresShell> presShell = GetPresShell();
|
||||
presShell->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
// This routine will get the entire rectangle for all the frames in this node.
|
||||
// -------------------------------------------------------------------------
|
||||
// Primary Frame for node
|
||||
// Another frame, same node <- Example
|
||||
// Another frame, same node
|
||||
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
if (!presContext)
|
||||
{
|
||||
*x = *y = *width = *height = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsRect unionRectTwips;
|
||||
nsIFrame* aBoundingFrame = nsnull;
|
||||
GetBoundsRect(unionRectTwips, &aBoundingFrame); // Unions up all primary frames for this node and all siblings after it
|
||||
if (!aBoundingFrame) {
|
||||
*x = *y = *width = *height = 0;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsIFrame* boundingFrame = nsnull;
|
||||
GetBoundsRect(unionRectTwips, &boundingFrame); // Unions up all primary frames for this node and all siblings after it
|
||||
NS_ENSURE_STATE(boundingFrame);
|
||||
|
||||
*x = presContext->AppUnitsToDevPixels(unionRectTwips.x);
|
||||
*y = presContext->AppUnitsToDevPixels(unionRectTwips.y);
|
||||
*width = presContext->AppUnitsToDevPixels(unionRectTwips.width);
|
||||
*height = presContext->AppUnitsToDevPixels(unionRectTwips.height);
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
*aX = presContext->AppUnitsToDevPixels(unionRectTwips.x);
|
||||
*aY = presContext->AppUnitsToDevPixels(unionRectTwips.y);
|
||||
*aWidth = presContext->AppUnitsToDevPixels(unionRectTwips.width);
|
||||
*aHeight = presContext->AppUnitsToDevPixels(unionRectTwips.height);
|
||||
|
||||
// We have the union of the rectangle, now we need to put it in absolute screen coords
|
||||
|
||||
nsIntRect orgRectPixels = aBoundingFrame->GetScreenRectExternal();
|
||||
*x += orgRectPixels.x;
|
||||
*y += orgRectPixels.y;
|
||||
nsIntRect orgRectPixels = boundingFrame->GetScreenRectExternal();
|
||||
*aX += orgRectPixels.x;
|
||||
*aY += orgRectPixels.y;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2619,16 +2629,11 @@ nsAccessible::Init()
|
||||
if (!nsAccessNodeWrap::Init())
|
||||
return PR_FALSE;
|
||||
|
||||
nsDocAccessible *docAcc =
|
||||
nsDocAccessible* document =
|
||||
GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
|
||||
NS_ASSERTION(docAcc, "Cannot cache new nsAccessible!");
|
||||
if (!docAcc)
|
||||
return PR_FALSE;
|
||||
NS_ASSERTION(document, "Cannot cache new nsAccessible!");
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
GetUniqueID(&uniqueID);
|
||||
|
||||
return docAcc->CacheAccessible(uniqueID, this);
|
||||
return document ? document->CacheAccessible(this) : PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2637,10 +2642,8 @@ nsAccessible::Shutdown()
|
||||
// Invalidate the child count and pointers to other accessibles, also make
|
||||
// sure none of its children point to this parent
|
||||
InvalidateChildren();
|
||||
if (mParent) {
|
||||
mParent->InvalidateChildren();
|
||||
UnbindFromParent();
|
||||
}
|
||||
if (mParent)
|
||||
mParent->RemoveChild(this);
|
||||
|
||||
nsAccessNodeWrap::Shutdown();
|
||||
}
|
||||
@ -2689,14 +2692,14 @@ nsAccessible::BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent)
|
||||
{
|
||||
NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
|
||||
|
||||
if (mParent && mParent != aParent) {
|
||||
// Adopt a child -- we allow this now. the new parent
|
||||
// may be a dom node which wasn't previously accessible but now is.
|
||||
// The old parent's children now need to be invalidated, since
|
||||
// it no longer owns the child, the new parent does
|
||||
NS_ASSERTION(PR_FALSE, "Adopting child!");
|
||||
if (mParent)
|
||||
if (mParent) {
|
||||
if (mParent != aParent) {
|
||||
NS_ERROR("Adopting child!");
|
||||
mParent->InvalidateChildren();
|
||||
} else {
|
||||
NS_ERROR("Binding to the same parent!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mParent = aParent;
|
||||
@ -2732,7 +2735,7 @@ nsAccessible::AppendChild(nsAccessible* aChild)
|
||||
if (!mChildren.AppendElement(aChild))
|
||||
return PR_FALSE;
|
||||
|
||||
if (nsAccUtils::IsText(aChild))
|
||||
if (!nsAccUtils::IsEmbeddedObject(aChild))
|
||||
mChildrenFlags = eMixedChildren;
|
||||
|
||||
aChild->BindToParent(this, mChildren.Length() - 1);
|
||||
@ -2897,13 +2900,10 @@ nsAccessible::IsInCache()
|
||||
{
|
||||
nsDocAccessible *docAccessible =
|
||||
GetAccService()->GetDocAccessible(mContent->GetOwnerDoc());
|
||||
if (!docAccessible)
|
||||
return nsnull;
|
||||
if (docAccessible)
|
||||
return docAccessible->GetCachedAccessibleByUniqueID(UniqueID()) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
GetUniqueID(&uniqueID);
|
||||
|
||||
return docAccessible->GetCachedAccessible(uniqueID) ? PR_TRUE : PR_FALSE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "nsStringGlue.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
class AccGroupInfo;
|
||||
class EmbeddedObjCollector;
|
||||
@ -66,6 +67,8 @@ class nsIView;
|
||||
|
||||
typedef nsRefPtrHashtable<nsVoidPtrHashKey, nsAccessible>
|
||||
nsAccessibleHashtable;
|
||||
typedef nsDataHashtable<nsPtrHashKey<const nsINode>, nsAccessible*>
|
||||
NodeToAccessibleMap;
|
||||
|
||||
// see nsAccessible::GetAttrValue
|
||||
#define NS_OK_NO_ARIA_VALUE \
|
||||
@ -206,6 +209,7 @@ public:
|
||||
* nsnull if none.
|
||||
*/
|
||||
virtual void SetRoleMapEntry(nsRoleMapEntry *aRoleMapEntry);
|
||||
const nsRoleMapEntry* GetRoleMapEntry() const { return mRoleMapEntry; }
|
||||
|
||||
/**
|
||||
* Cache children if necessary. Return true if the accessible is defunct.
|
||||
@ -290,7 +294,9 @@ public:
|
||||
mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull;
|
||||
}
|
||||
PRUint32 GetCachedChildCount() const { return mChildren.Length(); }
|
||||
nsAccessible* GetCachedChildAt(PRUint32 aIndex) const { return mChildren.ElementAt(aIndex); }
|
||||
PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; }
|
||||
bool IsBoundToParent() const { return mParent; }
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
|
@ -363,6 +363,12 @@ nsApplicationAccessible::Shutdown()
|
||||
mAppInfo = nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsApplicationAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible public methods
|
||||
|
||||
@ -470,7 +476,7 @@ nsApplicationAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsIAccessNode
|
||||
// nsIAccessNode and nsAccessNode
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
|
||||
@ -524,14 +530,6 @@ nsApplicationAccessible::GetOwnerWindow(void **aOwnerWindow)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
*aUniqueID = static_cast<void *>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt,
|
||||
const nsAString &aPropertyName,
|
||||
@ -556,3 +554,4 @@ nsApplicationAccessible::GetLanguage(nsAString &aLanguage)
|
||||
aLanguage.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,20 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_DECL_NSIACCESSNODE
|
||||
NS_SCRIPTABLE NS_IMETHOD GetDOMNode(nsIDOMNode** aDOMNode);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
|
||||
NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType);
|
||||
NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY);
|
||||
NS_IMETHOD GetOwnerWindow(void **aOwnerWindow);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt,
|
||||
const nsAString& aPropertyName,
|
||||
nsAString& aValue NS_OUTPARAM);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetComputedStyleCSSValue(const nsAString& aPseudoElt,
|
||||
const nsAString& aPropertyName,
|
||||
nsIDOMCSSPrimitiveValue** aValue NS_OUTPARAM);
|
||||
NS_SCRIPTABLE NS_IMETHOD GetLanguage(nsAString& aLanguage);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetParent(nsIAccessible **aParent);
|
||||
@ -109,6 +122,7 @@ public:
|
||||
virtual PRBool IsDefunct();
|
||||
virtual PRBool Init();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetARIAState(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
@ -285,8 +285,7 @@ nsCaretAccessible::SpellcheckSelectionChanged(nsIDOMDocument *aDoc,
|
||||
NS_ENSURE_STATE(textAcc);
|
||||
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED,
|
||||
textAcc, nsnull);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_TEXT_ATTRIBUTE_CHANGED, textAcc);
|
||||
|
||||
nsEventShell::FireEvent(event);
|
||||
return NS_OK;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -170,12 +170,9 @@ public:
|
||||
* @param aEventType [in] the nsIAccessibleEvent event type
|
||||
* @param aDOMNode [in] DOM node the accesible event should be fired for
|
||||
* @param aAllowDupes [in] rule to process an event (see EEventRule constants)
|
||||
* @param aIsAsynch [in] set to PR_TRUE if this is not being called from
|
||||
* code synchronous with a DOM event
|
||||
*/
|
||||
nsresult FireDelayedAccessibleEvent(PRUint32 aEventType, nsINode *aNode,
|
||||
AccEvent::EEventRule aAllowDupes = AccEvent::eRemoveDupes,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
@ -186,51 +183,45 @@ public:
|
||||
nsresult FireDelayedAccessibleEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Find the accessible object in the accessibility cache that corresponds to
|
||||
* the given node or the first ancestor of it that has an accessible object
|
||||
* associated with it. Clear that accessible object's parent's cache of
|
||||
* accessible children and remove the accessible object and any descendants
|
||||
* from the accessible cache. Fires proper events. New accessible objects will
|
||||
* be created and cached again on demand.
|
||||
*
|
||||
* @param aContent [in] the child that is changing
|
||||
* @param aEvent [in] the event from nsIAccessibleEvent that caused
|
||||
* the change.
|
||||
*/
|
||||
void InvalidateCacheSubtree(nsIContent *aContent, PRUint32 aEvent);
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID if it's in subtree of
|
||||
* Return the cached accessible by the given DOM node if it's in subtree of
|
||||
* this document accessible or the document accessible itself, otherwise null.
|
||||
*
|
||||
* @note the unique ID matches with the uniqueID attribute on nsIAccessNode
|
||||
*
|
||||
* @param aUniqueID [in] the unique ID used to cache the node.
|
||||
*
|
||||
* @return the accessible object
|
||||
*/
|
||||
nsAccessible* GetCachedAccessible(void *aUniqueID);
|
||||
nsAccessible* GetCachedAccessible(nsINode* aNode);
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID within this document.
|
||||
*
|
||||
* @note the unique ID matches with the uniqueID() of nsAccessNode
|
||||
*
|
||||
* @param aUniqueID [in] the unique ID used to cache the node.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleByUniqueID(void* aUniqueID)
|
||||
{
|
||||
return UniqueID() == aUniqueID ?
|
||||
this : mAccessibleCache.GetWeak(aUniqueID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached accessible by the given unique ID looking through
|
||||
* this and nested documents.
|
||||
*/
|
||||
nsAccessible* GetCachedAccessibleInSubtree(void* aUniqueID);
|
||||
nsAccessible* GetCachedAccessibleByUniqueIDInSubtree(void* aUniqueID);
|
||||
|
||||
/**
|
||||
* Cache the accessible.
|
||||
*
|
||||
* @param aUniquID [in] the unique identifier of accessible
|
||||
* @param aAccessible [in] accessible to cache
|
||||
*
|
||||
* @return true if accessible being cached, otherwise false
|
||||
*/
|
||||
PRBool CacheAccessible(void *aUniqueID, nsAccessible *aAccessible);
|
||||
PRBool CacheAccessible(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Remove the given accessible from document cache.
|
||||
* Shutdown the accessible and remove it from document cache.
|
||||
*/
|
||||
void RemoveAccessNodeFromCache(nsAccessible *aAccessible);
|
||||
void ShutdownAccessible(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Process the event when the queue of pending events is untwisted. Fire
|
||||
@ -238,6 +229,17 @@ public:
|
||||
*/
|
||||
void ProcessPendingEvent(AccEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Update the accessible tree.
|
||||
*/
|
||||
void UpdateTree(nsIContent* aContainerNode, nsIContent* aStartChildNode,
|
||||
nsIContent* aEndChildNode, PRBool aIsInsert);
|
||||
|
||||
/**
|
||||
* Recreate an accessible, results in hide/show events pair.
|
||||
*/
|
||||
void RecreateAccessible(nsINode* aNode);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
|
||||
@ -264,20 +266,6 @@ protected:
|
||||
mChildDocuments.RemoveElement(aChildDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate parent-child relations for any cached accessible in the DOM
|
||||
* subtree. Accessible objects aren't destroyed.
|
||||
*
|
||||
* @param aStartNode [in] the root of the subrtee to invalidate accessible
|
||||
* child/parent refs in
|
||||
*/
|
||||
void InvalidateChildrenInSubtree(nsINode *aStartNode);
|
||||
|
||||
/**
|
||||
* Traverse through DOM tree and shutdown accessible objects.
|
||||
*/
|
||||
void RefreshNodes(nsINode *aStartNode);
|
||||
|
||||
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
|
||||
|
||||
/**
|
||||
@ -310,27 +298,6 @@ protected:
|
||||
CharacterDataChangeInfo* aInfo,
|
||||
PRBool aIsInserted);
|
||||
|
||||
/**
|
||||
* Create a text change event for a changed node.
|
||||
*
|
||||
* @param aContainerAccessible [in] the parent accessible for the node
|
||||
* @param aChangeNode [in] the node that is being inserted or
|
||||
* removed, or shown/hidden
|
||||
* @param aAccessible [in] the accessible for that node, or nsnull
|
||||
* if none exists
|
||||
* @param aIsInserting [in] is aChangeNode being created or shown
|
||||
* (vs. removed or hidden)
|
||||
* @param aIsAsync [in] whether casual change is async
|
||||
* @param aIsFromUserInput [in] the event is known to be from user input
|
||||
*/
|
||||
already_AddRefed<AccEvent>
|
||||
CreateTextChangeEventForNode(nsAccessible *aContainerAccessible,
|
||||
nsIContent *aChangeNode,
|
||||
nsAccessible *aAccessible,
|
||||
PRBool aIsInserting,
|
||||
PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Used to define should the event be fired on a delay.
|
||||
*/
|
||||
@ -339,34 +306,47 @@ protected:
|
||||
eDelayedEvent
|
||||
};
|
||||
|
||||
/**
|
||||
* Fire show/hide events for either the current node if it has an accessible,
|
||||
* or the first-line accessible descendants of the given node.
|
||||
*
|
||||
* @param aDOMNode [in] the given node
|
||||
* @param aAvoidOnThisNode [in] call with PR_TRUE the first time to
|
||||
* prevent event firing on root node for change
|
||||
* @param aEventType [in] event type to fire an event
|
||||
* @param aDelayedOrNormal [in] whether to fire the event on a delay
|
||||
* @param aIsAsyncChange [in] whether casual change is async
|
||||
* @param aIsFromUserInput [in] the event is known to be from user input
|
||||
*/
|
||||
nsresult FireShowHideEvents(nsINode *aDOMNode, PRBool aAvoidOnThisNode,
|
||||
PRUint32 aEventType,
|
||||
EEventFiringType aDelayedOrNormal,
|
||||
PRBool aIsAsyncChange,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
* Fire a value change event for the the given accessible if it is a text
|
||||
* field (has a ROLE_ENTRY).
|
||||
*/
|
||||
void FireValueChangeForTextFields(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Helper for UpdateTree() method. Go down to DOM subtree and updates
|
||||
* accessible tree. Return one of these flags.
|
||||
*/
|
||||
enum EUpdateTreeFlags {
|
||||
eNoAccessible = 0,
|
||||
eAccessible = 1,
|
||||
eAlertAccessible = 2
|
||||
};
|
||||
|
||||
PRUint32 UpdateTreeInternal(nsAccessible* aContainer,
|
||||
nsIContent* aStartNode,
|
||||
nsIContent* aEndNode,
|
||||
PRBool aIsInsert,
|
||||
PRBool aFireEvents,
|
||||
EIsFromUserInput aFromUserInput);
|
||||
|
||||
/**
|
||||
* Remove accessibles in subtree from node to accessible map.
|
||||
*/
|
||||
void UncacheChildrenInSubtree(nsAccessible* aRoot);
|
||||
|
||||
/**
|
||||
* Shutdown any cached accessible in the subtree.
|
||||
*
|
||||
* @param aAccessible [in] the root of the subrtee to invalidate accessible
|
||||
* child/parent refs in
|
||||
*/
|
||||
void ShutdownChildrenInSubtree(nsAccessible *aAccessible);
|
||||
|
||||
/**
|
||||
* Cache of accessibles within this document accessible.
|
||||
*/
|
||||
nsAccessibleHashtable mAccessibleCache;
|
||||
NodeToAccessibleMap mNodeToAccessibleMap;
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
nsCOMPtr<nsITimer> mScrollWatchTimer;
|
||||
|
@ -68,12 +68,12 @@ nsEventShell::FireEvent(AccEvent* aEvent)
|
||||
|
||||
void
|
||||
nsEventShell::FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
NS_ENSURE_TRUE(aAccessible,);
|
||||
|
||||
nsRefPtr<AccEvent> event = new AccEvent(aEventType, aAccessible,
|
||||
aIsAsynch, aIsFromUserInput);
|
||||
aIsFromUserInput);
|
||||
|
||||
FireEvent(event);
|
||||
}
|
||||
@ -147,9 +147,9 @@ nsAccEventQueue::Push(AccEvent* aEvent)
|
||||
|
||||
// Associate text change with hide event if it wasn't stolen from hiding
|
||||
// siblings during coalescence.
|
||||
AccHideEvent* hideEvent = downcast_accEvent(aEvent);
|
||||
if (hideEvent && !hideEvent->mTextChangeEvent)
|
||||
CreateTextChangeEventFor(hideEvent);
|
||||
AccMutationEvent* showOrHideEvent = downcast_accEvent(aEvent);
|
||||
if (showOrHideEvent && !showOrHideEvent->mTextChangeEvent)
|
||||
CreateTextChangeEventFor(showOrHideEvent);
|
||||
|
||||
// Process events.
|
||||
PrepareFlush();
|
||||
@ -209,10 +209,10 @@ nsAccEventQueue::WillRefresh(mozilla::TimeStamp aTime)
|
||||
if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
mDocument->ProcessPendingEvent(accEvent);
|
||||
|
||||
AccHideEvent* hideEvent = downcast_accEvent(accEvent);
|
||||
if (hideEvent) {
|
||||
if (hideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(hideEvent->mTextChangeEvent);
|
||||
AccMutationEvent* showOrhideEvent = downcast_accEvent(accEvent);
|
||||
if (showOrhideEvent) {
|
||||
if (showOrhideEvent->mTextChangeEvent)
|
||||
mDocument->ProcessPendingEvent(showOrhideEvent->mTextChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +267,7 @@ nsAccEventQueue::CoalesceEvents()
|
||||
// accessibles can't be created at this point because of lazy frame
|
||||
// construction (bug 570275).
|
||||
|
||||
// Coalesce hide events for sibling targets.
|
||||
// Coalesce hide and show events for sibling targets.
|
||||
if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
AccHideEvent* tailHideEvent = downcast_accEvent(tailEvent);
|
||||
AccHideEvent* thisHideEvent = downcast_accEvent(thisEvent);
|
||||
@ -278,6 +278,20 @@ nsAccEventQueue::CoalesceEvents()
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
CoalesceTextChangeEventsFor(tailHideEvent, thisHideEvent);
|
||||
|
||||
return;
|
||||
}
|
||||
} else if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_SHOW) {
|
||||
if (thisEvent->mAccessible->GetParent() ==
|
||||
tailEvent->mAccessible->GetParent()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
|
||||
// Coalesce text change events for show events.
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit) {
|
||||
AccShowEvent* tailShowEvent = downcast_accEvent(tailEvent);
|
||||
AccShowEvent* thisShowEvent = downcast_accEvent(thisEvent);
|
||||
CoalesceTextChangeEventsFor(tailShowEvent, thisShowEvent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -286,70 +300,22 @@ nsAccEventQueue::CoalesceEvents()
|
||||
if (!thisEvent->mNode->IsInDoc())
|
||||
continue;
|
||||
|
||||
// Coalesce show and reorder events by sibling targets.
|
||||
// Coalesce earlier event for the same target.
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Coalesce events by sibling targets (this is a case for reorder
|
||||
// events).
|
||||
if (thisEvent->mNode->GetNodeParent() ==
|
||||
tailEvent->mNode->GetNodeParent()) {
|
||||
tailEvent->mEventRule = thisEvent->mEventRule;
|
||||
return;
|
||||
}
|
||||
|
||||
// Specifies if this event target can be descendant of tail node.
|
||||
PRBool thisCanBeDescendantOfTail = PR_FALSE;
|
||||
|
||||
// Coalesce depending on whether this event was coalesced or not.
|
||||
if (thisEvent->mEventRule == AccEvent::eDoNotEmit) {
|
||||
// If this event was coalesced then do not emit tail event iff tail
|
||||
// event has the same target or its target is contained by this event
|
||||
// target. Note, we don't need to check whether tail event target
|
||||
// contains this event target since this event was coalesced already.
|
||||
|
||||
// As well we don't need to apply the calculated rule for siblings of
|
||||
// tail node because tail event rule was applied to possible tail
|
||||
// node siblings while this event was coalesced.
|
||||
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// If this event wasn't coalesced already then try to coalesce it or
|
||||
// tail event. If this event is coalesced by tail event then continue
|
||||
// search through events other events that can be coalesced by tail
|
||||
// event.
|
||||
|
||||
// If tail and this events have the same target then coalesce tail
|
||||
// event because more early event we should fire early and then stop
|
||||
// processing.
|
||||
if (thisEvent->mNode == tailEvent->mNode) {
|
||||
// Coalesce reorder events by special way since reorder events can
|
||||
// be conditional events (be or not be fired in the end).
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameSource(thisEvent, tailEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// This and tail events can be anywhere in the tree, make assumptions
|
||||
// for mutation events.
|
||||
|
||||
// More older show event target (thisNode) can't be contained by
|
||||
// recent.
|
||||
// show event target (tailNode), i.e be a descendant of tailNode.
|
||||
// XXX: target of older show event caused by DOM node appending can be
|
||||
// contained by target of recent show event caused by style change.
|
||||
// XXX: target of older show event caused by style change can be
|
||||
// contained by target of recent show event caused by style change.
|
||||
thisCanBeDescendantOfTail =
|
||||
tailEvent->mEventType != nsIAccessibleEvent::EVENT_SHOW ||
|
||||
tailEvent->mIsAsync;
|
||||
}
|
||||
// This and tail events can be anywhere in the tree, make assumptions
|
||||
// for mutation events.
|
||||
|
||||
// Coalesce tail event if tail node is descendant of this node. Stop
|
||||
// processing if tail event is coalesced since all possible descendants
|
||||
@ -359,54 +325,20 @@ nsAccEventQueue::CoalesceEvents()
|
||||
// this check for hide events.
|
||||
if (tailEvent->mEventType != nsIAccessibleEvent::EVENT_HIDE &&
|
||||
nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
|
||||
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(thisEvent, tailEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tailEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (tailEvent->mEventType == nsIAccessibleEvent::EVENT_HIDE &&
|
||||
nsCoreUtils::IsAncestorOf(thisEvent->mNode, tailEvent->mNode)) {
|
||||
NS_NOTREACHED("More older hide event target is an ancestor of recent hide event target!");
|
||||
}
|
||||
#endif
|
||||
|
||||
// If this node is a descendant of tail node then coalesce this event,
|
||||
// check other events in the queue.
|
||||
if (thisCanBeDescendantOfTail &&
|
||||
nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
|
||||
if (thisEvent->mEventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
CoalesceReorderEventsFromSameTree(tailEvent, thisEvent);
|
||||
if (tailEvent->mEventRule != AccEvent::eDoNotEmit)
|
||||
continue;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit thisEvent, also apply this result to sibling nodes of
|
||||
// thisNode.
|
||||
// check other events in the queue. Do not emit thisEvent, also apply
|
||||
// this result to sibling nodes of thisNode.
|
||||
if (nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
thisEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
ApplyToSiblings(0, index, thisEvent->mEventType,
|
||||
thisEvent->mNode, AccEvent::eDoNotEmit);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!thisCanBeDescendantOfTail &&
|
||||
nsCoreUtils::IsAncestorOf(tailEvent->mNode, thisEvent->mNode)) {
|
||||
NS_NOTREACHED("Older event target is a descendant of recent event target!");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // for (index)
|
||||
|
||||
} break; // case eCoalesceFromSameSubtree
|
||||
@ -455,48 +387,13 @@ nsAccEventQueue::ApplyToSiblings(PRUint32 aStart, PRUint32 aEnd,
|
||||
for (PRUint32 index = aStart; index < aEnd; index ++) {
|
||||
AccEvent* accEvent = mEvents[index];
|
||||
if (accEvent->mEventType == aEventType &&
|
||||
accEvent->mEventRule != AccEvent::eDoNotEmit &&
|
||||
accEvent->mEventRule != AccEvent::eDoNotEmit && accEvent->mNode &&
|
||||
accEvent->mNode->GetNodeParent() == aNode->GetNodeParent()) {
|
||||
accEvent->mEventRule = aEventRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
|
||||
AccEvent* aAccEvent2)
|
||||
{
|
||||
// Do not emit event2 if event1 is unconditional.
|
||||
AccReorderEvent* reorderEvent1 = downcast_accEvent(aAccEvent1);
|
||||
if (reorderEvent1->IsUnconditionalEvent()) {
|
||||
aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event1 if event2 is unconditional.
|
||||
AccReorderEvent* reorderEvent2 = downcast_accEvent(aAccEvent2);
|
||||
if (reorderEvent2->IsUnconditionalEvent()) {
|
||||
aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not emit event2 if event1 is valid, otherwise do not emit event1.
|
||||
if (reorderEvent1->HasAccessibleInReasonSubtree())
|
||||
aAccEvent2->mEventRule = AccEvent::eDoNotEmit;
|
||||
else
|
||||
aAccEvent1->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceReorderEventsFromSameTree(AccEvent* aAccEvent,
|
||||
AccEvent* aDescendantAccEvent)
|
||||
{
|
||||
// Do not emit descendant event if this event is unconditional.
|
||||
AccReorderEvent* reorderEvent = downcast_accEvent(aAccEvent);
|
||||
if (reorderEvent->IsUnconditionalEvent())
|
||||
aDescendantAccEvent->mEventRule = AccEvent::eDoNotEmit;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
||||
AccHideEvent* aThisEvent)
|
||||
@ -523,7 +420,35 @@ nsAccEventQueue::CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CreateTextChangeEventFor(AccHideEvent* aEvent)
|
||||
nsAccEventQueue::CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
|
||||
AccShowEvent* aThisEvent)
|
||||
{
|
||||
AccTextChangeEvent* textEvent = aThisEvent->mTextChangeEvent;
|
||||
if (!textEvent)
|
||||
return;
|
||||
|
||||
if (aTailEvent->mAccessible->GetIndexInParent() ==
|
||||
aThisEvent->mAccessible->GetIndexInParent() + 1) {
|
||||
// If tail target was inserted after this target, i.e. tail target is next
|
||||
// sibling of this target.
|
||||
aTailEvent->mAccessible->AppendTextTo(textEvent->mModifiedText,
|
||||
0, PR_UINT32_MAX);
|
||||
|
||||
} else if (aTailEvent->mAccessible->GetIndexInParent() ==
|
||||
aThisEvent->mAccessible->GetIndexInParent() -1) {
|
||||
// If tail target was inserted before this target, i.e. tail target is
|
||||
// previous sibling of this target.
|
||||
nsAutoString startText;
|
||||
aTailEvent->mAccessible->AppendTextTo(startText, 0, PR_UINT32_MAX);
|
||||
textEvent->mModifiedText = startText + textEvent->mModifiedText;
|
||||
textEvent->mStart -= startText.Length();
|
||||
}
|
||||
|
||||
aTailEvent->mTextChangeEvent.swap(aThisEvent->mTextChangeEvent);
|
||||
}
|
||||
|
||||
void
|
||||
nsAccEventQueue::CreateTextChangeEventFor(AccMutationEvent* aEvent)
|
||||
{
|
||||
nsRefPtr<nsHyperTextAccessible> textAccessible = do_QueryObject(
|
||||
GetAccService()->GetContainerAccessible(aEvent->mNode,
|
||||
@ -551,7 +476,6 @@ nsAccEventQueue::CreateTextChangeEventFor(AccHideEvent* aEvent)
|
||||
return;
|
||||
|
||||
aEvent->mTextChangeEvent =
|
||||
new AccTextChangeEvent(textAccessible, offset, text, PR_FALSE,
|
||||
aEvent->mIsAsync,
|
||||
new AccTextChangeEvent(textAccessible, offset, text, aEvent->IsShow(),
|
||||
aEvent->mIsFromUserInput ? eFromUserInput : eNoUserInput);
|
||||
}
|
||||
|
@ -66,11 +66,8 @@ public:
|
||||
*
|
||||
* @param aEventType [in] the event type
|
||||
* @param aAccessible [in] the event target
|
||||
* @param aIsAsync [in, optional] specifies whether the origin change
|
||||
* this event is fired owing to is async.
|
||||
*/
|
||||
static void FireEvent(PRUint32 aEventType, nsAccessible *aAccessible,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
@ -144,12 +141,6 @@ private:
|
||||
PRUint32 aEventType, nsINode* aNode,
|
||||
AccEvent::EEventRule aEventRule);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for the same DOM node.
|
||||
*/
|
||||
void CoalesceReorderEventsFromSameSource(AccEvent* aAccEvent1,
|
||||
AccEvent* aAccEvent2);
|
||||
|
||||
/**
|
||||
* Do not emit one of two given reorder events fired for DOM nodes in the case
|
||||
* when one DOM node is in parent chain of second one.
|
||||
@ -162,14 +153,15 @@ private:
|
||||
*/
|
||||
void CoalesceTextChangeEventsFor(AccHideEvent* aTailEvent,
|
||||
AccHideEvent* aThisEvent);
|
||||
void CoalesceTextChangeEventsFor(AccShowEvent* aTailEvent,
|
||||
AccShowEvent* aThisEvent);
|
||||
|
||||
/**
|
||||
* Create text change event caused by hide event. When a node is hidden or
|
||||
* removed, the text in an ancestor hyper text will lose characters. Create
|
||||
* text change event unless the node is being removed or frame is being
|
||||
* destroyed.
|
||||
* Create text change event caused by hide or show event. When a node is
|
||||
* hidden/removed or shown/appended, the text in an ancestor hyper text will
|
||||
* lose or get new characters.
|
||||
*/
|
||||
void CreateTextChangeEventFor(AccHideEvent* aEvent);
|
||||
void CreateTextChangeEventFor(AccMutationEvent* aEvent);
|
||||
|
||||
/**
|
||||
* Indicates whether we're waiting on a refresh notification from our
|
||||
|
@ -319,7 +319,6 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
||||
nsINode *aNode,
|
||||
nsIDOMEvent *aFocusEvent,
|
||||
PRBool aForceEvent,
|
||||
PRBool aIsAsynch,
|
||||
EIsFromUserInput aIsFromUserInput)
|
||||
{
|
||||
// Implementors: only fire delayed/async events from this method.
|
||||
@ -398,7 +397,7 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
||||
if (mCurrentARIAMenubar) {
|
||||
nsRefPtr<AccEvent> menuStartEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENU_START,
|
||||
menuBarAccessible, PR_FALSE, aIsFromUserInput,
|
||||
menuBarAccessible, aIsFromUserInput,
|
||||
AccEvent::eAllowDupes);
|
||||
if (menuStartEvent) {
|
||||
FireDelayedAccessibleEvent(menuStartEvent);
|
||||
@ -411,7 +410,7 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
||||
else if (mCurrentARIAMenubar) {
|
||||
nsRefPtr<AccEvent> menuEndEvent =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
|
||||
PR_FALSE, aIsFromUserInput, AccEvent::eAllowDupes);
|
||||
aIsFromUserInput, AccEvent::eAllowDupes);
|
||||
if (menuEndEvent) {
|
||||
FireDelayedAccessibleEvent(menuEndEvent);
|
||||
}
|
||||
@ -434,13 +433,11 @@ nsRootAccessible::FireAccessibleFocusEvent(nsAccessible *aAccessible,
|
||||
gLastFocusedNode = finalFocusNode;
|
||||
NS_IF_ADDREF(gLastFocusedNode);
|
||||
|
||||
gLastFocusedFrameType = (focusFrame && focusFrame->GetStyleVisibility()->IsVisible()) ? focusFrame->GetType() : 0;
|
||||
|
||||
// Coalesce focus events from the same document, because DOM focus event might
|
||||
// be fired for the document node and then for the focused DOM element.
|
||||
FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
|
||||
finalFocusNode, AccEvent::eCoalesceFromSameDocument,
|
||||
aIsAsynch, aIsFromUserInput);
|
||||
aIsFromUserInput);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -663,7 +660,6 @@ nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
||||
}
|
||||
else if (eventType.EqualsLiteral("blur")) {
|
||||
NS_IF_RELEASE(gLastFocusedNode);
|
||||
gLastFocusedFrameType = nsnull;
|
||||
gLastFocusedAccessiblesState = 0;
|
||||
}
|
||||
else if (eventType.EqualsLiteral("AlertActive")) {
|
||||
@ -732,16 +728,16 @@ nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
||||
if (fireFocus) {
|
||||
// Always asynch, always from user input.
|
||||
FireAccessibleFocusEvent(accessible, targetNode, aEvent, PR_TRUE,
|
||||
PR_TRUE, eFromUserInput);
|
||||
eFromUserInput);
|
||||
}
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always asynch, always from user input
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_START,
|
||||
accessible, PR_TRUE, eFromUserInput);
|
||||
accessible, eFromUserInput);
|
||||
}
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always asynch, always from user input
|
||||
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always from user input
|
||||
nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENU_END,
|
||||
accessible, PR_TRUE, eFromUserInput);
|
||||
accessible, eFromUserInput);
|
||||
FireCurrentFocusEvent();
|
||||
}
|
||||
else if (eventType.EqualsLiteral("ValueChange")) {
|
||||
|
@ -106,7 +106,6 @@ public:
|
||||
nsINode *aFocusNode,
|
||||
nsIDOMEvent *aFocusEvent,
|
||||
PRBool aForceEvent = PR_FALSE,
|
||||
PRBool aIsAsynch = PR_FALSE,
|
||||
EIsFromUserInput aIsFromUserInput = eAutoDetect);
|
||||
|
||||
/**
|
||||
|
@ -237,6 +237,11 @@ nsresult
|
||||
nsTextEquivUtils::AppendFromAccessible(nsAccessible *aAccessible,
|
||||
nsAString *aString)
|
||||
{
|
||||
// Ignore hidden accessible for name computation.
|
||||
nsIFrame* frame = aAccessible->GetFrame();
|
||||
if (!frame || !frame->GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
//XXX: is it necessary to care the accessible is not a document?
|
||||
if (aAccessible->IsContent()) {
|
||||
nsresult rv = AppendTextEquivFromTextContent(aAccessible->GetContent(),
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include "nsCoreUtils.h"
|
||||
|
||||
#include "nsILink.h"
|
||||
#include "nsIEventStateManager.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLLinkAccessible
|
||||
@ -82,20 +82,22 @@ nsHTMLLinkAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
|
||||
*aState |= nsIAccessibleStates::STATE_SELECTABLE;
|
||||
}
|
||||
|
||||
nsLinkState linkState = mContent->GetLinkState();
|
||||
if (linkState == eLinkState_NotLink || linkState == eLinkState_Unknown) {
|
||||
// This is a either named anchor (a link with also a name attribute) or
|
||||
// it doesn't have any attributes. Check if 'click' event handler is
|
||||
// registered, otherwise bail out.
|
||||
PRBool isOnclick = nsCoreUtils::HasClickListener(mContent);
|
||||
if (!isOnclick)
|
||||
return NS_OK;
|
||||
nsEventStates state = mContent->IntrinsicState();
|
||||
if (state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
|
||||
NS_EVENT_STATE_UNVISITED)) {
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
if (state.HasState(NS_EVENT_STATE_VISITED))
|
||||
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
if (linkState == eLinkState_Visited)
|
||||
*aState |= nsIAccessibleStates::STATE_TRAVERSED;
|
||||
// This is a either named anchor (a link with also a name attribute) or
|
||||
// it doesn't have any attributes. Check if 'click' event handler is
|
||||
// registered, otherwise bail out.
|
||||
if (nsCoreUtils::HasClickListener(mContent))
|
||||
*aState |= nsIAccessibleStates::STATE_LINKED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -186,6 +188,7 @@ nsHTMLLinkAccessible::IsLinked()
|
||||
if (IsDefunct())
|
||||
return PR_FALSE;
|
||||
|
||||
nsLinkState linkState = mContent->GetLinkState();
|
||||
return linkState != eLinkState_NotLink && linkState != eLinkState_Unknown;
|
||||
nsEventStates state = mContent->IntrinsicState();
|
||||
return state.HasAtLeastOneOfStates(NS_EVENT_STATE_VISITED |
|
||||
NS_EVENT_STATE_UNVISITED);
|
||||
}
|
||||
|
@ -80,23 +80,18 @@ nsHTMLSelectListAccessible::GetStateInternal(PRUint32 *aState,
|
||||
// nsIAccessibleStates::STATE_MULTISELECTABLE
|
||||
// nsIAccessibleStates::STATE_EXTSELECTABLE
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> select(do_QueryInterface(mContent));
|
||||
if (select) {
|
||||
if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
|
||||
// Treat first focusable option node as actual focus, in order
|
||||
// to avoid confusing JAWS, which needs focus on the option
|
||||
nsCOMPtr<nsIContent> focusedOption =
|
||||
nsHTMLSelectOptionAccessible::GetFocusedOption(mContent);
|
||||
if (focusedOption) { // Clear focused state since it is on option
|
||||
*aState &= ~nsIAccessibleStates::STATE_FOCUSED;
|
||||
}
|
||||
if (*aState & nsIAccessibleStates::STATE_FOCUSED) {
|
||||
// Treat first focusable option node as actual focus, in order
|
||||
// to avoid confusing JAWS, which needs focus on the option
|
||||
nsCOMPtr<nsIContent> focusedOption =
|
||||
nsHTMLSelectOptionAccessible::GetFocusedOption(mContent);
|
||||
if (focusedOption) { // Clear focused state since it is on option
|
||||
*aState &= ~nsIAccessibleStates::STATE_FOCUSED;
|
||||
}
|
||||
PRBool multiple;
|
||||
select->GetMultiple(&multiple);
|
||||
if ( multiple )
|
||||
*aState |= nsIAccessibleStates::STATE_MULTISELECTABLE |
|
||||
nsIAccessibleStates::STATE_EXTSELECTABLE;
|
||||
}
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple))
|
||||
*aState |= nsIAccessibleStates::STATE_MULTISELECTABLE |
|
||||
nsIAccessibleStates::STATE_EXTSELECTABLE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -122,19 +117,15 @@ nsHTMLSelectListAccessible::IsSelect()
|
||||
bool
|
||||
nsHTMLSelectListAccessible::SelectAll()
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElm(do_QueryInterface(mContent));
|
||||
PRBool isMultiple = PR_FALSE;
|
||||
selectElm->GetMultiple(&isMultiple);
|
||||
return isMultiple ? nsAccessibleWrap::SelectAll() : false;
|
||||
return mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple) ?
|
||||
nsAccessibleWrap::SelectAll() : false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLSelectListAccessible::UnselectAll()
|
||||
{
|
||||
nsCOMPtr<nsIDOMHTMLSelectElement> selectElm(do_QueryInterface(mContent));
|
||||
PRBool isMultiple = PR_FALSE;
|
||||
selectElm->GetMultiple(&isMultiple);
|
||||
return isMultiple ? nsAccessibleWrap::UnselectAll() : false;
|
||||
return mContent->HasAttr(kNameSpaceID_None, nsAccessibilityAtoms::multiple) ?
|
||||
nsAccessibleWrap::UnselectAll() : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -674,6 +665,9 @@ nsHTMLComboboxAccessible::
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessible
|
||||
|
||||
PRUint32
|
||||
nsHTMLComboboxAccessible::NativeRole()
|
||||
{
|
||||
@ -868,6 +862,9 @@ nsHTMLComboboxListAccessible::
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessNode
|
||||
|
||||
nsIFrame*
|
||||
nsHTMLComboboxListAccessible::GetFrame()
|
||||
{
|
||||
@ -883,6 +880,15 @@ nsHTMLComboboxListAccessible::GetFrame()
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLComboboxListAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLComboboxAccessible: nsAccessible
|
||||
|
||||
/**
|
||||
* As a nsHTMLComboboxListAccessible we can have the following states:
|
||||
* STATE_FOCUSED
|
||||
@ -908,14 +914,6 @@ nsHTMLComboboxListAccessible::GetStateInternal(PRUint32 *aState,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHTMLComboboxListAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same for all tree item, use |this| pointer as the unique
|
||||
// Id.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounds for the areaFrame.
|
||||
* Walks the Frame tree and checks for proper frames.
|
||||
|
@ -226,11 +226,9 @@ public:
|
||||
nsIWeakReference* aShell);
|
||||
virtual ~nsHTMLComboboxListAccessible() {}
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsAccessNode
|
||||
virtual nsIFrame* GetFrame();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsISelection.h"
|
||||
#include "nsISelectionController.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
@ -252,13 +253,12 @@ nsHTMLOutputAccessible::GetAttributesInternal(nsIPersistentProperties* aAttribut
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLLIAccessible::
|
||||
nsHTMLLIAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
const nsAString& aBulletText) :
|
||||
nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
|
||||
nsHyperTextAccessibleWrap(aContent, aShell)
|
||||
{
|
||||
if (!aBulletText.IsEmpty()) {
|
||||
mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell,
|
||||
aBulletText);
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(GetFrame());
|
||||
if (blockFrame && !blockFrame->BulletIsEmptyExternal()) {
|
||||
mBulletAccessible = new nsHTMLListBulletAccessible(mContent, mWeakShell);
|
||||
if (mBulletAccessible)
|
||||
mBulletAccessible->Init();
|
||||
}
|
||||
@ -329,21 +329,14 @@ nsHTMLLIAccessible::CacheChildren()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsHTMLListBulletAccessible::
|
||||
nsHTMLListBulletAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
const nsAString& aBulletText) :
|
||||
nsLeafAccessible(aContent, aShell), mBulletText(aBulletText)
|
||||
nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell) :
|
||||
nsLeafAccessible(aContent, aShell)
|
||||
{
|
||||
mBulletText += ' '; // Otherwise bullets are jammed up against list text
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLListBulletAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same as for list item, use |this| pointer as the unique
|
||||
// id.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessNode
|
||||
|
||||
void
|
||||
nsHTMLListBulletAccessible::Shutdown()
|
||||
@ -352,11 +345,32 @@ nsHTMLListBulletAccessible::Shutdown()
|
||||
nsLeafAccessible::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsHTMLListBulletAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHTMLListBulletAccessible: nsAccessible
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLListBulletAccessible::GetName(nsAString &aName)
|
||||
{
|
||||
// Native anonymous content, ARIA can't be used.
|
||||
aName = mBulletText;
|
||||
aName.Truncate();
|
||||
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Native anonymous content, ARIA can't be used. Get list bullet text.
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
if (blockFrame) {
|
||||
blockFrame->GetBulletText(aName);
|
||||
|
||||
// Append space otherwise bullets are jammed up against list text.
|
||||
aName.Append(' ');
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -381,11 +395,17 @@ nsresult
|
||||
nsHTMLListBulletAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
|
||||
PRUint32 aLength)
|
||||
{
|
||||
PRUint32 maxLength = mBulletText.Length() - aStartOffset;
|
||||
if (aLength > maxLength) {
|
||||
aLength = maxLength;
|
||||
nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame());
|
||||
if (blockFrame) {
|
||||
nsAutoString bulletText;
|
||||
blockFrame->GetBulletText(bulletText);
|
||||
|
||||
PRUint32 maxLength = bulletText.Length() - aStartOffset;
|
||||
if (aLength > maxLength)
|
||||
aLength = maxLength;
|
||||
|
||||
aText += Substring(bulletText, aStartOffset, aLength);
|
||||
}
|
||||
aText += Substring(mBulletText, aStartOffset, aLength);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -130,17 +130,14 @@ public:
|
||||
class nsHTMLListBulletAccessible : public nsLeafAccessible
|
||||
{
|
||||
public:
|
||||
nsHTMLListBulletAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
const nsAString& aBulletText);
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
nsHTMLListBulletAccessible(nsIContent* aContent, nsIWeakReference* aShell);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetName(nsAString& aName);
|
||||
|
||||
// nsAccessNode
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual PRUint32 NativeRole();
|
||||
@ -180,8 +177,7 @@ public:
|
||||
class nsHTMLLIAccessible : public nsHyperTextAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsHTMLLIAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
const nsAString& aBulletText);
|
||||
nsHTMLLIAccessible(nsIContent* aContent, nsIWeakReference* aShell);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -134,13 +134,59 @@ STDMETHODIMP nsAccessNodeWrap::QueryInterface(REFIID iid, void** ppv)
|
||||
STDMETHODIMP
|
||||
nsAccessNodeWrap::QueryService(REFGUID guidService, REFIID iid, void** ppv)
|
||||
{
|
||||
*ppv = nsnull;
|
||||
|
||||
static const GUID IID_SimpleDOMDeprecated = {0x0c539790,0x12e4,0x11cf,0xb6,0x61,0x00,0xaa,0x00,0x4c,0xd6,0xd8};
|
||||
|
||||
// Provide a special service ID for getting the accessible for the browser tab
|
||||
// document that contains this accessible object. If this accessible object
|
||||
// is not inside a browser tab then the service fails with E_NOINTERFACE.
|
||||
// A use case for this is for screen readers that need to switch context or
|
||||
// 'virtual buffer' when focus moves from one browser tab area to another.
|
||||
static const GUID SID_IAccessibleContentDocument = {0xa5d8e1f3,0x3571,0x4d8f,0x95,0x21,0x07,0xed,0x28,0xfb,0x07,0x2e};
|
||||
|
||||
if (guidService != IID_ISimpleDOMNode &&
|
||||
guidService != IID_SimpleDOMDeprecated &&
|
||||
guidService != IID_IAccessible && guidService != IID_IAccessible2 &&
|
||||
guidService != IID_IAccessibleApplication)
|
||||
guidService != IID_IAccessibleApplication &&
|
||||
guidService != SID_IAccessibleContentDocument)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (guidService == SID_IAccessibleContentDocument) {
|
||||
if (iid != IID_IAccessible)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
||||
nsCoreUtils::GetDocShellTreeItemFor(mContent);
|
||||
if (!docShellTreeItem)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
// Walk up the parent chain without crossing the boundary at which item
|
||||
// types change, preventing us from walking up out of tab content.
|
||||
nsCOMPtr<nsIDocShellTreeItem> root;
|
||||
docShellTreeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
|
||||
if (!root)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
|
||||
// If the item type is typeContent, we assume we are in browser tab content.
|
||||
// Note this includes content such as about:addons, for consistency.
|
||||
PRInt32 itemType;
|
||||
root->GetItemType(&itemType);
|
||||
if (itemType != nsIDocShellTreeItem::typeContent)
|
||||
return E_NOINTERFACE;
|
||||
|
||||
// Make sure this is a document.
|
||||
nsDocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
|
||||
if (!docAcc)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
*ppv = static_cast<IAccessible*>(docAcc);
|
||||
|
||||
(reinterpret_cast<IUnknown*>(*ppv))->AddRef();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Can get to IAccessibleApplication from any node via QS
|
||||
if (iid == IID_IAccessibleApplication) {
|
||||
nsApplicationAccessible *applicationAcc = GetApplicationAccessible();
|
||||
@ -211,9 +257,7 @@ __try{
|
||||
// accessibility application can compare this to the childID we
|
||||
// return for events such as focus events, to correlate back to
|
||||
// data nodes in their internal object model.
|
||||
void *uniqueID;
|
||||
GetUniqueID(&uniqueID);
|
||||
*aUniqueID = - NS_PTR_TO_INT32(uniqueID);
|
||||
*aUniqueID = - NS_PTR_TO_INT32(UniqueID());
|
||||
|
||||
*aNumChildren = GetNode()->GetChildCount();
|
||||
|
||||
|
@ -1354,12 +1354,7 @@ STDMETHODIMP
|
||||
nsAccessibleWrap::get_uniqueID(long *uniqueID)
|
||||
{
|
||||
__try {
|
||||
void *id = nsnull;
|
||||
nsresult rv = GetUniqueID(&id);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*uniqueID = - reinterpret_cast<long>(id);
|
||||
*uniqueID = - reinterpret_cast<long>(UniqueID());
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
@ -1575,60 +1570,53 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
||||
if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED ||
|
||||
eventType == nsIAccessibleEvent::EVENT_FOCUS) {
|
||||
UpdateSystemCaret();
|
||||
|
||||
} else if (eventType == nsIAccessibleEvent::EVENT_REORDER) {
|
||||
// If the accessible children are changed then drop the IEnumVariant current
|
||||
// position of the accessible.
|
||||
UnattachIEnumVariant();
|
||||
}
|
||||
|
||||
|
||||
PRInt32 childID = GetChildIDFor(accessible); // get the id for the accessible
|
||||
if (!childID)
|
||||
return NS_OK; // Can't fire an event without a child ID
|
||||
|
||||
// See if we're in a scrollable area with its own window
|
||||
nsAccessible *newAccessible = nsnull;
|
||||
if (eventType == nsIAccessibleEvent::EVENT_HIDE) {
|
||||
// Don't use frame from current accessible when we're hiding that
|
||||
// accessible.
|
||||
newAccessible = accessible->GetCachedParent();
|
||||
} else {
|
||||
newAccessible = accessible;
|
||||
}
|
||||
|
||||
HWND hWnd = GetHWNDFor(newAccessible);
|
||||
HWND hWnd = GetHWNDFor(accessible);
|
||||
NS_ENSURE_TRUE(hWnd, NS_ERROR_FAILURE);
|
||||
|
||||
// Gecko uses two windows for every scrollable area. One window contains
|
||||
// scrollbars and the child window contains only the client area.
|
||||
// Details of the 2 window system:
|
||||
// * Scrollbar window: caret drawing window & return value for WindowFromAccessibleObject()
|
||||
// * Client area window: text drawing window & MSAA event window
|
||||
nsAutoString tag;
|
||||
nsCAutoString id;
|
||||
nsIContent* cnt = accessible->GetContent();
|
||||
if (cnt) {
|
||||
cnt->Tag()->ToString(tag);
|
||||
nsIAtom* aid = cnt->GetID();
|
||||
if (aid)
|
||||
aid->ToUTF8String(id);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_A11Y
|
||||
printf("\n\nMSAA event: event: %d, target: %s@id='%s', childid: %d, hwnd: %d\n\n",
|
||||
eventType, NS_ConvertUTF16toUTF8(tag).get(), id.get(),
|
||||
childID, hWnd);
|
||||
#endif
|
||||
|
||||
// Fire MSAA event for client area window.
|
||||
NotifyWinEvent(winEvent, hWnd, OBJID_CLIENT, childID);
|
||||
|
||||
// If the accessible children are changed then drop the IEnumVariant current
|
||||
// position of the accessible.
|
||||
if (eventType == nsIAccessibleEvent::EVENT_REORDER)
|
||||
UnattachIEnumVariant();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//------- Helper methods ---------
|
||||
|
||||
PRInt32 nsAccessibleWrap::GetChildIDFor(nsIAccessible* aAccessible)
|
||||
PRInt32 nsAccessibleWrap::GetChildIDFor(nsAccessible* aAccessible)
|
||||
{
|
||||
// A child ID of the window is required, when we use NotifyWinEvent,
|
||||
// so that the 3rd party application can call back and get the IAccessible
|
||||
// the event occurred on.
|
||||
|
||||
void *uniqueID = nsnull;
|
||||
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(aAccessible));
|
||||
if (!accessNode) {
|
||||
return 0;
|
||||
}
|
||||
accessNode->GetUniqueID(&uniqueID);
|
||||
|
||||
// Yes, this means we're only compatibible with 32 bit
|
||||
// MSAA is only available for 32 bit windows, so it's okay
|
||||
return - NS_PTR_TO_INT32(uniqueID);
|
||||
// XXX: bug 606080
|
||||
return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
|
||||
}
|
||||
|
||||
HWND
|
||||
|
@ -310,7 +310,7 @@ public: // construction, destruction
|
||||
virtual nsresult HandleAccEvent(AccEvent* aEvent);
|
||||
|
||||
// Helper methods
|
||||
static PRInt32 GetChildIDFor(nsIAccessible* aAccessible);
|
||||
static PRInt32 GetChildIDFor(nsAccessible* aAccessible);
|
||||
static HWND GetHWNDFor(nsAccessible *aAccessible);
|
||||
static HRESULT ConvertToIA2Attributes(nsIPersistentProperties *aAttributes,
|
||||
BSTR *aIA2Attributes);
|
||||
|
@ -109,7 +109,7 @@ nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
|
||||
if (aVarChild.vt == VT_I4 && aVarChild.lVal < 0) {
|
||||
// Convert child ID to unique ID.
|
||||
void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
|
||||
return GetCachedAccessibleInSubtree(uniqueID);
|
||||
return GetCachedAccessibleByUniqueIDInSubtree(uniqueID);
|
||||
}
|
||||
|
||||
return nsAccessibleWrap::GetXPAccessibleFor(aVarChild);
|
||||
|
@ -64,7 +64,7 @@ nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
||||
return S_FALSE;
|
||||
|
||||
*aIA2Array =
|
||||
static_cast<IUnknown**>(nsMemory::Alloc((length) * sizeof(IUnknown*)));
|
||||
static_cast<IUnknown**>(::CoTaskMemAlloc((length) * sizeof(IUnknown*)));
|
||||
if (!*aIA2Array)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
@ -90,7 +90,7 @@ nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
|
||||
(*aIA2Array)[idx2] = NULL;
|
||||
}
|
||||
|
||||
nsMemory::Free(*aIA2Array);
|
||||
::CoTaskMemFree(*aIA2Array);
|
||||
return GetHRESULT(rv);
|
||||
}
|
||||
|
||||
|
@ -509,15 +509,13 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
|
||||
|
||||
if (accessible) {
|
||||
nsRefPtr<AccEvent> event =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, accessible);
|
||||
nsEventShell::FireEvent(event);
|
||||
|
||||
accessible->Shutdown();
|
||||
|
||||
// Remove accessible from document cache and tree cache.
|
||||
// Shutdown and remove accessible from document cache and tree cache.
|
||||
nsDocAccessible *docAccessible = GetDocAccessible();
|
||||
if (docAccessible)
|
||||
docAccessible->RemoveAccessNodeFromCache(accessible);
|
||||
docAccessible->ShutdownAccessible(accessible);
|
||||
|
||||
mAccessibleCache.Remove(key);
|
||||
}
|
||||
@ -539,12 +537,10 @@ nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
|
||||
nsAccessible *accessible = mAccessibleCache.GetWeak(key);
|
||||
|
||||
if (accessible) {
|
||||
accessible->Shutdown();
|
||||
|
||||
// Remove accessible from document cache and tree cache.
|
||||
// Shutdown and remove accessible from document cache and tree cache.
|
||||
nsDocAccessible *docAccessible = GetDocAccessible();
|
||||
if (docAccessible)
|
||||
docAccessible->RemoveAccessNodeFromCache(accessible);
|
||||
docAccessible->ShutdownAccessible(accessible);
|
||||
|
||||
mAccessibleCache.Remove(key);
|
||||
}
|
||||
@ -610,7 +606,7 @@ nsXULTreeAccessible::TreeViewChanged()
|
||||
// AT because it should be expensive to fire destroy events for each tree item
|
||||
// in cache.
|
||||
nsRefPtr<AccEvent> eventDestroy =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_HIDE, this);
|
||||
if (!eventDestroy)
|
||||
return;
|
||||
|
||||
@ -621,7 +617,7 @@ nsXULTreeAccessible::TreeViewChanged()
|
||||
mTree->GetView(getter_AddRefs(mTreeView));
|
||||
|
||||
nsRefPtr<AccEvent> eventCreate =
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this, PR_FALSE);
|
||||
new AccEvent(nsIAccessibleEvent::EVENT_SHOW, this);
|
||||
if (!eventCreate)
|
||||
return;
|
||||
|
||||
@ -662,18 +658,6 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeItemAccessibleBase,
|
||||
nsAccessible,
|
||||
nsXULTreeItemAccessibleBase)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsIAccessNode implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeItemAccessibleBase::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
// Since mContent is same for all tree items and tree itself, use |this|
|
||||
// pointer as the unique ID.
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsIAccessible implementation
|
||||
|
||||
@ -888,6 +872,12 @@ nsXULTreeItemAccessibleBase::Shutdown()
|
||||
nsAccessibleWrap::Shutdown();
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULTreeItemAccessibleBase::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeItemAccessibleBase: nsAccessible public methods
|
||||
|
||||
|
@ -181,9 +181,6 @@ public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
|
||||
@ -207,6 +204,7 @@ public:
|
||||
// nsAccessNode
|
||||
virtual PRBool IsDefunct();
|
||||
virtual void Shutdown();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
|
@ -804,18 +804,6 @@ NS_IMPL_ISUPPORTS_INHERITED2(nsXULTreeGridCellAccessible,
|
||||
nsIAccessibleTableCell,
|
||||
nsXULTreeGridCellAccessible)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsIAccessNode implementation
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTreeGridCellAccessible::GetUniqueID(void **aUniqueID)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUniqueID);
|
||||
*aUniqueID = static_cast<void*>(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsIAccessible implementation
|
||||
|
||||
@ -1124,6 +1112,12 @@ nsXULTreeGridCellAccessible::Init()
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULTreeGridCellAccessible::IsPrimaryForNode() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTreeGridCellAccessible: nsAccessible public implementation
|
||||
|
||||
|
@ -141,9 +141,6 @@ public:
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIAccessNode
|
||||
NS_IMETHOD GetUniqueID(void **aUniqueID);
|
||||
|
||||
// nsIAccessible
|
||||
NS_IMETHOD GetFocusedChild(nsIAccessible **aFocusedChild);
|
||||
|
||||
@ -161,6 +158,7 @@ public:
|
||||
// nsAccessNode
|
||||
virtual PRBool IsDefunct();
|
||||
virtual PRBool Init();
|
||||
virtual bool IsPrimaryForNode() const;
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
|
||||
|
@ -52,6 +52,7 @@ DIRS = \
|
||||
states \
|
||||
table \
|
||||
tree \
|
||||
treeupdate \
|
||||
$(null)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
@ -51,6 +51,7 @@ _TEST_FILES =\
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_inputs.html \
|
||||
test_link.html \
|
||||
test_tree.xul \
|
||||
test_treegrid.xul \
|
||||
$(NULL)
|
||||
|
@ -19,18 +19,55 @@
|
||||
src="../actions.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function getAnchorTargetDocumentAcc()
|
||||
{
|
||||
var thisTabDocAcc = getTabDocAccessible();
|
||||
var thisDocTabPanelAcc = thisTabDocAcc.parent.parent;
|
||||
var tabPanelsAcc = thisDocTabPanelAcc.parent;
|
||||
var newDocTabPanelAcc = tabPanelsAcc.lastChild.firstChild;
|
||||
return newDocTabPanelAcc.firstChild;
|
||||
}
|
||||
|
||||
function linkChecker(aID)
|
||||
{
|
||||
this.type = EVENT_DOCUMENT_LOAD_COMPLETE;
|
||||
this.__defineGetter__("target", getAnchorTargetDocumentAcc);
|
||||
|
||||
this.check = function linkChecker_check()
|
||||
{
|
||||
var anchorTargetWindow =
|
||||
getAccessible(getAnchorTargetDocumentAcc(), [nsIAccessibleDocument]).
|
||||
window;
|
||||
anchorTargetWindow.close();
|
||||
}
|
||||
|
||||
this.getID = function linkChecker_getID()
|
||||
{
|
||||
return "link '" + aID + "' states check ";
|
||||
}
|
||||
}
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var actionsArray = [
|
||||
{
|
||||
ID: "link1",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
events: CLICK_EVENTS,
|
||||
eventSeq: [
|
||||
new linkChecker("link1")
|
||||
]
|
||||
},
|
||||
{
|
||||
ID: "img1",
|
||||
actionName: "click",
|
||||
events: CLICK_EVENTS
|
||||
targetID: "link1",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS,
|
||||
eventSeq: [
|
||||
new linkChecker("link1")
|
||||
]
|
||||
},
|
||||
{
|
||||
ID: "link2",
|
||||
@ -39,7 +76,8 @@
|
||||
},
|
||||
{
|
||||
ID: "img2",
|
||||
actionName: "click",
|
||||
targetID: "link2",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
@ -49,7 +87,8 @@
|
||||
},
|
||||
{
|
||||
ID: "img3",
|
||||
actionName: "click",
|
||||
targetID: "link3",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
},
|
||||
{
|
||||
@ -59,7 +98,8 @@
|
||||
},
|
||||
{
|
||||
ID: "img4",
|
||||
actionName: "click",
|
||||
targetID: "link4",
|
||||
actionName: "jump",
|
||||
events: CLICK_EVENTS
|
||||
}
|
||||
];
|
||||
@ -83,7 +123,7 @@
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<a href="http://mozilla.org" id="link1">
|
||||
<a href="about:mozilla" id="link1" target="_blank">
|
||||
<img src="../moz.png" id="img1">
|
||||
</a>
|
||||
<a id="link2" onmousedown="">
|
||||
@ -95,5 +135,7 @@
|
||||
<a id="link4" onmouseup="">
|
||||
<img src="../moz.png" id="img4">
|
||||
</a>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -429,11 +429,8 @@
|
||||
ID = "area14";
|
||||
defAttrs = buildDefaultTextAttrs(ID, kInputFontSize);
|
||||
|
||||
// XXX: While we expose text leaf accessibles for placeholder we grab its
|
||||
// style, bug 545817.
|
||||
// attrs = { color: "rgb(109, 109, 109)" };
|
||||
//testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
todo(false, "enable commented tests when bug 545817 is fixed");
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area15, embed char tests, "*plain*plain**bold*bold*"
|
||||
|
@ -50,42 +50,6 @@ const nsIDOMXULElement = Components.interfaces.nsIDOMXULElement;
|
||||
|
||||
const nsIPropertyElement = Components.interfaces.nsIPropertyElement;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// States
|
||||
|
||||
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
|
||||
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
|
||||
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
|
||||
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
|
||||
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
|
||||
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
|
||||
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
|
||||
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
|
||||
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
|
||||
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
|
||||
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
|
||||
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
|
||||
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
|
||||
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
|
||||
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
|
||||
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
|
||||
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
|
||||
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
|
||||
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
|
||||
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
|
||||
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
|
||||
|
||||
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
|
||||
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
|
||||
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// OS detect
|
||||
const MAC = (navigator.platform.indexOf("Mac") != -1)? true : false;
|
||||
@ -96,6 +60,8 @@ const WIN = (navigator.platform.indexOf("Win") != -1)? true : false;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Accessible general
|
||||
|
||||
const STATE_BUSY = nsIAccessibleStates.STATE_BUSY;
|
||||
|
||||
const kEmbedChar = String.fromCharCode(0xfffc);
|
||||
|
||||
/**
|
||||
@ -264,6 +230,19 @@ function isAccessible(aAccOrElmOrID, aInterfaces)
|
||||
true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an accessible that contains the DOM node for the given identifier.
|
||||
*/
|
||||
function getContainerAccessible(aAccOrElmOrID)
|
||||
{
|
||||
var node = getNode(aAccOrElmOrID);
|
||||
if (!node)
|
||||
return null;
|
||||
|
||||
while ((node = node.parentNode) && !isAccessible(node));
|
||||
return node ? getAccessible(node) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return root accessible for the given identifier.
|
||||
*/
|
||||
@ -274,6 +253,25 @@ function getRootAccessible(aAccOrElmOrID)
|
||||
return acc ? acc.rootDocument.QueryInterface(nsIAccessible) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return tab document accessible the given accessible is contained by.
|
||||
*/
|
||||
function getTabDocAccessible(aAccOrElmOrID)
|
||||
{
|
||||
var acc = getAccessible(aAccOrElmOrID ? aAccOrElmOrID : document,
|
||||
[nsIAccessNode]);
|
||||
|
||||
var docAcc = acc.document.QueryInterface(nsIAccessible);
|
||||
var containerDocAcc = docAcc.parent.QueryInterface(nsIAccessNode).document;
|
||||
|
||||
// Test is running is stand-alone mode.
|
||||
if (acc.rootDocument == containerDocAcc)
|
||||
return docAcc;
|
||||
|
||||
// In the case of running all tests together.
|
||||
return containerDocAcc.QueryInterface(nsIAccessible);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return application accessible.
|
||||
*/
|
||||
@ -542,6 +540,15 @@ function prettyName(aIdentifier)
|
||||
} catch (e) {
|
||||
msg += "defunct";
|
||||
}
|
||||
|
||||
if (acc) {
|
||||
var exp = /native\s*@\s*(0x[a-f0-9]+)/g;
|
||||
var match = exp.exec(acc.valueOf());
|
||||
if (match)
|
||||
msg += ", address: " + match[1];
|
||||
else
|
||||
msg += ", address: " + acc.valueOf();
|
||||
}
|
||||
msg += "]";
|
||||
|
||||
return msg;
|
||||
@ -571,14 +578,16 @@ addLoadEvent(initialize);
|
||||
function getNodePrettyName(aNode)
|
||||
{
|
||||
try {
|
||||
if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
|
||||
return " '" + aNode.getAttribute("id") + "' ";
|
||||
|
||||
if (aNode.nodeType == nsIDOMNode.DOCUMENT_NODE)
|
||||
return " 'document node' ";
|
||||
|
||||
return " '" + aNode.localName + " node' ";
|
||||
var name = " '" + aNode.localName;
|
||||
if (aNode.nodeType == nsIDOMNode.ELEMENT_NODE && aNode.hasAttribute("id"))
|
||||
name += "@id='" + aNode.getAttribute("id") + "'";
|
||||
|
||||
name += " node' "
|
||||
return name;
|
||||
} catch (e) {
|
||||
return "no node info";
|
||||
return "' no node info '";
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ const EVENT_DOCUMENT_LOAD_STOPPED = nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_STOPP
|
||||
const EVENT_HIDE = nsIAccessibleEvent.EVENT_HIDE;
|
||||
const EVENT_FOCUS = nsIAccessibleEvent.EVENT_FOCUS;
|
||||
const EVENT_NAME_CHANGE = nsIAccessibleEvent.EVENT_NAME_CHANGE;
|
||||
const EVENT_MENUPOPUP_START = nsIAccessibleEvent.EVENT_MENUPOPUP_START;
|
||||
const EVENT_MENUPOPUP_END = nsIAccessibleEvent.EVENT_MENUPOPUP_END;
|
||||
const EVENT_REORDER = nsIAccessibleEvent.EVENT_REORDER;
|
||||
const EVENT_SCROLLING_START = nsIAccessibleEvent.EVENT_SCROLLING_START;
|
||||
const EVENT_SELECTION_ADD = nsIAccessibleEvent.EVENT_SELECTION_ADD;
|
||||
@ -554,7 +556,9 @@ function eventQueue(aEventType)
|
||||
styledNode.textContent = "matched";
|
||||
|
||||
// Dump matched events into console.
|
||||
dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
|
||||
if (gA11yEventDumpToConsole)
|
||||
dump("\n*****\nEQ matched: " + eventTypeToString(currType) + "\n*****\n");
|
||||
|
||||
} else {
|
||||
styledNode.textContent = "expected";
|
||||
}
|
||||
@ -932,6 +936,9 @@ var gA11yEventObserver =
|
||||
info += ". Listeners count: " + listenersArray.length;
|
||||
|
||||
eventFromDumpArea = false;
|
||||
|
||||
if (gA11yEventDumpToConsole)
|
||||
dump("\n" + info + "\n");
|
||||
dumpInfoToDOM(info);
|
||||
}
|
||||
}
|
||||
|
@ -54,7 +54,8 @@ _TEST_FILES =\
|
||||
test_aria_statechange.html \
|
||||
test_attrs.html \
|
||||
test_caretmove.html \
|
||||
$(warning test_coalescence.html temporarily disabled) \
|
||||
test_coalescence.html \
|
||||
test_contextmenu.html \
|
||||
test_docload.html \
|
||||
test_docload.xul \
|
||||
test_dragndrop.html \
|
||||
|
@ -364,6 +364,11 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=513213"
|
||||
title="coalesce events when new event is appended to the queue">
|
||||
Mozilla Bug 513213
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
|
141
accessible/tests/mochitest/events/test_contextmenu.html
Normal file
141
accessible/tests/mochitest/events/test_contextmenu.html
Normal file
@ -0,0 +1,141 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Context menu tests</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function showContextMenu(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_MENUPOPUP_START, getContextMenuNode()),
|
||||
];
|
||||
|
||||
this.invoke = function showContextMenu_invoke()
|
||||
{
|
||||
synthesizeMouse(this.DOMNode, 4, 4, { type: "contextmenu", button: 2 });
|
||||
}
|
||||
|
||||
this.getID = function showContextMenu_getID()
|
||||
{
|
||||
return "show context menu";
|
||||
}
|
||||
}
|
||||
|
||||
function selectMenuItem()
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, getFocusedMenuItem)
|
||||
];
|
||||
|
||||
this.invoke = function selectMenuItem_invoke()
|
||||
{
|
||||
synthesizeKey("VK_DOWN", { });
|
||||
}
|
||||
|
||||
this.getID = function selectMenuItem_getID()
|
||||
{
|
||||
return "select first menuitem";
|
||||
}
|
||||
}
|
||||
|
||||
function closeContextMenu(aID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_MENUPOPUP_END,
|
||||
getAccessible(getContextMenuNode()))
|
||||
];
|
||||
|
||||
this.invoke = function closeContextMenu_invoke()
|
||||
{
|
||||
synthesizeKey("VK_ESCAPE", { });
|
||||
}
|
||||
|
||||
this.getID = function closeContextMenu_getID()
|
||||
{
|
||||
return "close context menu";
|
||||
}
|
||||
}
|
||||
|
||||
function getContextMenuNode()
|
||||
{
|
||||
return getRootAccessible().DOMDocument.
|
||||
getElementById("contentAreaContextMenu");
|
||||
}
|
||||
|
||||
function getFocusedMenuItem()
|
||||
{
|
||||
var menu = getAccessible(getAccessible(getContextMenuNode()));
|
||||
for (var idx = 0; idx < menu.childCount; idx++) {
|
||||
var item = menu.getChildAt(idx);
|
||||
|
||||
if (hasState(item, STATE_FOCUSED))
|
||||
return getAccessible(item, [nsIAccessNode]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Do tests
|
||||
|
||||
var gQueue = null;
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new showContextMenu("input"));
|
||||
gQueue.push(new selectMenuItem());
|
||||
gQueue.push(new closeContextMenu());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTests);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580535"
|
||||
title="Broken accessibility in context menus">
|
||||
Mozilla Bug 580535
|
||||
</a><br>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<input id="input">
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
@ -58,11 +58,34 @@
|
||||
}
|
||||
}
|
||||
|
||||
function showNFocusAlertDialog()
|
||||
{
|
||||
this.ID = "alertdialog";
|
||||
this.DOMNode = getNode(this.ID);
|
||||
|
||||
this.invoke = function showNFocusAlertDialog_invoke()
|
||||
{
|
||||
document.getElementById(this.ID).style.display = 'block';
|
||||
document.getElementById(this.ID).focus();
|
||||
todo(false, "Enable show event handling when bug 422744 is fixed.");
|
||||
}
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_FOCUS, this.DOMNode),
|
||||
// new invokerChecker(EVENT_SHOW, this.DOMNode)
|
||||
];
|
||||
|
||||
this.getID = function showNFocusAlertDialog_getID()
|
||||
{
|
||||
return "Show and focus alert dialog " + prettyName(this.ID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do tests.
|
||||
*/
|
||||
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
@ -82,6 +105,8 @@
|
||||
|
||||
gQueue.push(new focusElmWhileSubdocIsFocused("button"));
|
||||
|
||||
gQueue.push(new showNFocusAlertDialog());
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -102,6 +127,11 @@
|
||||
title=" Inconsistent focus events when returning to a document frame">
|
||||
Mozilla Bug 352220
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=580464"
|
||||
title="Accessible focus incorrect after JS focus() but correct after switching apps or using menu bar">
|
||||
Mozilla Bug 580464
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
@ -112,6 +142,13 @@
|
||||
<button id="button">button</button>
|
||||
<iframe id="editabledoc" src="focus.html"></iframe>
|
||||
|
||||
<div id="alertdialog" style="display: none" tabindex="-1" role="alertdialog" aria-labelledby="title2" aria-describedby="desc2">
|
||||
<div id="title2">Blah blah</div>
|
||||
<div id="desc2">Woof woof woof.</div>
|
||||
<button>Close</button>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -41,7 +41,7 @@
|
||||
* Do tests.
|
||||
*/
|
||||
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
|
@ -230,16 +230,17 @@
|
||||
|
||||
this.invoke = function cloneAndReplaceInDOM_invoke()
|
||||
{
|
||||
var newElm = this.DOMNode.cloneNode(true);
|
||||
newElm.removeAttribute('id');
|
||||
this.eventSeq[1][1] = newElm;
|
||||
this.DOMNode.parentNode.replaceChild(newElm, this.DOMNode);
|
||||
this.DOMNode.parentNode.replaceChild(this.newElm, this.DOMNode);
|
||||
}
|
||||
|
||||
this.getID = function cloneAndReplaceInDOM_getID()
|
||||
{
|
||||
return aNodeOrID + " clone and replace in DOM.";
|
||||
}
|
||||
|
||||
this.newElm = this.DOMNode.cloneNode(true);
|
||||
this.newElm.removeAttribute('id');
|
||||
this.setTarget(kShowEvent, this.newElm);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -279,7 +280,7 @@
|
||||
* Do tests.
|
||||
*/
|
||||
var gQueue = null;
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
function doTests()
|
||||
{
|
||||
@ -292,13 +293,6 @@
|
||||
gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'visible' to 'hidden', 'hidden' to 'visible'.
|
||||
var id = "link2";
|
||||
getAccessible(id);
|
||||
gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of display style of accessible DOM node
|
||||
// from 'inline' to 'block', 'block' to 'inline'.
|
||||
var id = "link3";
|
||||
@ -306,12 +300,6 @@
|
||||
gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'collapse' to 'visible', 'visible' to 'collapse'.
|
||||
var id = "link4";
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
|
||||
|
||||
// Show/hide events by adding new accessible DOM node and removing old one.
|
||||
var id = "link5";
|
||||
gQueue.push(new cloneAndAppendToDOM(id));
|
||||
@ -347,16 +335,13 @@
|
||||
|
||||
// Show/hide events by creating new accessible DOM node and replacing
|
||||
// old one.
|
||||
// XXX: bug 472810
|
||||
// gQueue.push(new cloneAndReplaceInDOM("link6"));
|
||||
getAccessible("link6"); // ensure accessible is created
|
||||
gQueue.push(new cloneAndReplaceInDOM("link6"));
|
||||
|
||||
// Show/hide events by changing class name on the parent node.
|
||||
gQueue.push(new changeClass("container2", "link7", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container2", "link7", "displayNone",
|
||||
kHideEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
|
||||
kHideEvents));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
@ -372,11 +357,16 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=469985"
|
||||
title=" turn the test from bug 354745 into mochitest">
|
||||
Mozilla Bug 469985
|
||||
</a>
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=472662"
|
||||
title="no reorder event when html:link display property is changed from 'none' to 'inline'">
|
||||
Mozilla Bug 472662
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
|
@ -73,10 +73,10 @@
|
||||
var jar = getJar(rootDir);
|
||||
if (jar) {
|
||||
var tmpdir = extractJarToTmp(jar);
|
||||
rootDir = "file://" + tmpdir.path;
|
||||
rootDir = "file://" + tmpdir.path + '/';
|
||||
}
|
||||
|
||||
var url = rootDir + "/scroll.html#link1";
|
||||
var url = rootDir + "scroll.html#link1";
|
||||
var tabBrowser = document.getElementById("tabBrowser");
|
||||
tabBrowser.loadURI(url);
|
||||
}
|
||||
|
@ -84,22 +84,36 @@
|
||||
/**
|
||||
* Insert inaccessible child node containing accessibles.
|
||||
*/
|
||||
function insertChildSpan(aID)
|
||||
function insertChildSpan(aID, aInsertAllTogether)
|
||||
{
|
||||
this.__proto__ = new textInsertInvoker(aID, 0, 5, "33322");
|
||||
|
||||
this.invoke = function insertChildSpan_invoke()
|
||||
{
|
||||
// <span><span>333</span><span>22</span></span>
|
||||
var topSpan = document.createElement("span");
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
if (aInsertAllTogether) {
|
||||
var topSpan = document.createElement("span");
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
|
||||
} else {
|
||||
var topSpan = document.createElement("span");
|
||||
this.DOMNode.insertBefore(topSpan, this.DOMNode.childNodes[0]);
|
||||
|
||||
var fSpan = document.createElement("span");
|
||||
fSpan.textContent = "333";
|
||||
topSpan.appendChild(fSpan);
|
||||
|
||||
var sSpan = document.createElement("span");
|
||||
sSpan.textContent = "22";
|
||||
topSpan.appendChild(sSpan);
|
||||
}
|
||||
}
|
||||
|
||||
this.getID = function insertChildSpan_getID()
|
||||
@ -271,7 +285,8 @@
|
||||
// Text remove event on inaccessible child HTML span removal containing
|
||||
// accessible text nodes.
|
||||
gQueue.push(new removeChildSpan("p"));
|
||||
gQueue.push(new insertChildSpan("p"));
|
||||
gQueue.push(new insertChildSpan("p"), true);
|
||||
gQueue.push(new insertChildSpan("p"), false);
|
||||
|
||||
// Remove embedded character.
|
||||
gQueue.push(new removeChildDiv("div"));
|
||||
@ -323,6 +338,11 @@
|
||||
title="Cache text offsets within hypertext accessible">
|
||||
Mozilla Bug 575052
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275"
|
||||
title="Rework accessible tree update code">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
@ -15,6 +15,7 @@ const ROLE_COMBOBOX = nsIAccessibleRole.ROLE_COMBOBOX;
|
||||
const ROLE_COMBOBOX_LIST = nsIAccessibleRole.ROLE_COMBOBOX_LIST;
|
||||
const ROLE_COMBOBOX_OPTION = nsIAccessibleRole.ROLE_COMBOBOX_OPTION;
|
||||
const ROLE_COLUMNHEADER = nsIAccessibleRole.ROLE_COLUMNHEADER;
|
||||
const ROLE_DIALOG = nsIAccessibleRole.ROLE_DIALOG;
|
||||
const ROLE_DOCUMENT = nsIAccessibleRole.ROLE_DOCUMENT;
|
||||
const ROLE_EMBEDDED_OBJECT = nsIAccessibleRole.ROLE_EMBEDDED_OBJECT;
|
||||
const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
|
||||
@ -100,3 +101,23 @@ function getRole(aAccOrElmOrID)
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analogy of SimpleTest.is function used to check the role.
|
||||
*/
|
||||
function isRole(aIdentifier, aRole, aMsg)
|
||||
{
|
||||
var role = getRole(aIdentifier);
|
||||
if (role == - 1)
|
||||
return;
|
||||
|
||||
if (role == aRole) {
|
||||
ok(true, aMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
var got = roleToString(role);
|
||||
var expected = roleToString(aRole);
|
||||
|
||||
ok(false, aMsg + "got '" + got + "', expected '" + expected + "'");
|
||||
}
|
||||
|
@ -6,6 +6,46 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// State constants
|
||||
|
||||
// const STATE_BUSY is defined in common.js
|
||||
const STATE_CHECKED = nsIAccessibleStates.STATE_CHECKED;
|
||||
const STATE_CHECKABLE = nsIAccessibleStates.STATE_CHECKABLE;
|
||||
const STATE_COLLAPSED = nsIAccessibleStates.STATE_COLLAPSED;
|
||||
const STATE_EXPANDED = nsIAccessibleStates.STATE_EXPANDED;
|
||||
const STATE_EXTSELECTABLE = nsIAccessibleStates.STATE_EXTSELECTABLE;
|
||||
const STATE_FOCUSABLE = nsIAccessibleStates.STATE_FOCUSABLE;
|
||||
const STATE_FOCUSED = nsIAccessibleStates.STATE_FOCUSED;
|
||||
const STATE_HASPOPUP = nsIAccessibleStates.STATE_HASPOPUP;
|
||||
const STATE_INVALID = nsIAccessibleStates.STATE_INVALID;
|
||||
const STATE_LINKED = nsIAccessibleStates.STATE_LINKED;
|
||||
const STATE_MIXED = nsIAccessibleStates.STATE_MIXED;
|
||||
const STATE_MULTISELECTABLE = nsIAccessibleStates.STATE_MULTISELECTABLE;
|
||||
const STATE_OFFSCREEN = nsIAccessibleStates.STATE_OFFSCREEN;
|
||||
const STATE_PRESSED = nsIAccessibleStates.STATE_PRESSED;
|
||||
const STATE_READONLY = nsIAccessibleStates.STATE_READONLY;
|
||||
const STATE_REQUIRED = nsIAccessibleStates.STATE_REQUIRED;
|
||||
const STATE_SELECTABLE = nsIAccessibleStates.STATE_SELECTABLE;
|
||||
const STATE_SELECTED = nsIAccessibleStates.STATE_SELECTED;
|
||||
const STATE_TRAVERSED = nsIAccessibleStates.STATE_TRAVERSED;
|
||||
const STATE_UNAVAILABLE = nsIAccessibleStates.STATE_UNAVAILABLE;
|
||||
|
||||
const EXT_STATE_ACTIVE = nsIAccessibleStates.EXT_STATE_ACTIVE;
|
||||
const EXT_STATE_DEFUNCT = nsIAccessibleStates.EXT_STATE_DEFUNCT;
|
||||
const EXT_STATE_EDITABLE = nsIAccessibleStates.EXT_STATE_EDITABLE;
|
||||
const EXT_STATE_EXPANDABLE = nsIAccessibleStates.EXT_STATE_EXPANDABLE;
|
||||
const EXT_STATE_HORIZONTAL = nsIAccessibleStates.EXT_STATE_HORIZONTAL;
|
||||
const EXT_STATE_MULTI_LINE = nsIAccessibleStates.EXT_STATE_MULTI_LINE;
|
||||
const EXT_STATE_SINGLE_LINE = nsIAccessibleStates.EXT_STATE_SINGLE_LINE;
|
||||
const EXT_STATE_SUPPORTS_AUTOCOMPLETION =
|
||||
nsIAccessibleStates.EXT_STATE_SUPPORTS_AUTOCOMPLETION;
|
||||
const EXT_STATE_VERTICAL = nsIAccessibleStates.EXT_STATE_VERTICAL;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Test functions
|
||||
|
||||
/**
|
||||
* Tests the states and extra states of the given accessible.
|
||||
* Also tests for unwanted states and extra states.
|
||||
@ -92,14 +132,6 @@ function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
|
||||
isState(state & STATE_SELECTABLE, STATE_SELECTABLE, false,
|
||||
"Selected element should be selectable!");
|
||||
}
|
||||
|
||||
// unavailable
|
||||
if (state & STATE_UNAVAILABLE) {
|
||||
var role = getRole(aAccOrElmOrID);
|
||||
if (role != ROLE_GROUPING && role != ROLE_EMBEDDED_OBJECT)
|
||||
isState(state & STATE_FOCUSABLE, STATE_FOCUSABLE, false,
|
||||
"Disabled " + id + " must be focusable!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,6 +189,16 @@ function getStates(aAccOrElmOrID)
|
||||
return [state.value, extraState.value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the accessible has given states.
|
||||
*/
|
||||
function hasState(aAccOrElmOrID, aState, aExtraState)
|
||||
{
|
||||
var [state, exstate] = getStates(aAccOrElmOrID);
|
||||
return (aState ? state & aState : true) &&
|
||||
(aExtraState ? exstate & aExtraState : true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Private implementation details
|
||||
|
||||
|
@ -54,6 +54,8 @@ _TEST_FILES =\
|
||||
test_doc.html \
|
||||
test_docarticle.html \
|
||||
test_editablebody.html \
|
||||
test_inputs.html \
|
||||
test_inputs.xul \
|
||||
test_link.html \
|
||||
test_popup.xul \
|
||||
test_tree.xul \
|
||||
|
@ -29,6 +29,36 @@
|
||||
src="../states.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function testAriaDisabledTree(aAccOrElmOrID)
|
||||
{
|
||||
// test accessible and its subtree for propagated state.
|
||||
var acc = getAccessible(aAccOrElmOrID);
|
||||
if (!acc)
|
||||
return;
|
||||
|
||||
var [state, extraState] = getStates(aAccOrElmOrID);
|
||||
if (state & STATE_UNAVAILABLE) {
|
||||
var role = getRole(acc);
|
||||
if (role != ROLE_GROUPING) {
|
||||
testStates(acc, STATE_FOCUSABLE);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate over its children to see if the state got propagated.
|
||||
var children = null;
|
||||
try {
|
||||
children = acc.children;
|
||||
} catch(e) {}
|
||||
ok(children, "Could not get children for " + aAccOrElmOrID +"!");
|
||||
|
||||
if (children) {
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
var childAcc = children.queryElementAt(i, nsIAccessible);
|
||||
testAriaDisabledTree(childAcc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// aria_autocomplete
|
||||
@ -64,7 +94,7 @@
|
||||
|
||||
// test disabled group and all its descendants to see if they are
|
||||
// disabled, too. See bug 429285.
|
||||
testStatesInSubtree("group", STATE_UNAVAILABLE);
|
||||
testAriaDisabledTree("group");
|
||||
|
||||
// offscreen test
|
||||
testStates("aria_offscreen_textbox", STATE_OFFSCREEN);
|
||||
|
148
accessible/tests/mochitest/states/test_inputs.html
Normal file
148
accessible/tests/mochitest/states/test_inputs.html
Normal file
@ -0,0 +1,148 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML input states</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../states.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
// 'required' state. Also piggyback 'unavailable' testing here.
|
||||
var maybe_required = ["input","search","radio","checkbox","textarea"];
|
||||
var never_required = ["submit","button","reset","image"];
|
||||
|
||||
var i;
|
||||
for (i in maybe_required) {
|
||||
testStates(maybe_required[i], STATE_REQUIRED, 0, STATE_UNAVAILABLE);
|
||||
testStates(maybe_required[i] + "2", 0, 0, STATE_REQUIRED);
|
||||
testStates(maybe_required[i] + "3", STATE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
for (i in never_required) {
|
||||
testStates(never_required[i], 0, 0, STATE_REQUIRED);
|
||||
}
|
||||
|
||||
// inherited 'unavailable' state
|
||||
testStates("f", STATE_UNAVAILABLE);
|
||||
testStates("f_input", STATE_UNAVAILABLE);
|
||||
testStates("f_input_disabled", STATE_UNAVAILABLE);
|
||||
|
||||
// invalid/valid state
|
||||
var invalid = ["maxlength","pattern","email","url"];
|
||||
document.getElementById("maxlength").value = "i am too long";
|
||||
for (i in invalid) {
|
||||
testStates(invalid[i], STATE_INVALID);
|
||||
testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
|
||||
}
|
||||
|
||||
// invalid/valid state
|
||||
var invalid = ["maxlength","pattern","email","url"];
|
||||
document.getElementById("maxlength").value = "i am too long";
|
||||
for (i in invalid) {
|
||||
testStates(invalid[i], STATE_INVALID);
|
||||
testStates(invalid[i] + "2", 0, 0, STATE_INVALID);
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=559275"
|
||||
title="map attribute required to STATE_REQUIRED">
|
||||
Mozilla Bug 559275
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=389238"
|
||||
title="Support disabled state on fieldset">
|
||||
Mozilla Bug 389238
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=599163"
|
||||
title="check disabled state instead of attribute">
|
||||
Mozilla Bug 599163
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=601205"
|
||||
title="Expose intrinsic invalid state to accessibility API">
|
||||
Mozilla Bug 601205
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=601205"
|
||||
title="Expose intrinsic invalid state to accessibility API">
|
||||
Mozilla Bug 601205
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
|
||||
<form>
|
||||
<input id="input" type="input" required>
|
||||
<input id="input2" type="input">
|
||||
<input id="input3" type="input" disabled>
|
||||
<input id="search" type="search" required>
|
||||
<input id="search2" type="search">
|
||||
<input id="search3" type="search" disabled>
|
||||
<input id="radio" type="radio" required>
|
||||
<input id="radio2" type="radio">
|
||||
<input id="radio3" type="radio" disabled>
|
||||
<input id="checkbox" type="checkbox" required>
|
||||
<input id="checkbox2" type="checkbox">
|
||||
<input id="checkbox3" type="checkbox" disabled>
|
||||
<textarea id="textarea" required></textarea>
|
||||
<textarea id="textarea2"></textarea>
|
||||
<textarea id="textarea3" disabled></textarea>
|
||||
</form>
|
||||
|
||||
<!-- bogus required usage -->
|
||||
<input id="submit" type="submit" required>
|
||||
<input id="button" type="button" required>
|
||||
<input id="reset" type="reset" required>
|
||||
<input id="image" type="image" required>
|
||||
|
||||
<!-- disabled -->
|
||||
<fieldset id="f" disabled>
|
||||
<input id="f_input">
|
||||
<input id="f_input_disabled" disabled>
|
||||
</fieldset>
|
||||
|
||||
<!-- invalid/valid -->
|
||||
<input id="maxlength" maxlength="1">
|
||||
<input id="maxlength2" maxlength="100" value="foo">
|
||||
<input id="pattern" pattern="bar" value="foo">
|
||||
<input id="pattern2" pattern="bar" value="bar">
|
||||
<input id="email" type="email" value="foo">
|
||||
<input id="email2" type="email" value="foo@bar.com">
|
||||
<input id="url" type="url" value="foo">
|
||||
<input id="url2" type="url" value="http://mozilla.org/">
|
||||
|
||||
<!-- invalid/valid -->
|
||||
<input id="maxlength" maxlength="1">
|
||||
<input id="maxlength2" maxlength="100" value="foo">
|
||||
<input id="pattern" pattern="bar" value="foo">
|
||||
<input id="pattern2" pattern="bar" value="bar">
|
||||
<input id="email" type="email" value="foo">
|
||||
<input id="email2" type="email" value="foo@bar.com">
|
||||
<input id="url" type="url" value="foo">
|
||||
<input id="url2" type="url" value="http://mozilla.org/">
|
||||
|
||||
</body>
|
||||
</html>
|
84
accessible/tests/mochitest/states/test_inputs.xul
Normal file
84
accessible/tests/mochitest/states/test_inputs.xul
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessible XUL input control state tests">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../states.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
|
||||
function doTest()
|
||||
{
|
||||
testStates("some-text", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("some-text2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("some-password", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("some-password2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("checkbox", STATE_FOCUSABLE, 0, STATE_UNAVAILABLE);
|
||||
testStates("checkbox2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("radio-group", 0, 0, STATE_UNAVAILABLE);
|
||||
testStates("orange", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("violet", 0, 0, STATE_UNAVAILABLE);
|
||||
testStates("radio-group2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
testStates("orange2", STATE_UNAVAILABLE, 0 , STATE_FOCUSABLE);
|
||||
|
||||
SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=599163"
|
||||
title="check disabled state instead of attribute">
|
||||
Mozilla Bug 599163
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
|
||||
<textbox id="some-text"/>
|
||||
<textbox id="some-text2" disabled="true"/>
|
||||
<textbox id="some-password" type="password" maxlength="8"/>
|
||||
<textbox id="some-password2" type="password" maxlength="8" disabled="true"/>
|
||||
|
||||
<checkbox id="checkbox" checked="true" label="Steak"/>
|
||||
<checkbox id="checkbox2" checked="true" label="Salad" disabled="true"/>
|
||||
|
||||
<radiogroup id="radio-group">
|
||||
<radio id="orange" label="Orange" disabled="true"/>
|
||||
<radio id="violet" selected="true" label="Violet"/>
|
||||
<radio id="yellow" label="Yellow"/>
|
||||
</radiogroup>
|
||||
|
||||
<radiogroup id="radio-group2" disabled="true">
|
||||
<radio id="orange2" label="Orange"/>
|
||||
<radio id="violet2" selected="true" label="Violet"/>
|
||||
<radio id="yellow2" label="Yellow"/>
|
||||
</radiogroup>
|
||||
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
@ -21,11 +21,11 @@
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
// strong roles
|
||||
testStates("link1", STATE_LINKED);
|
||||
testStates("link2", STATE_LINKED);
|
||||
testStates("link3", STATE_LINKED);
|
||||
testStates("link4", STATE_LINKED);
|
||||
testStates("link5", 0, 0, STATE_LINKED);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
@ -52,6 +52,7 @@
|
||||
<a id="link2" onclick="">link</a>
|
||||
<a id="link3" onmousedown="">link</a>
|
||||
<a id="link4" onmouseup="">link</a>
|
||||
<a id="link5">not link</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
@ -68,7 +68,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=452161
|
||||
var frame = document.getElementById("frame");
|
||||
frame.contentDocument.designMode = "on";
|
||||
testEditable(frame.contentDocument);
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,8 @@
|
||||
src="common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="states.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="nsIAccessible_selects.js"></script>
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
var rootDir = getRootDirectory(window.location.href);
|
||||
var href = rootDir.path + "/foo";
|
||||
var href = rootDir.path + "foo";
|
||||
|
||||
// roles that can't live as nsHTMLLinkAccessibles
|
||||
testValue("aria_menuitem_link", "");
|
||||
|
@ -62,7 +62,6 @@ _TEST_FILES =\
|
||||
test_iframe.html \
|
||||
test_img.html \
|
||||
test_list.html \
|
||||
test_list_invalidate.html \
|
||||
test_media.html \
|
||||
test_menu.xul \
|
||||
test_select.html \
|
||||
|
@ -53,9 +53,6 @@
|
||||
{
|
||||
role: ROLE_ENTRY,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // HTML 5 placeholder attribute value
|
||||
},
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // Text node for the node's value
|
||||
}
|
||||
@ -126,9 +123,6 @@
|
||||
{
|
||||
role: ROLE_ENTRY,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // HTML 5 placeholder attribute value
|
||||
},
|
||||
{
|
||||
role: ROLE_TEXT_LEAF // Text node for the node's value
|
||||
}
|
||||
|
@ -30,26 +30,22 @@
|
||||
|
||||
function focusAnchor(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
this.link = getAccessible(this.DOMNode);
|
||||
this.linkChild = this.link.firstChild;
|
||||
this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
|
||||
this.linkNode = getNode(aID);
|
||||
this.link = getAccessible(this.linkNode);
|
||||
|
||||
this.eventSeq = [
|
||||
// new invokerChecker(EVENT_HIDE, this.linkChild),
|
||||
// new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
|
||||
new invokerChecker(EVENT_FOCUS, this.link)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.link),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
|
||||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.invoke = function focusAnchor_invoke()
|
||||
{
|
||||
todo(false, "enable event hide/show events");
|
||||
getNode(aID).focus();
|
||||
this.linkNode.focus();
|
||||
}
|
||||
|
||||
this.check = function focusAnchor_check(aEvent)
|
||||
{
|
||||
isnot(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function focusAnchor_getID()
|
||||
@ -58,34 +54,27 @@
|
||||
}
|
||||
}
|
||||
|
||||
function tabAnchor(aID, aPrevID)
|
||||
function tabAnchor(aID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
this.link = getAccessible(this.DOMNode);
|
||||
this.linkChild = this.link.firstChild;
|
||||
this.linkChildNode = getAccessible(this.linkChild, [nsIAccessNode]).DOMNode;
|
||||
this.prevLink = getAccessible(aPrevID);
|
||||
this.prevLinkNode = getAccessible(this.prevLink, [nsIAccessNode]).DOMNode;
|
||||
this.linkNode = getNode(aID);
|
||||
this.link = getAccessible(this.linkNode);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.prevLink),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.prevLinkNode),
|
||||
new invokerChecker(EVENT_HIDE, this.linkChild),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.linkChildNode),
|
||||
new invokerChecker(EVENT_FOCUS, this.link)
|
||||
new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
|
||||
];
|
||||
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.link),
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.DOMNode)
|
||||
];
|
||||
|
||||
this.invoke = function focusAnchor_invoke()
|
||||
this.invoke = function tabAnchor_invoke()
|
||||
{
|
||||
synthesizeKey("VK_TAB", { shiftKey: false });
|
||||
}
|
||||
|
||||
this.getID = function focusAnchor_getID()
|
||||
this.check = function tabAnchor_check(aEvent)
|
||||
{
|
||||
isnot(this.link, aEvent.accessible,
|
||||
"Focus should be fired against new link accessible!");
|
||||
}
|
||||
|
||||
this.getID = function tabAnchor_getID()
|
||||
{
|
||||
return "focus a:focus{overflow:scroll} #2";
|
||||
}
|
||||
@ -95,20 +84,20 @@
|
||||
// Do tests
|
||||
|
||||
var gQueue = null;
|
||||
// gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
function doTests()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// CSS 'overflow: scroll' property setting and unsetting causes accessible
|
||||
// recreation (and fire show/hide events) if the accessible is not
|
||||
// focused. If it's focused its children are recreated. For example,
|
||||
// focusing the HTML:a with ':focus {overflow: scroll; }' CSS style
|
||||
// shouldn't cause of HTML:a accessible recreation. The same time blur
|
||||
// makes its accessible to be recreated.
|
||||
gQueue.push(new focusAnchor("a"))
|
||||
gQueue.push(new tabAnchor("a2", "a"));
|
||||
// recreation (and fire show/hide events). For example, the focus and
|
||||
// blur of HTML:a with ':focus {overflow: scroll; }' CSS style causes its
|
||||
// accessible recreation. The focus event should be fired on new
|
||||
// accessible.
|
||||
gQueue.push(new focusAnchor("a"));
|
||||
gQueue.push(new tabAnchor("a2"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
@ -125,6 +114,11 @@
|
||||
title="mochitest for bug 413777: focus the a:focus {overflow: scroll;} shouldn't recreate HTML a accessible">
|
||||
Mozilla Bug 591163
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a><br>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
|
@ -40,31 +40,57 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var bulletText = String.fromCharCode(0x2022) + " ";
|
||||
const discBulletText = String.fromCharCode(0x2022) + " ";
|
||||
const circleBulletText = String.fromCharCode(0x25e6) + " ";
|
||||
const squareBulletText = String.fromCharCode(0x25aa) + " ";
|
||||
|
||||
// list1
|
||||
var accTree = {
|
||||
var discAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(bulletText, "Oranges"),
|
||||
new listItemTree(bulletText, "Apples"),
|
||||
new listItemTree(bulletText, "Bananas")
|
||||
new listItemTree(discBulletText, "Oranges"),
|
||||
new listItemTree(discBulletText, "Apples"),
|
||||
new listItemTree(discBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
testAccessibleTree("list1", accTree);
|
||||
testAccessibleTree("list1", discAccTree);
|
||||
|
||||
// list2
|
||||
accTree = {
|
||||
var circleAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(circleBulletText, "Oranges"),
|
||||
new listItemTree(circleBulletText, "Apples"),
|
||||
new listItemTree(circleBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
testAccessibleTree("list2", circleAccTree);
|
||||
|
||||
// list3
|
||||
var squareAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree(squareBulletText, "Oranges"),
|
||||
new listItemTree(squareBulletText, "Apples"),
|
||||
new listItemTree(squareBulletText, "Bananas")
|
||||
]
|
||||
};
|
||||
|
||||
testAccessibleTree("list3", squareAccTree);
|
||||
|
||||
// list4
|
||||
var nestedAccTree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
new listItemTree("1. ", "Oranges"),
|
||||
new listItemTree("2. ", "Apples"),
|
||||
new listItemTree("3. ", "Bananas", accTree)
|
||||
new listItemTree("3. ", "Bananas", circleAccTree)
|
||||
]
|
||||
};
|
||||
|
||||
testAccessibleTree("list2", accTree);
|
||||
testAccessibleTree("list4", nestedAccTree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
@ -80,18 +106,35 @@
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=342045">
|
||||
Mozilla Bug 342045
|
||||
</a>
|
||||
<a target="_blank"
|
||||
title="Bullets of nested not ordered lists have one and the same character."
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=604587">
|
||||
Mozilla Bug 604587
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<ul id="list1">
|
||||
<li id="li1">Oranges</li>
|
||||
<li id="li2">Apples</li>
|
||||
<li id="li3">Bananas</li>
|
||||
<li id="l1_li1">Oranges</li>
|
||||
<li id="l1_li2">Apples</li>
|
||||
<li id="l1_li3">Bananas</li>
|
||||
</ul>
|
||||
|
||||
<ol id="list2">
|
||||
<ul id="list2" style="list-style-type: circle">
|
||||
<li id="l2_li1">Oranges</li>
|
||||
<li id="l2_li2">Apples</li>
|
||||
<li id="l2_li3">Bananas</li>
|
||||
</ul>
|
||||
|
||||
<ul id="list3" style="list-style-type: square">
|
||||
<li id="l3_li1">Oranges</li>
|
||||
<li id="l3_li2">Apples</li>
|
||||
<li id="l3_li3">Bananas</li>
|
||||
</ul>
|
||||
|
||||
<ol id="list4">
|
||||
<li id="li4">Oranges</li>
|
||||
<li id="li5">Apples</li>
|
||||
<li id="li6">Bananas<ul>
|
||||
|
@ -70,6 +70,9 @@
|
||||
var tabsAccTree = {
|
||||
role: ROLE_PAGETABLIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll up button
|
||||
},
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: [
|
||||
@ -88,6 +91,9 @@
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll down button
|
||||
}
|
||||
]
|
||||
};
|
||||
|
56
accessible/tests/mochitest/treeupdate/Makefile.in
Normal file
56
accessible/tests/mochitest/treeupdate/Makefile.in
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = accessible/treeupdate
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_recreation.html \
|
||||
test_tableinsubtree.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
|
108
accessible/tests/mochitest/treeupdate/test_list_editabledoc.html
Normal file
108
accessible/tests/mochitest/treeupdate/test_list_editabledoc.html
Normal file
@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test HTML li and listitem bullet accessible insertion into editable document</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function addLi(aID)
|
||||
{
|
||||
this.listNode = getNode(aID);
|
||||
this.liNode = document.createElement("li");
|
||||
this.liNode.textContent = "item";
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getAccessible, this.liNode),
|
||||
new invokerChecker(EVENT_REORDER, this.listNode)
|
||||
];
|
||||
|
||||
this.invoke = function addLi_invoke()
|
||||
{
|
||||
this.listNode.appendChild(this.liNode);
|
||||
}
|
||||
|
||||
this.finalCheck = function addLi_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_LIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_LISTITEM,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_STATICTEXT,
|
||||
name: "1. ",
|
||||
children: []
|
||||
},
|
||||
{
|
||||
role: ROLE_TEXT_LEAF,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(aID, tree);
|
||||
}
|
||||
|
||||
this.getID = function addLi_getID()
|
||||
{
|
||||
return "add li";
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new addLi("list"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body contentEditable="true">
|
||||
|
||||
<a target="_blank"
|
||||
title="Wrong list bullet text of accessible for the first numbered HTML:li in CKEditor"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=557795">Mozilla Bug 557795</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<ol id="list">
|
||||
</ol>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
166
accessible/tests/mochitest/treeupdate/test_recreation.html
Normal file
166
accessible/tests/mochitest/treeupdate/test_recreation.html
Normal file
@ -0,0 +1,166 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Test accessible recreation</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function recreateAccessible(aID, aWontBeAccessible)
|
||||
{
|
||||
this.node = getNode(aID);
|
||||
this.accessible =
|
||||
isAccessible(this.node) ? getAccessible(this.node) : null;
|
||||
|
||||
this.eventSeq = [ ];
|
||||
|
||||
if (this.accessible)
|
||||
this.eventSeq.push(new invokerChecker(EVENT_HIDE,
|
||||
this.accessible));
|
||||
|
||||
if (!aWontBeAccessible)
|
||||
this.eventSeq.push(new invokerChecker(EVENT_SHOW, getAccessible,
|
||||
this.node));
|
||||
|
||||
this.eventSeq.push(new invokerChecker(EVENT_REORDER,
|
||||
getContainerAccessible(this.node)));
|
||||
|
||||
if (this.accessible) {
|
||||
this.unexpectedEventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.accessible)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
function changeAttr(aID, aAttr, aValue)
|
||||
{
|
||||
this.__proto__ = new recreateAccessible(aID);
|
||||
|
||||
this.invoke = function changeAttr_invoke()
|
||||
{
|
||||
this.node.setAttribute(aAttr, aValue);
|
||||
}
|
||||
|
||||
this.getID = function changeAttr_getID()
|
||||
{
|
||||
return "change " + aAttr + "attribute for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
function removeAttr(aID, aAttr)
|
||||
{
|
||||
this.__proto__ = new recreateAccessible(aID, true);
|
||||
|
||||
this.invoke = function remvoeAttr_invoke()
|
||||
{
|
||||
this.node.removeAttribute(aAttr);
|
||||
}
|
||||
|
||||
this.getID = function remvoeAttr_getID()
|
||||
{
|
||||
return "remove " + aAttr + "attribute for " + aID;
|
||||
}
|
||||
}
|
||||
|
||||
function changeRole(aID, aHasAccessible)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "role", "button");
|
||||
}
|
||||
|
||||
function removeRole(aID)
|
||||
{
|
||||
this.__proto__ = new removeAttr(aID, "role");
|
||||
}
|
||||
|
||||
function changeOnclick(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "onclick", "alert(3);");
|
||||
}
|
||||
|
||||
function changeHref(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "href", "www");
|
||||
}
|
||||
|
||||
function changeMultiselectable(aID)
|
||||
{
|
||||
this.__proto__ = new changeAttr(aID, "aria-multiselectable", "true");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// make the accessible an inaccessible
|
||||
gQueue.push(new changeRole("span"));
|
||||
|
||||
// make the inaccessible an accessible
|
||||
gQueue.push(new removeRole("span"));
|
||||
|
||||
// recreate an accessible by role change
|
||||
gQueue.push(new changeRole("div1"));
|
||||
|
||||
// recreate an accessible by onclick change
|
||||
gQueue.push(new changeOnclick("div2"));
|
||||
|
||||
// recreate an accessible by href change
|
||||
gQueue.push(new changeHref("anchor"));
|
||||
|
||||
// recreate an accessible by aria-multiselectable change
|
||||
gQueue.push(new changeMultiselectable("div3"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<span id="span">span</span>
|
||||
<div id="div1">div</div>
|
||||
<div id="div2">div</div>
|
||||
<a id="anchor">anchor</a>
|
||||
<div id="div3" role="listbox">list</div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
120
accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
Normal file
120
accessible/tests/mochitest/treeupdate/test_tableinsubtree.html
Normal file
@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Table creation in ARIA dialog test</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
function showARIADialog(aID)
|
||||
{
|
||||
this.node = getNode(aID);
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, this.node)
|
||||
];
|
||||
|
||||
this.invoke = function showARIADialog_invoke()
|
||||
{
|
||||
this.node.style.display = "block";
|
||||
getNode("input").value = "hello";
|
||||
getNode("cell").textContent = "cell1";
|
||||
getNode("input").focus();
|
||||
}
|
||||
|
||||
this.finalCheck = function showARIADialog_finalCheck()
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_DIALOG,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TABLE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
},
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_ENTRY } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(aID, tree);
|
||||
}
|
||||
|
||||
this.getID = function showARIADialog_getID()
|
||||
{
|
||||
return "show ARIA dialog";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
// make the accessible an inaccessible
|
||||
gQueue.push(new showARIADialog("dialog"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="dialog" role="dialog" style="display: none;">
|
||||
<table>
|
||||
<tr><td id="cell"></td><td><input id="input"></td>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
@ -330,6 +330,7 @@ pref("browser.search.log", false);
|
||||
// Ordering of Search Engines in the Engine list.
|
||||
pref("browser.search.order.1", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.2", "chrome://browser-region/locale/region.properties");
|
||||
pref("browser.search.order.3", "chrome://browser-region/locale/region.properties");
|
||||
|
||||
// search bar results always open in a new tab
|
||||
pref("browser.search.openintab", false);
|
||||
@ -490,8 +491,8 @@ pref("intl.menuitems.insertseparatorbeforeaccesskeys","chrome://global/locale/in
|
||||
// simple gestures support
|
||||
pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate");
|
||||
pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate");
|
||||
pref("browser.gesture.swipe.up", "cmd_scrollTop");
|
||||
pref("browser.gesture.swipe.down", "cmd_scrollBottom");
|
||||
pref("browser.gesture.swipe.up", "Browser:HideTabView");
|
||||
pref("browser.gesture.swipe.down", "Browser:ShowTabView");
|
||||
#ifdef XP_MACOSX
|
||||
pref("browser.gesture.pinch.latched", true);
|
||||
pref("browser.gesture.pinch.threshold", 150);
|
||||
@ -791,9 +792,9 @@ pref("browser.sessionstore.interval", 15000);
|
||||
pref("browser.sessionstore.postdata", 0);
|
||||
// on which sites to save text data, POSTDATA and cookies
|
||||
// 0 = everywhere, 1 = unencrypted sites, 2 = nowhere
|
||||
pref("browser.sessionstore.privacy_level", 1);
|
||||
pref("browser.sessionstore.privacy_level", 0);
|
||||
// the same as browser.sessionstore.privacy_level, but for saving deferred session data
|
||||
pref("browser.sessionstore.privacy_level_deferred", 2);
|
||||
pref("browser.sessionstore.privacy_level_deferred", 0);
|
||||
// how many tabs can be reopened (per window)
|
||||
pref("browser.sessionstore.max_tabs_undo", 10);
|
||||
// how many windows can be reopened (per session) - on non-OS X platforms this
|
||||
@ -802,7 +803,11 @@ pref("browser.sessionstore.max_windows_undo", 3);
|
||||
// number of crashes that can occur before the about:sessionrestore page is displayed
|
||||
// (this pref has no effect if more than 6 hours have passed since the last crash)
|
||||
pref("browser.sessionstore.max_resumed_crashes", 1);
|
||||
// number of tabs to restore concurrently
|
||||
// The number of tabs that can restore concurrently:
|
||||
// < 0 = All tabs can restore at the same time
|
||||
// 0 = Only the selected tab in each window will be restored
|
||||
// Other tabs won't be restored until they are selected
|
||||
// N = The number of tabs to restore at the same time
|
||||
pref("browser.sessionstore.max_concurrent_tabs", 3);
|
||||
|
||||
// allow META refresh by default
|
||||
@ -938,14 +943,12 @@ pref("toolbar.customization.usesheet", false);
|
||||
// The default for this pref reflects whether the build is capable of IPC.
|
||||
// (Turning it on in a no-IPC build will have no effect.)
|
||||
#ifdef XP_MACOSX
|
||||
// OSX still has only partial support for IPC. Note that the PowerPC
|
||||
// and x86 builds must generate identical copies of this file, so we
|
||||
// can't make the prefs indicate that IPC is not available at all in
|
||||
// PowerPC builds.
|
||||
pref("dom.ipc.plugins.enabled", false);
|
||||
// These plug-ins will run OOP by default
|
||||
pref("dom.ipc.plugins.enabled.flash player.plugin", true);
|
||||
pref("dom.ipc.plugins.enabled.javaplugin2_npapi.plugin", true);
|
||||
// i386 ipc preferences
|
||||
pref("dom.ipc.plugins.enabled.i386", false);
|
||||
pref("dom.ipc.plugins.enabled.i386.flash player.plugin", true);
|
||||
pref("dom.ipc.plugins.enabled.i386.javaplugin2_npapi.plugin", true);
|
||||
// x86_64 ipc preferences
|
||||
pref("dom.ipc.plugins.enabled.x86_64", true);
|
||||
#elifdef MOZ_IPC
|
||||
pref("dom.ipc.plugins.enabled", true);
|
||||
#else
|
||||
@ -962,7 +965,7 @@ pref("browser.taskbar.lists.frequent.enabled", true);
|
||||
pref("browser.taskbar.lists.recent.enabled", false);
|
||||
pref("browser.taskbar.lists.maxListItemCount", 7);
|
||||
pref("browser.taskbar.lists.tasks.enabled", true);
|
||||
pref("browser.taskbar.lists.refreshInSeconds", 30);
|
||||
pref("browser.taskbar.lists.refreshInSeconds", 120);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -1043,13 +1046,13 @@ pref("services.sync.prefs.sync.spellchecker.dictionary", true);
|
||||
pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
|
||||
#endif
|
||||
|
||||
// Disable the Error Console
|
||||
// Disable the error console and inspector
|
||||
pref("devtools.errorconsole.enabled", false);
|
||||
|
||||
// disable the Inspector
|
||||
pref("devtools.inspector.enabled", false);
|
||||
|
||||
// Whether the character encoding menu is under the main Firefox button. This
|
||||
// preference is a string so that localizers can alter it.
|
||||
pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
|
||||
|
||||
// Whether the Panorama should animate going in/out of tabs
|
||||
pref("browser.panorama.animate_zoom", true);
|
||||
|
@ -171,7 +171,7 @@ function showSnippets()
|
||||
let relocatedScript = document.createElement("script");
|
||||
relocatedScript.type = "text/javascript;version=1.8";
|
||||
relocatedScript.text = elt.text;
|
||||
snippetsElt.replaceChild(relocatedScript, elt);
|
||||
elt.parentNode.replaceChild(relocatedScript, elt);
|
||||
});
|
||||
snippetsElt.hidden = false;
|
||||
} else {
|
||||
|
@ -210,6 +210,7 @@
|
||||
accesskey="&viewMenu.accesskey;">
|
||||
<menupopup id="menu_viewPopup">
|
||||
<menuitem id="menu_tabview"
|
||||
key="key_tabview"
|
||||
label="&viewTabGroups.label;"
|
||||
accesskey="&viewTabGroups.accesskey;"
|
||||
command="Browser:ToggleTabView"/>
|
||||
|
@ -96,13 +96,33 @@ var StarUI = {
|
||||
if (aEvent.originalTarget == this.panel) {
|
||||
if (!this._element("editBookmarkPanelContent").hidden)
|
||||
this.quitEditMode();
|
||||
|
||||
this._restoreCommandsState();
|
||||
this._itemId = -1;
|
||||
this._uri = null;
|
||||
if (this._batching) {
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
this._batching = false;
|
||||
}
|
||||
|
||||
switch (this._actionOnHide) {
|
||||
case "cancel": {
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
break;
|
||||
}
|
||||
case "remove": {
|
||||
// Remove all bookmarks for the bookmark's url, this also removes
|
||||
// the tags for the url.
|
||||
PlacesUIUtils.ptm.beginBatch();
|
||||
let itemIds = PlacesUtils.getBookmarksForURI(this._uriForRemoval);
|
||||
for (let i = 0; i < itemIds.length; i++) {
|
||||
let txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
}
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this._actionOnHide = "";
|
||||
}
|
||||
break;
|
||||
case "keypress":
|
||||
@ -185,12 +205,9 @@ var StarUI = {
|
||||
gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle");
|
||||
|
||||
// No description; show the Done, Cancel;
|
||||
// hide the Edit, Undo buttons
|
||||
this._element("editBookmarkPanelDescription").textContent = "";
|
||||
this._element("editBookmarkPanelBottomButtons").hidden = false;
|
||||
this._element("editBookmarkPanelContent").hidden = false;
|
||||
this._element("editBookmarkPanelEditButton").hidden = true;
|
||||
this._element("editBookmarkPanelUndoRemoveButton").hidden = true;
|
||||
|
||||
// The remove button is shown only if we're not already batching, i.e.
|
||||
// if the cancel button/ESC does not remove the bookmark.
|
||||
@ -237,42 +254,6 @@ var StarUI = {
|
||||
}
|
||||
},
|
||||
|
||||
showPageBookmarkedNotification:
|
||||
function PCH_showPageBookmarkedNotification(aItemId, aAnchorElement, aPosition) {
|
||||
this._blockCommands(); // un-done in the popuphiding handler
|
||||
|
||||
var brandBundle = this._element("bundle_brand");
|
||||
var brandShortName = brandBundle.getString("brandShortName");
|
||||
|
||||
// "Page Bookmarked" title
|
||||
this._element("editBookmarkPanelTitle").value =
|
||||
gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle");
|
||||
|
||||
// description
|
||||
this._element("editBookmarkPanelDescription").textContent =
|
||||
gNavigatorBundle.getFormattedString("editBookmarkPanel.pageBookmarkedDescription",
|
||||
[brandShortName]);
|
||||
|
||||
// show the "Edit.." button and the Remove Bookmark button, hide the
|
||||
// undo-remove-bookmark button.
|
||||
this._element("editBookmarkPanelEditButton").hidden = false;
|
||||
this._element("editBookmarkPanelRemoveButton").hidden = false;
|
||||
this._element("editBookmarkPanelUndoRemoveButton").hidden = true;
|
||||
|
||||
// unset the unstarred state, if set
|
||||
this._element("editBookmarkPanelStarIcon").removeAttribute("unstarred");
|
||||
|
||||
this._itemId = aItemId !== undefined ? aItemId : this._itemId;
|
||||
if (this.panel.state == "closed") {
|
||||
// Consume dismiss clicks, see bug 400924
|
||||
this.panel.popupBoxObject
|
||||
.setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
|
||||
this.panel.openPopup(aAnchorElement, aPosition, -1, -1);
|
||||
}
|
||||
else
|
||||
this.panel.focus();
|
||||
},
|
||||
|
||||
quitEditMode: function SU_quitEditMode() {
|
||||
this._element("editBookmarkPanelContent").hidden = true;
|
||||
this._element("editBookmarkPanelBottomButtons").hidden = true;
|
||||
@ -284,67 +265,14 @@ var StarUI = {
|
||||
},
|
||||
|
||||
cancelButtonOnCommand: function SU_cancelButtonOnCommand() {
|
||||
// The order here is important! We have to hide the panel first, otherwise
|
||||
// changes done as part of Undo may change the panel contents and by
|
||||
// that force it to commit more transactions
|
||||
this._actionOnHide = "cancel";
|
||||
this.panel.hidePopup();
|
||||
this.endBatch();
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
},
|
||||
|
||||
removeBookmarkButtonCommand: function SU_removeBookmarkButtonCommand() {
|
||||
#ifdef ADVANCED_STARRING_UI
|
||||
// In minimal mode ("page bookmarked" notification), the bookmark
|
||||
// is removed and the panel is hidden immediately. In full edit mode,
|
||||
// a "Bookmark Removed" notification along with an Undo button is
|
||||
// shown
|
||||
if (this._batching) {
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
PlacesUIUtils.ptm.beginBatch(); // allow undo from within the notification
|
||||
|
||||
// "Bookmark Removed" title (the description field is already empty in
|
||||
// this mode)
|
||||
this._element("editBookmarkPanelTitle").value =
|
||||
gNavigatorBundle.getString("editBookmarkPanel.bookmarkedRemovedTitle");
|
||||
|
||||
// hide the edit panel
|
||||
this.quitEditMode();
|
||||
|
||||
// Hide the remove bookmark button, show the undo-remove-bookmark
|
||||
// button.
|
||||
this._element("editBookmarkPanelUndoRemoveButton").hidden = false;
|
||||
this._element("editBookmarkPanelRemoveButton").hidden = true;
|
||||
this._element("editBookmarkPanelStarIcon").setAttribute("unstarred", "true");
|
||||
this.panel.focus();
|
||||
}
|
||||
#endif
|
||||
|
||||
// cache its uri so we can get the new itemId in the case of undo
|
||||
this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
|
||||
|
||||
// remove all bookmarks for the bookmark's url, this also removes
|
||||
// the tags for the url
|
||||
var itemIds = PlacesUtils.getBookmarksForURI(this._uri);
|
||||
for (var i=0; i < itemIds.length; i++) {
|
||||
var txn = PlacesUIUtils.ptm.removeItem(itemIds[i]);
|
||||
PlacesUIUtils.ptm.doTransaction(txn);
|
||||
}
|
||||
|
||||
#ifdef ADVANCED_STARRING_UI
|
||||
// hidePopup resets our itemId, thus we call it only after removing
|
||||
// the bookmark
|
||||
if (!this._batching)
|
||||
#endif
|
||||
this.panel.hidePopup();
|
||||
},
|
||||
|
||||
undoRemoveBookmarkCommand: function SU_undoRemoveBookmarkCommand() {
|
||||
// restore the bookmark by undoing the last transaction and go back
|
||||
// to the edit state
|
||||
this.endBatch();
|
||||
PlacesUIUtils.ptm.undoTransaction();
|
||||
this._itemId = PlacesUtils.getMostRecentBookmarkForURI(this._uri);
|
||||
this.showEditBookmarkPopup();
|
||||
this._uriForRemoval = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
|
||||
this._actionOnHide = "remove";
|
||||
this.panel.hidePopup();
|
||||
},
|
||||
|
||||
beginBatch: function SU_beginBatch() {
|
||||
@ -352,13 +280,6 @@ var StarUI = {
|
||||
PlacesUIUtils.ptm.beginBatch();
|
||||
this._batching = true;
|
||||
}
|
||||
},
|
||||
|
||||
endBatch: function SU_endBatch() {
|
||||
if (this._batching) {
|
||||
PlacesUIUtils.ptm.endBatch();
|
||||
this._batching = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -429,10 +350,6 @@ var PlacesCommandHook = {
|
||||
var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_start' : 'after_end';
|
||||
if (aShowEditUI)
|
||||
StarUI.showEditBookmarkPopup(itemId, starIcon, position);
|
||||
#ifdef ADVANCED_STARRING_UI
|
||||
else
|
||||
StarUI.showPageBookmarkedNotification(itemId, starIcon, position);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -550,15 +467,6 @@ var PlacesCommandHook = {
|
||||
organizer.PlacesOrganizer.selectLeftPaneQuery(aLeftPaneRoot);
|
||||
organizer.focus();
|
||||
}
|
||||
},
|
||||
|
||||
deleteButtonOnCommand: function PCH_deleteButtonCommand() {
|
||||
PlacesUtils.bookmarks.removeItem(gEditItemOverlay.itemId);
|
||||
|
||||
// remove all tags for the associated url
|
||||
PlacesUtils.tagging.untagURI(gEditItemOverlay._uri, null);
|
||||
|
||||
this.panel.hidePopup();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1153,39 +1061,49 @@ let BookmarksMenuButton = {
|
||||
// handled in the onPopupShowing handler, so it does not hit Ts.
|
||||
},
|
||||
|
||||
_popupInitialized: false,
|
||||
_popupNeedsUpdating: true,
|
||||
_popupNeedsUpdate: {},
|
||||
onPopupShowing: function BMB_onPopupShowing(event) {
|
||||
if (!this._popupNeedsUpdating)
|
||||
// Don't handle events for submenus.
|
||||
if (event.target != event.currentTarget)
|
||||
return;
|
||||
this._popupNeedsUpdating = false;
|
||||
|
||||
let viewToolbar = document.getElementById("BMB_viewBookmarksToolbar");
|
||||
if (!this._popupInitialized) {
|
||||
// First popupshowing event, initialize immutable attributes.
|
||||
this._popupInitialized = true;
|
||||
let popup = event.target;
|
||||
let needsUpdate = this._popupNeedsUpdate[popup.id];
|
||||
|
||||
// Check if popup contents need to be updated. Note that if needsUpdate is
|
||||
// undefined we have never seen the popup, thus it should be updated.
|
||||
if (needsUpdate === false)
|
||||
return;
|
||||
this._popupNeedsUpdate[popup.id] = false;
|
||||
|
||||
function getPlacesAnonymousElement(aAnonId)
|
||||
document.getAnonymousElementByAttribute(popup.parentNode,
|
||||
"placesanonid",
|
||||
aAnonId);
|
||||
|
||||
let viewToolbarMenuitem = getPlacesAnonymousElement("view-toolbar");
|
||||
if (viewToolbarMenuitem) {
|
||||
// Update View bookmarks toolbar checkbox menuitem.
|
||||
viewToolbar.setAttribute("toolbarId", this.personalToolbar.id);
|
||||
|
||||
// Need to set the label on Unsorted Bookmarks menu.
|
||||
let unsortedBookmarksElt =
|
||||
document.getElementById("BMB_unsortedBookmarksFolderMenu");
|
||||
unsortedBookmarksElt.label =
|
||||
PlacesUtils.getString("UnsortedBookmarksFolderTitle");
|
||||
viewToolbarMenuitem.setAttribute("checked",
|
||||
!this.personalToolbar.collapsed);
|
||||
}
|
||||
|
||||
// Update View Bookmarks Toolbar checkbox menuitem.
|
||||
viewToolbar.setAttribute("checked", !this.personalToolbar.collapsed);
|
||||
|
||||
// Hide Bookmarks Toolbar menu if the button is next to the bookmarks
|
||||
// toolbar item, show them otherwise.
|
||||
let button = this.button;
|
||||
document.getElementById("BMB_bookmarksToolbarFolderMenu").collapsed =
|
||||
button && button.parentNode == this.bookmarksToolbarItem;
|
||||
let toolbarMenuitem = getPlacesAnonymousElement("toolbar-autohide");
|
||||
if (toolbarMenuitem) {
|
||||
// If bookmarks items are visible, hide Bookmarks Toolbar menu and the
|
||||
// separator after it.
|
||||
toolbarMenuitem.collapsed = toolbarMenuitem.nextSibling.collapsed =
|
||||
isElementVisible(this.bookmarksToolbarItem);
|
||||
}
|
||||
},
|
||||
|
||||
updatePosition: function BMB_updatePosition() {
|
||||
this._popupNeedsUpdating = true;
|
||||
// Popups will have to be updated when the user customizes the UI, or
|
||||
// changes personal toolbar collapsed status. Both of those location call
|
||||
// updatePosition(), so this is the only point asking for popup updates.
|
||||
for (let popupId in this._popupNeedsUpdate) {
|
||||
this._popupNeedsUpdate[popupId] = true;
|
||||
}
|
||||
|
||||
let button = this.button;
|
||||
if (!button)
|
||||
|
@ -117,6 +117,8 @@
|
||||
<command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/>
|
||||
<command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/>
|
||||
<command id="Browser:ToggleTabView" oncommand="TabView.toggle();"/>
|
||||
<command id="Browser:ShowTabView" oncommand="TabView.show();"/>
|
||||
<command id="Browser:HideTabView" oncommand="TabView.hide();"/>
|
||||
<command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/>
|
||||
<command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
|
||||
<command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/>
|
||||
@ -216,9 +218,9 @@
|
||||
#
|
||||
# Unix: Ctrl+K (cross platform binding)
|
||||
# Ctrl+J (in case of emacs Ctrl-K conflict)
|
||||
# Mac: Ctrl+K (cross platform binding)
|
||||
# Mac: Cmd+K (cross platform binding)
|
||||
# Cmd+Opt+F (platform convention)
|
||||
# Win: Ctrl+K (cross platform binding)
|
||||
# Ctrl+E (IE compat)
|
||||
#
|
||||
# We support Ctrl+K on all platforms now and advertise it in the menu since it is
|
||||
# our standard - it is a "safe" choice since it is near no harmful keys like "W" as
|
||||
@ -231,9 +233,6 @@
|
||||
#ifdef XP_MACOSX
|
||||
<key id="key_search2" key="&findOnCmd.commandkey;" command="Tools:Search" modifiers="accel,alt"/>
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
<key id="key_search2" key="&searchFocus.commandkey2;" command="Tools:Search" modifiers="accel"/>
|
||||
#endif
|
||||
#ifdef XP_GNOME
|
||||
<key id="key_search2" key="&searchFocusUnix.commandkey;" command="Tools:Search" modifiers="accel"/>
|
||||
<key id="key_openDownloads" key="&downloadsUnix.commandkey;" command="Tools:Downloads" modifiers="accel,shift"/>
|
||||
@ -348,6 +347,8 @@
|
||||
|
||||
<key id="key_switchTextDirection" key="&bidiSwitchTextDirectionItem.commandkey;" command="cmd_switchTextDirection" modifiers="accel,shift" />
|
||||
|
||||
<key id="key_tabview" key="&tabView.commandkey;" command="Browser:ToggleTabView" modifiers="accel"/>
|
||||
|
||||
<key id="key_privatebrowsing" command="Tools:PrivateBrowsing" key="&privateBrowsingCmd.commandkey;" modifiers="accel,shift"/>
|
||||
<key id="key_sanitize" command="Tools:Sanitize" keycode="VK_DELETE" modifiers="accel,shift"/>
|
||||
#ifdef XP_MACOSX
|
||||
|
@ -195,7 +195,7 @@ let gSyncUI = {
|
||||
let buttons = [new Weave.NotificationButton(
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.label"),
|
||||
this._stringBundle.GetStringFromName("error.sync.serverStatusButton.accesskey"),
|
||||
function() { gWeaveWin.openServerStatus(); return true; }
|
||||
function() { gSyncUI.openServerStatus(); return true; }
|
||||
)];
|
||||
let notification = new Weave.Notification(
|
||||
title, description, null, Weave.Notifications.PRIORITY_INFO, buttons);
|
||||
|
@ -212,47 +212,6 @@ let TabView = {
|
||||
return;
|
||||
|
||||
let charCode = event.charCode;
|
||||
#ifdef XP_MACOSX
|
||||
// if a text box in a webpage has the focus, the event.altKey would
|
||||
// return false so we are depending on the charCode here.
|
||||
if (!event.ctrlKey && !event.metaKey && !event.shiftKey &&
|
||||
charCode == 160) { // alt + space
|
||||
#else
|
||||
if (event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey &&
|
||||
charCode == KeyEvent.DOM_VK_SPACE) { // ctrl + space
|
||||
#endif
|
||||
|
||||
// Don't handle this event if it's coming from a node that might allow
|
||||
// multiple keyboard selection like selects or trees
|
||||
let node = event.target;
|
||||
switch (node.namespaceURI) {
|
||||
case "http://www.w3.org/1999/xhtml":
|
||||
// xhtml:select only allows multiple when the attr is set
|
||||
if (node.localName == "select" && node.hasAttribute("multiple"))
|
||||
return;
|
||||
break;
|
||||
|
||||
case "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul":
|
||||
switch (node.localName) {
|
||||
case "listbox":
|
||||
// xul:listbox is by default single
|
||||
if (node.getAttribute("seltype") == "multiple")
|
||||
return;
|
||||
break;
|
||||
case "tree":
|
||||
// xul:tree is by default multiple
|
||||
if (node.getAttribute("seltype") != "single")
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
self.show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Control (+ Shift) + `
|
||||
if (event.ctrlKey && !event.metaKey && !event.altKey &&
|
||||
(charCode == 96 || charCode == 126)) {
|
||||
|
@ -37,14 +37,14 @@ tabbrowser {
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
.tab-progress:not([fadein]):not([pinned]),
|
||||
.tab-throbber:not([fadein]):not([pinned]),
|
||||
.tab-label:not([fadein]):not([pinned]),
|
||||
.tab-icon-image:not([fadein]):not([pinned]),
|
||||
.tab-close-button:not([fadein]):not([pinned]) {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.tab-progress,
|
||||
.tab-throbber,
|
||||
.tab-label,
|
||||
.tab-icon-image,
|
||||
.tab-close-button {
|
||||
@ -106,6 +106,14 @@ toolbar[mode="icons"] > #reload-button[displaystop] {
|
||||
visibility: collapse;
|
||||
}
|
||||
|
||||
#feed-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#feed-menu > .feed-menuitem:-moz-locale-dir(rtl) {
|
||||
direction: rtl;
|
||||
}
|
||||
|
||||
#main-window:-moz-lwtheme {
|
||||
background-repeat: no-repeat;
|
||||
background-position: top right;
|
||||
@ -146,10 +154,6 @@ toolbar[mode="icons"] > #reload-button[displaystop] {
|
||||
-moz-binding: url(chrome://browser/content/urlbarBindings.xml#urlbar);
|
||||
}
|
||||
|
||||
#urlbar-progress {
|
||||
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter");
|
||||
}
|
||||
|
||||
/* Some child nodes want to be ordered based on the locale's direction, while
|
||||
everything else should be ltr. */
|
||||
.urlbar-input-box:-moz-locale-dir(rtl) {
|
||||
@ -162,15 +166,6 @@ html|*.urlbar-input {
|
||||
|
||||
/* over-link in location bar */
|
||||
|
||||
/* Delay transitions on mouseout. (Mouseover transitions are delayed by a
|
||||
timeout in urlbarBindings.xml.) */
|
||||
.urlbar-textbox-container:not([overlinkstate]),
|
||||
.urlbar-over-link-layer:not([overlinkstate]),
|
||||
.urlbar-textbox-container-children:not([overlinkstate]),
|
||||
.urlbar-over-link-box:not([overlinkstate]) {
|
||||
-moz-transition-delay: 100ms;
|
||||
}
|
||||
|
||||
.urlbar-over-link-layer[overlinkstate="fade-in"],
|
||||
.urlbar-textbox-container:not([overlinkstate]) {
|
||||
-moz-transition-property: color;
|
||||
@ -267,9 +262,7 @@ richlistitem[type~="action"]:-moz-locale-dir(rtl) > .ac-url-box {
|
||||
|
||||
/* ::::: Unified Back-/Forward Button ::::: */
|
||||
#back-button > .toolbarbutton-menu-dropmarker,
|
||||
#forward-button > .toolbarbutton-menu-dropmarker,
|
||||
#back-forward-dropmarker > .toolbarbutton-icon,
|
||||
#back-forward-dropmarker > .toolbarbutton-text {
|
||||
#forward-button > .toolbarbutton-menu-dropmarker {
|
||||
display: none;
|
||||
}
|
||||
.unified-nav-current {
|
||||
|
@ -253,7 +253,6 @@ function UpdateBackForwardCommands(aWebNavigation) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
/**
|
||||
* Click-and-Hold implementation for the Back and Forward buttons
|
||||
* XXXmano: should this live in toolbarbutton.xml?
|
||||
@ -310,8 +309,8 @@ function SetClickAndHoldHandlers() {
|
||||
// the forward buttons.
|
||||
var unifiedButton = document.getElementById("unified-back-forward-button");
|
||||
if (unifiedButton && !unifiedButton._clickHandlersAttached) {
|
||||
var popup = document.getElementById("back-forward-dropmarker")
|
||||
.firstChild.cloneNode(true);
|
||||
var popup = document.getElementById("backForwardMenu").cloneNode(true);
|
||||
popup.removeAttribute("id");
|
||||
var backButton = document.getElementById("back-button");
|
||||
backButton.setAttribute("type", "menu");
|
||||
backButton.appendChild(popup);
|
||||
@ -324,7 +323,6 @@ function SetClickAndHoldHandlers() {
|
||||
unifiedButton._clickHandlersAttached = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const gSessionHistoryObserver = {
|
||||
observe: function(subject, topic, data)
|
||||
@ -789,7 +787,6 @@ const gFormSubmitObserver = {
|
||||
init: function()
|
||||
{
|
||||
this.panel = document.getElementById('invalid-form-popup');
|
||||
this.panel.appendChild(document.createTextNode(""));
|
||||
},
|
||||
|
||||
panelIsOpen: function()
|
||||
@ -823,7 +820,7 @@ const gFormSubmitObserver = {
|
||||
}
|
||||
|
||||
// Limit the message to 256 characters.
|
||||
this.panel.firstChild.nodeValue = element.validationMessage.substring(0, 256);
|
||||
this.panel.firstChild.textContent = element.validationMessage.substring(0, 256);
|
||||
|
||||
element.focus();
|
||||
|
||||
@ -1462,12 +1459,10 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
||||
document.getElementById("textfieldDirection-swap").hidden = false;
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Setup click-and-hold gestures access to the session history
|
||||
// menus if global click-and-hold isn't turned on
|
||||
if (!getBoolPref("ui.click_hold_context_menus", false))
|
||||
SetClickAndHoldHandlers();
|
||||
#endif
|
||||
|
||||
// Initialize the full zoom setting.
|
||||
// We do this before the session restore service gets initialized so we can
|
||||
@ -1536,11 +1531,6 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
// Delayed initialization of PlacesDBUtils.
|
||||
// This component checks for database coherence once per day, on
|
||||
// an idle timer, taking corrective actions where needed.
|
||||
setTimeout(function() PlacesUtils.startPlacesDBUtils(), 15000);
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
updateEditUIVisibility();
|
||||
let placesContext = document.getElementById("placesContext");
|
||||
@ -1582,7 +1572,8 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
||||
}
|
||||
|
||||
// Enable Error Console?
|
||||
let consoleEnabled = gPrefService.getBoolPref("devtools.errorconsole.enabled");
|
||||
// XXX Temporarily always-enabled, see bug 601201
|
||||
let consoleEnabled = true || gPrefService.getBoolPref("devtools.errorconsole.enabled");
|
||||
if (consoleEnabled) {
|
||||
document.getElementById("javascriptConsole").hidden = false;
|
||||
document.getElementById("key_errorConsole").removeAttribute("disabled");
|
||||
@ -3491,12 +3482,6 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
|
||||
gIdentityHandler._cacheElements();
|
||||
window.XULBrowserWindow.init();
|
||||
|
||||
var backForwardDropmarker = document.getElementById("back-forward-dropmarker");
|
||||
if (backForwardDropmarker)
|
||||
backForwardDropmarker.disabled =
|
||||
document.getElementById('Browser:Back').hasAttribute('disabled') &&
|
||||
document.getElementById('Browser:Forward').hasAttribute('disabled');
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
updateEditUIVisibility();
|
||||
#endif
|
||||
@ -3523,15 +3508,11 @@ function BrowserToolboxCustomizeDone(aToolboxChanged) {
|
||||
var cmd = document.getElementById("cmd_CustomizeToolbars");
|
||||
cmd.removeAttribute("disabled");
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// make sure to re-enable click-and-hold
|
||||
if (!getBoolPref("ui.click_hold_context_menus", false))
|
||||
SetClickAndHoldHandlers();
|
||||
#endif
|
||||
|
||||
// XXX Shouldn't have to do this, but I do
|
||||
if (!gCustomizeSheet)
|
||||
window.focus();
|
||||
window.content.focus();
|
||||
}
|
||||
|
||||
function BrowserToolboxCustomizeChange() {
|
||||
@ -3652,7 +3633,7 @@ var FullScreen = {
|
||||
// The user may quit fullscreen during an animation
|
||||
clearInterval(this._animationInterval);
|
||||
clearTimeout(this._animationTimeout);
|
||||
gNavToolbox.style.marginTop = "0px";
|
||||
gNavToolbox.style.marginTop = "";
|
||||
if (this._isChromeCollapsed)
|
||||
this.mouseoverToggle(true);
|
||||
this._isAnimating = false;
|
||||
@ -3785,7 +3766,7 @@ var FullScreen = {
|
||||
if (animateFrameAmount >= gNavToolbox.boxObject.height) {
|
||||
// We've animated enough
|
||||
clearInterval(FullScreen._animationInterval);
|
||||
gNavToolbox.style.marginTop = "0px";
|
||||
gNavToolbox.style.marginTop = "";
|
||||
FullScreen._isAnimating = false;
|
||||
FullScreen._shouldAnimate = false; // Just to make sure
|
||||
FullScreen.mouseoverToggle(false);
|
||||
@ -3940,8 +3921,6 @@ var XULBrowserWindow = {
|
||||
statusText: "",
|
||||
isBusy: false,
|
||||
|
||||
_progressCollapseTimer: 0,
|
||||
|
||||
QueryInterface: function (aIID) {
|
||||
if (aIID.equals(Ci.nsIWebProgressListener) ||
|
||||
aIID.equals(Ci.nsIWebProgressListener2) ||
|
||||
@ -3952,10 +3931,6 @@ var XULBrowserWindow = {
|
||||
throw Cr.NS_NOINTERFACE;
|
||||
},
|
||||
|
||||
get statusMeter () {
|
||||
delete this.statusMeter;
|
||||
return this.statusMeter = document.getElementById("urlbar-progress");
|
||||
},
|
||||
get stopCommand () {
|
||||
delete this.stopCommand;
|
||||
return this.stopCommand = document.getElementById("Browser:Stop");
|
||||
@ -3987,7 +3962,6 @@ var XULBrowserWindow = {
|
||||
destroy: function () {
|
||||
// XXXjag to avoid leaks :-/, see bug 60729
|
||||
delete this.throbberElement;
|
||||
delete this.statusMeter;
|
||||
delete this.stopCommand;
|
||||
delete this.reloadCommand;
|
||||
delete this.statusText;
|
||||
@ -4021,15 +3995,7 @@ var XULBrowserWindow = {
|
||||
onProgressChange: function (aWebProgress, aRequest,
|
||||
aCurSelfProgress, aMaxSelfProgress,
|
||||
aCurTotalProgress, aMaxTotalProgress) {
|
||||
// Check this._busyUI to be safe, because we don't want to update
|
||||
// the progress meter when restoring a page from bfcache.
|
||||
if (aMaxTotalProgress > 0 && this._busyUI) {
|
||||
// This is highly optimized. Don't touch this code unless
|
||||
// you are intimately familiar with the cost of setting
|
||||
// attrs on XUL elements. -- hyatt
|
||||
let percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
|
||||
this.statusMeter.value = percentage;
|
||||
}
|
||||
// Do nothing.
|
||||
},
|
||||
|
||||
onProgressChange64: function (aWebProgress, aRequest,
|
||||
@ -4059,15 +4025,6 @@ var XULBrowserWindow = {
|
||||
if (this.throbberElement)
|
||||
this.throbberElement.setAttribute("busy", "true");
|
||||
|
||||
// Turn the status meter on.
|
||||
this.statusMeter.value = 0; // be sure to clear the progress bar
|
||||
if (this._progressCollapseTimer) {
|
||||
clearTimeout(this._progressCollapseTimer);
|
||||
this._progressCollapseTimer = 0;
|
||||
}
|
||||
else
|
||||
this.statusMeter.collapsed = false;
|
||||
|
||||
// XXX: This needs to be based on window activity...
|
||||
this.stopCommand.removeAttribute("disabled");
|
||||
CombinedStopReload.switchToStop();
|
||||
@ -4128,12 +4085,7 @@ var XULBrowserWindow = {
|
||||
if (this._busyUI) {
|
||||
this._busyUI = false;
|
||||
|
||||
// Turn the progress meter and throbber off.
|
||||
this._progressCollapseTimer = setTimeout(function (self) {
|
||||
self.statusMeter.collapsed = true;
|
||||
self._progressCollapseTimer = 0;
|
||||
}, 100, this);
|
||||
|
||||
// Turn the throbber off.
|
||||
if (this.throbberElement)
|
||||
this.throbberElement.removeAttribute("busy");
|
||||
|
||||
@ -4275,14 +4227,12 @@ var XULBrowserWindow = {
|
||||
|
||||
// Properties used to cache security state used to update the UI
|
||||
_state: null,
|
||||
_tooltipText: null,
|
||||
_hostChanged: false, // onLocationChange will flip this bit
|
||||
|
||||
onSecurityChange: function (aWebProgress, aRequest, aState) {
|
||||
// Don't need to do anything if the data we use to update the UI hasn't
|
||||
// changed
|
||||
if (this._state == aState &&
|
||||
this._tooltipText == gBrowser.securityUI.tooltipText &&
|
||||
!this._hostChanged) {
|
||||
#ifdef DEBUG
|
||||
try {
|
||||
@ -4308,7 +4258,6 @@ var XULBrowserWindow = {
|
||||
#endif
|
||||
|
||||
this._hostChanged = false;
|
||||
this._tooltipText = gBrowser.securityUI.tooltipText
|
||||
|
||||
// aState is defined as a bitmask that may be extended in the future.
|
||||
// We filter out any unknown bits before testing for known values.
|
||||
@ -4380,7 +4329,6 @@ var XULBrowserWindow = {
|
||||
if (loadingDone)
|
||||
return;
|
||||
this.onStatusChange(gBrowser.webProgress, null, 0, aMessage);
|
||||
this.onProgressChange(gBrowser.webProgress, 0, 0, aTotalProgress, 1);
|
||||
},
|
||||
|
||||
startDocumentLoad: function XWB_startDocumentLoad(aRequest) {
|
||||
@ -4469,19 +4417,26 @@ var CombinedStopReload = {
|
||||
if (!this._initialized)
|
||||
return;
|
||||
|
||||
this.reload.removeAttribute("displaystop");
|
||||
|
||||
if (!aDelay || this._stopClicked) {
|
||||
this._stopClicked = false;
|
||||
this._cancelTransition();
|
||||
this.reload.removeAttribute("displaystop");
|
||||
this.reload.disabled = XULBrowserWindow.reloadCommand
|
||||
.getAttribute("disabled") == "true";
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._timer)
|
||||
return;
|
||||
|
||||
// Temporarily disable the reload button to prevent the user from
|
||||
// accidentally reloading the page when intending to click the stop button
|
||||
this.reload.disabled = true;
|
||||
this._timer = setTimeout(function (self) {
|
||||
self._timer = 0;
|
||||
self.reload.removeAttribute("displaystop");
|
||||
self.reload.disabled = XULBrowserWindow.reloadCommand
|
||||
.getAttribute("disabled") == "true";
|
||||
}, 650, this);
|
||||
},
|
||||
|
||||
@ -4512,7 +4467,7 @@ var TabsProgressListener = {
|
||||
// document URI is not yet the about:-uri of the error page.
|
||||
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
|
||||
/^about:/.test(aBrowser.contentWindow.document.documentURI)) {
|
||||
/^about:/.test(aWebProgress.DOMWindow.document.documentURI)) {
|
||||
aBrowser.addEventListener("click", BrowserOnClick, false);
|
||||
aBrowser.addEventListener("pagehide", function () {
|
||||
aBrowser.removeEventListener("click", BrowserOnClick, false);
|
||||
@ -4664,10 +4619,8 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
||||
if (popup != aEvent.currentTarget)
|
||||
return;
|
||||
|
||||
var i;
|
||||
|
||||
// Empty the menu
|
||||
for (i = popup.childNodes.length-1; i >= 0; --i) {
|
||||
for (var i = popup.childNodes.length-1; i >= 0; --i) {
|
||||
var deadItem = popup.childNodes[i];
|
||||
if (deadItem.hasAttribute("toolbarId"))
|
||||
popup.removeChild(deadItem);
|
||||
@ -4675,9 +4628,9 @@ function onViewToolbarsPopupShowing(aEvent, aInsertPoint) {
|
||||
|
||||
var firstMenuItem = aInsertPoint || popup.firstChild;
|
||||
|
||||
let toolbarNodes = [document.getElementById("addon-bar")];
|
||||
for (i = 0; i < gNavToolbox.childNodes.length; ++i)
|
||||
toolbarNodes.push(gNavToolbox.childNodes[i]);
|
||||
let toolbarNodes = Array.slice(gNavToolbox.childNodes);
|
||||
toolbarNodes.push(document.getElementById("addon-bar"));
|
||||
|
||||
toolbarNodes.forEach(function(toolbar) {
|
||||
var toolbarName = toolbar.getAttribute("toolbarname");
|
||||
if (toolbarName) {
|
||||
@ -5138,54 +5091,28 @@ function asyncOpenWebPanel(event)
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLinkClick(event, href, linkNode)
|
||||
{
|
||||
function handleLinkClick(event, href, linkNode) {
|
||||
if (event.button == 2) // right click
|
||||
return false;
|
||||
|
||||
var where = whereToOpenLink(event);
|
||||
if (where == "current")
|
||||
return false;
|
||||
|
||||
var doc = event.target.ownerDocument;
|
||||
|
||||
switch (event.button) {
|
||||
case 0: // if left button clicked
|
||||
#ifdef XP_MACOSX
|
||||
if (event.metaKey) { // Cmd
|
||||
#else
|
||||
if (event.ctrlKey) {
|
||||
#endif
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.shiftKey && event.altKey) {
|
||||
var feedService =
|
||||
Cc["@mozilla.org/browser/feeds/result-service;1"].
|
||||
getService(Ci.nsIFeedResultService);
|
||||
feedService.forcePreviewPage = true;
|
||||
loadURI(href, null, null, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.altKey) {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
case 1: // if middle button clicked
|
||||
var tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick");
|
||||
if (tab)
|
||||
openNewTabWith(href, doc, null, event, false);
|
||||
else
|
||||
openNewWindowWith(href, doc, null, false);
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
if (where == "save") {
|
||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||
true, doc.documentURIObject);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
urlSecurityCheck(href, doc.nodePrincipal);
|
||||
openLinkIn(href, where, { fromContent: true,
|
||||
referrerURI: doc.documentURIObject,
|
||||
charset: doc.characterSet });
|
||||
event.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
|
||||
function middleMousePaste(event) {
|
||||
@ -5779,7 +5706,7 @@ var OfflineApps = {
|
||||
|
||||
var updateService = Cc["@mozilla.org/offlinecacheupdate-service;1"].
|
||||
getService(Ci.nsIOfflineCacheUpdateService);
|
||||
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject);
|
||||
updateService.scheduleUpdate(manifestURI, aDocument.documentURIObject, window);
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -5900,6 +5827,11 @@ var IndexedDBPromptHelper = {
|
||||
|
||||
function WindowIsClosing()
|
||||
{
|
||||
if (TabView.isVisible()) {
|
||||
TabView.hide();
|
||||
return false;
|
||||
}
|
||||
|
||||
var reallyClose = closeWindow(false, warnAboutClosingWindow);
|
||||
if (!reallyClose)
|
||||
return false;
|
||||
@ -6603,7 +6535,22 @@ function convertFromUnicode(charset, str)
|
||||
*/
|
||||
var FeedHandler = {
|
||||
/**
|
||||
* Called when the user clicks on the Subscribe to This Page... menu item.
|
||||
* The click handler for the Feed icon in the toolbar. Opens the
|
||||
* subscription page if user is not given a choice of feeds.
|
||||
* (Otherwise the list of available feeds will be presented to the
|
||||
* user in a popup menu.)
|
||||
*/
|
||||
onFeedButtonClick: function(event) {
|
||||
event.stopPropagation();
|
||||
|
||||
if (event.target.hasAttribute("feed") &&
|
||||
event.eventPhase == Event.AT_TARGET &&
|
||||
(event.button == 0 || event.button == 1)) {
|
||||
this.subscribeToFeed(null, event);
|
||||
}
|
||||
},
|
||||
|
||||
/** Called when the user clicks on the Subscribe to This Page... menu item.
|
||||
* Builds a menu of unique feeds associated with the page, and if there
|
||||
* is only one, shows the feed inline in the browser window.
|
||||
* @param menuPopup
|
||||
@ -6628,6 +6575,13 @@ var FeedHandler = {
|
||||
while (menuPopup.firstChild)
|
||||
menuPopup.removeChild(menuPopup.firstChild);
|
||||
|
||||
if (feeds.length == 1) {
|
||||
var feedButton = document.getElementById("feed-button");
|
||||
if (feedButton)
|
||||
feedButton.setAttribute("feed", feeds[0].href);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build the menu showing the available feed choices for viewing.
|
||||
for (var i = 0; i < feeds.length; ++i) {
|
||||
var feedInfo = feeds[i];
|
||||
@ -6699,16 +6653,30 @@ var FeedHandler = {
|
||||
* a page is loaded or the user switches tabs to a page that has feeds.
|
||||
*/
|
||||
updateFeeds: function() {
|
||||
var feedButton = document.getElementById("feed-button");
|
||||
|
||||
var feeds = gBrowser.selectedBrowser.feeds;
|
||||
if (!feeds || feeds.length == 0) {
|
||||
if (feedButton) {
|
||||
feedButton.disabled = true;
|
||||
feedButton.removeAttribute("feed");
|
||||
}
|
||||
this._feedMenuitem.setAttribute("disabled", "true");
|
||||
this._feedMenupopup.setAttribute("hidden", "true");
|
||||
this._feedMenuitem.removeAttribute("hidden");
|
||||
} else {
|
||||
if (feedButton)
|
||||
feedButton.disabled = false;
|
||||
|
||||
if (feeds.length > 1) {
|
||||
this._feedMenuitem.setAttribute("hidden", "true");
|
||||
this._feedMenupopup.removeAttribute("hidden");
|
||||
if (feedButton)
|
||||
feedButton.removeAttribute("feed");
|
||||
} else {
|
||||
if (feedButton)
|
||||
feedButton.setAttribute("feed", feeds[0].href);
|
||||
|
||||
this._feedMenuitem.setAttribute("feed", feeds[0].href);
|
||||
this._feedMenuitem.removeAttribute("disabled");
|
||||
this._feedMenuitem.removeAttribute("hidden");
|
||||
@ -6729,6 +6697,12 @@ var FeedHandler = {
|
||||
browserForLink.feeds = [];
|
||||
|
||||
browserForLink.feeds.push({ href: link.href, title: link.title });
|
||||
|
||||
if (browserForLink == gBrowser.selectedBrowser) {
|
||||
var feedButton = document.getElementById("feed-button");
|
||||
if (feedButton)
|
||||
feedButton.collapsed = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -7932,11 +7906,14 @@ var TabContextMenu = {
|
||||
let unpinnedTabs = gBrowser.visibleTabs.length - gBrowser._numPinnedTabs;
|
||||
document.getElementById("context_closeOtherTabs").disabled = unpinnedTabs <= 1;
|
||||
document.getElementById("context_closeOtherTabs").hidden = this.contextTab.pinned;
|
||||
|
||||
// Disable "Move to Group" if it's a pinned tab.
|
||||
document.getElementById("context_tabViewMenu").disabled = this.contextTab.pinned;
|
||||
}
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "HUDConsoleUI", function () {
|
||||
Cu.import("resource://gre/modules/HUDService.jsm");
|
||||
Cu.import("resource:///modules/HUDService.jsm");
|
||||
try {
|
||||
return HUDService.consoleUI;
|
||||
}
|
||||
|
@ -152,9 +152,11 @@
|
||||
oncommand="gBrowser.removeTab(TabContextMenu.contextTab, { animate: true });"/>
|
||||
</menupopup>
|
||||
|
||||
<!-- bug 415444/582485: event.stopPropagation is here for the cloned version
|
||||
of this menupopup -->
|
||||
<menupopup id="backForwardMenu"
|
||||
onpopupshowing="return FillHistoryMenu(event.target);"
|
||||
oncommand="gotoHistoryIndex(event);"
|
||||
oncommand="gotoHistoryIndex(event); event.stopPropagation();"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<tooltip id="aHTMLTooltip" onpopupshowing="return FillInHTMLTooltip(document.tooltipNode);"/>
|
||||
|
||||
@ -165,7 +167,9 @@
|
||||
<panel type="autocomplete-richlistbox" id="PopupAutoCompleteRichResult" noautofocus="true" hidden="true"/>
|
||||
|
||||
<!-- for invalid form error message -->
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent"/>
|
||||
<panel id="invalid-form-popup" noautofocus="true" hidden="true" level="parent">
|
||||
<description/>
|
||||
</panel>
|
||||
|
||||
<panel id="editBookmarkPanel"
|
||||
orient="vertical"
|
||||
@ -181,21 +185,10 @@
|
||||
<label id="editBookmarkPanelTitle"/>
|
||||
<description id="editBookmarkPanelDescription"/>
|
||||
<hbox>
|
||||
<button id="editBookmarkPanelUndoRemoveButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
hidden="true"
|
||||
oncommand="StarUI.undoRemoveBookmarkCommand();"
|
||||
label="&editBookmark.undo.label;"
|
||||
accesskey="&editBookmark.undo.accessKey;"/>
|
||||
<button id="editBookmarkPanelRemoveButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
oncommand="StarUI.removeBookmarkButtonCommand();"
|
||||
accesskey="&editBookmark.removeBookmark.accessKey;"/>
|
||||
<button id="editBookmarkPanelEditButton"
|
||||
class="editBookmarkPanelHeaderButton"
|
||||
oncommand="StarUI.editButtonCommand();"
|
||||
label="&editBookmark.edit.label;"
|
||||
accesskey="&editBookmark.edit.accessKey;"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</row>
|
||||
@ -338,7 +331,7 @@
|
||||
|
||||
<menupopup id="placesContext"/>
|
||||
|
||||
<panel id="notification-popup" position="after_start" noautofocus="true" hidden="true"/>
|
||||
<panel id="notification-popup" type="arrow" position="after_start" noautofocus="true" hidden="true"/>
|
||||
|
||||
<!-- Popup for site identity information -->
|
||||
<panel id="identity-popup" position="after_start" hidden="true" noautofocus="true"
|
||||
@ -559,7 +552,6 @@
|
||||
<menupopup id="appmenu_webDeveloper_popup">
|
||||
<menuitem id="appmenu_webConsole"
|
||||
label="&webConsoleCmd.label;"
|
||||
type="checkbox"
|
||||
oncommand="HUDConsoleUI.toggleHUD();"
|
||||
key="key_webConsole"/>
|
||||
<menuitem id="appmenu_pageInspect"
|
||||
@ -613,7 +605,7 @@
|
||||
key="manBookmarkKb"/>
|
||||
<menu id="appmenu_bookmarksMenu"
|
||||
class="split-menuitem-menu">
|
||||
<menupopup id="appmenu_bookmarksMenupopup"
|
||||
<menupopup id="appmenu_bookmarksPopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
openInTabs="children"
|
||||
@ -621,16 +613,9 @@
|
||||
onclick="BookmarksEventHandler.onClick(event);"
|
||||
onpopupshowing="BookmarksMenuButton.onPopupShowing(event);
|
||||
if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');
|
||||
this.appendChild(document.getElementById('appmenu_unsortedBookmarks_seperator'));
|
||||
this.appendChild(document.getElementById('appmenu_unsortedBookmarks'));"
|
||||
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
|
||||
tooltip="bhTooltip"
|
||||
popupsinherittooltip="true">
|
||||
<menuseparator id="appmenu_unsortedBookmarks_seperator"/>
|
||||
<menuitem id="appmenu_unsortedBookmarks"
|
||||
label="&appMenuUnsorted.label;"
|
||||
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
|
||||
class="menuitem-iconic"/>
|
||||
<menuitem id="appmenu_showAllBookmarks"
|
||||
label="&showAllBookmarks.label;"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
@ -658,6 +643,25 @@
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<menu id="appmenu_bookmarksToolbar"
|
||||
placesanonid="toolbar-autohide"
|
||||
class="menu-iconic bookmark-item"
|
||||
label="&personalbarCmd.label;"
|
||||
container="true">
|
||||
<menupopup id="appmenu_bookmarksToolbarPopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<!-- Bookmarks menu items -->
|
||||
<menuseparator builder="end"
|
||||
class="hide-if-empty-places-result"/>
|
||||
<menuitem id="appmenu_unsortedBookmarks"
|
||||
label="&appMenuUnsorted.label;"
|
||||
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
|
||||
class="menuitem-iconic"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</hbox>
|
||||
@ -771,6 +775,10 @@
|
||||
label="&helpTroubleshootingInfo.label;"
|
||||
oncommand="openTroubleshootingPage()"
|
||||
onclick="checkForMiddleClick(this,event);"/>
|
||||
<menuitem id="appmenu_feedbackPage"
|
||||
label="&helpFeedbackPage.label;"
|
||||
oncommand="openFeedbackPage()"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenu_safeMode"
|
||||
accesskey="&appMenuSafeMode.accesskey;"
|
||||
@ -802,9 +810,9 @@
|
||||
</hbox>
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox">
|
||||
<toolbarbutton id="titlebar-min" oncommand="window.minimize();"/>
|
||||
<toolbarbutton id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton id="titlebar-close" command="cmd_closeWindow"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
</vbox>
|
||||
@ -867,21 +875,6 @@
|
||||
command="Browser:ForwardOrForwardDuplicate"
|
||||
onclick="checkForMiddleClick(this, event);"
|
||||
tooltiptext="&forwardButton.tooltip;"/>
|
||||
<toolbarbutton id="back-forward-dropmarker" type="menu"
|
||||
disabled="true" tooltiptext="&backForwardMenu.tooltip;"
|
||||
onbroadcast="if (this.disabled) this.disabled =
|
||||
document.getElementById('Browser:Back').hasAttribute('disabled') &&
|
||||
document.getElementById('Browser:Forward').hasAttribute('disabled');">
|
||||
<!-- bug 415444: event.stopPropagation is here for the cloned version of
|
||||
this menupopup -->
|
||||
<menupopup context=""
|
||||
position="after_start"
|
||||
onpopupshowing="return FillHistoryMenu(event.target);"
|
||||
oncommand="gotoHistoryIndex(event); event.stopPropagation();"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
<observes element="Browser:Back" attribute="disabled"/>
|
||||
<observes element="Browser:Forward" attribute="disabled"/>
|
||||
</toolbarbutton>
|
||||
</toolbaritem>
|
||||
|
||||
<toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
@ -955,7 +948,6 @@
|
||||
tooltiptext="&goEndCap.tooltip;"
|
||||
onclick="gURLBar.handleCommand(event);"/>
|
||||
</hbox>
|
||||
<progressmeter id="urlbar-progress" mode="normal" value="0" collapsed="true"/>
|
||||
<toolbarbutton id="urlbar-go-button"
|
||||
onclick="gURLBar.handleCommand(event);"
|
||||
tooltiptext="&goEndCap.tooltip;"/>
|
||||
@ -1009,6 +1001,23 @@
|
||||
if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
|
||||
tooltip="bhTooltip" popupsinherittooltip="true">
|
||||
<menuitem id="BMB_viewBookmarksToolbar"
|
||||
placesanonid="view-toolbar"
|
||||
toolbarId="PersonalToolbar"
|
||||
type="checkbox"
|
||||
oncommand="onViewToolbarCommand(event)"
|
||||
label="&viewBookmarksToolbar.label;"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="BMB_bookmarksShowAll"
|
||||
label="&showAllBookmarks.label;"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
key="manBookmarkKb"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="BMB_bookmarkThisPage"
|
||||
class="menuitem-iconic"
|
||||
label="&bookmarkThisPageCmd.label;"
|
||||
command="Browser:AddBookmarkAs"
|
||||
key="addBookmarkAsKb"/>
|
||||
<menuitem id="BMB_subscribeToPageMenuitem"
|
||||
label="&subscribeToPageMenuitem.label;"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
@ -1022,47 +1031,26 @@
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
</menu>
|
||||
<menuitem id="BMB_bookmarkAllTabs"
|
||||
label="&addCurPagesCmd.label;"
|
||||
command="Browser:BookmarkAllTabs"
|
||||
key="bookmarkAllTabsKb"/>
|
||||
<menuitem id="BMB_bookmarksShowAll"
|
||||
label="&showAllBookmarks.label;"
|
||||
command="Browser:ShowAllBookmarks"
|
||||
key="manBookmarkKb"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="BMB_viewBookmarksToolbar"
|
||||
type="checkbox"
|
||||
oncommand="onViewToolbarCommand(event)"
|
||||
label="&viewBookmarksToolbar.label;"/>
|
||||
<menuitem id="BMB_viewBookmarksSidebar"
|
||||
label="&viewBookmarksSidebar.label;"
|
||||
type="checkbox"
|
||||
oncommand="toggleSidebar('viewBookmarksSidebar');"
|
||||
key="viewBookmarksSidebarKb">
|
||||
<observes element="viewBookmarksSidebar" attribute="checked"/>
|
||||
</menuitem>
|
||||
<menuseparator/>
|
||||
<menu id="BMB_bookmarksToolbarFolderMenu"
|
||||
<menu id="BMB_bookmarksToolbar"
|
||||
placesanonid="toolbar-autohide"
|
||||
class="menu-iconic bookmark-item"
|
||||
label="&personalbarCmd.label;"
|
||||
container="true">
|
||||
<menupopup id="BMB_bookmarksToolbarFolderPopup"
|
||||
<menupopup id="BMB_bookmarksToolbarPopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=TOOLBAR');"/>
|
||||
</menu>
|
||||
<menu id="BMB_unsortedBookmarksFolderMenu"
|
||||
class="menu-iconic bookmark-item"
|
||||
container="true">
|
||||
<menupopup id="BMB_unsortedBookmarksFolderPopup"
|
||||
placespopup="true"
|
||||
context="placesContext"
|
||||
onpopupshowing="if (!this.parentNode._placesView)
|
||||
new PlacesMenu(event, 'place:folder=UNFILED_BOOKMARKS');"/>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<!-- Bookmarks menu items -->
|
||||
<menuseparator builder="end"
|
||||
class="hide-if-empty-places-result"/>
|
||||
<menuitem id="BMB_unsortedBookmarks"
|
||||
label="&bookmarksMenuButton.unsorted.label;"
|
||||
oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
|
||||
class="menuitem-iconic"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
</toolbaritem>
|
||||
@ -1271,6 +1259,19 @@
|
||||
label="&syncToolbarButton.label;"
|
||||
oncommand="gSyncUI.handleToolbarButton()"/>
|
||||
#endif
|
||||
<toolbarbutton id="feed-button"
|
||||
type="menu"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
disabled="true"
|
||||
label="&feedButton.label;"
|
||||
tooltiptext="&feedButton.tooltip;"
|
||||
onclick="return FeedHandler.onFeedButtonClick(event);">
|
||||
<menupopup position="after_end"
|
||||
id="feed-menu"
|
||||
onpopupshowing="return FeedHandler.buildFeedList(this);"
|
||||
oncommand="return FeedHandler.subscribeToFeed(null, event);"
|
||||
onclick="checkForMiddleClick(this, event);"/>
|
||||
</toolbarbutton>
|
||||
</toolbarpalette>
|
||||
</toolbox>
|
||||
|
||||
@ -1297,7 +1298,9 @@
|
||||
</hbox>
|
||||
|
||||
<vbox id="browser-bottombox" layer="true">
|
||||
<toolbar id="addon-bar" toolbarname="&addonBarCmd.label;" collapsed="true"
|
||||
<toolbar id="addon-bar"
|
||||
toolbarname="&addonBarCmd.label;" accesskey="&addonBarCmd.accesskey;"
|
||||
collapsed="true"
|
||||
class="toolbar-primary chromeclass-toolbar"
|
||||
context="toolbar-context-menu" toolboxid="navigator-toolbox"
|
||||
mode="icons" iconsize="small" defaulticonsize="small"
|
||||
|
@ -125,6 +125,10 @@ function onUnloadPermission()
|
||||
var os = Components.classes["@mozilla.org/observer-service;1"]
|
||||
.getService(Components.interfaces.nsIObserverService);
|
||||
os.removeObserver(permissionObserver, "perm-changed");
|
||||
|
||||
var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager);
|
||||
dbManager.cancelGetUsageForURI(gPermURI, onIndexedDBUsageCallback);
|
||||
}
|
||||
|
||||
function initRow(aPartId)
|
||||
@ -195,27 +199,16 @@ function setRadioState(aPartId, aValue)
|
||||
|
||||
function initIndexedDBRow()
|
||||
{
|
||||
var dbManager = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager);
|
||||
dbManager.getUsageForURI(gPermURI, onIndexedDBUsageCallback);
|
||||
|
||||
var status = document.getElementById("indexedDBStatus");
|
||||
var button = document.getElementById("indexedDBClear");
|
||||
|
||||
var usage = Components.classes["@mozilla.org/dom/indexeddb/manager;1"]
|
||||
.getService(nsIIndexedDatabaseManager)
|
||||
.getUsageForURI(gPermURI);
|
||||
if (usage) {
|
||||
if (!("DownloadUtils" in window)) {
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
}
|
||||
status.value =
|
||||
gBundle.getFormattedString("indexedDBUsage",
|
||||
DownloadUtils.convertByteUnits(usage));
|
||||
status.removeAttribute("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
}
|
||||
else {
|
||||
status.value = "";
|
||||
status.setAttribute("hidden", "true");
|
||||
button.setAttribute("hidden", "true");
|
||||
}
|
||||
status.value = "";
|
||||
status.setAttribute("hidden", "true");
|
||||
button.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
function onIndexedDBClear()
|
||||
@ -230,3 +223,25 @@ function onIndexedDBClear()
|
||||
permissionManager.remove(gPermURI.host, "indexedDB-unlimited");
|
||||
initIndexedDBRow();
|
||||
}
|
||||
|
||||
function onIndexedDBUsageCallback(uri, usage)
|
||||
{
|
||||
if (!uri.equals(gPermURI)) {
|
||||
throw new Error("Callback received for bad URI: " + uri);
|
||||
}
|
||||
|
||||
if (usage) {
|
||||
if (!("DownloadUtils" in window)) {
|
||||
Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
|
||||
}
|
||||
|
||||
var status = document.getElementById("indexedDBStatus");
|
||||
var button = document.getElementById("indexedDBClear");
|
||||
|
||||
status.value =
|
||||
gBundle.getFormattedString("indexedDBUsage",
|
||||
DownloadUtils.convertByteUnits(usage));
|
||||
status.removeAttribute("hidden");
|
||||
button.removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ function disableAddons() {
|
||||
aAddon.userDisabled = true;
|
||||
}
|
||||
});
|
||||
|
||||
restartApp();
|
||||
});
|
||||
}
|
||||
|
||||
@ -112,14 +114,18 @@ function onOK() {
|
||||
restoreDefaultBookmarks();
|
||||
if (document.getElementById("resetToolbars").checked)
|
||||
deleteLocalstore();
|
||||
if (document.getElementById("disableAddons").checked)
|
||||
disableAddons();
|
||||
if (document.getElementById("restoreSearch").checked)
|
||||
restoreDefaultSearchEngines();
|
||||
if (document.getElementById("disableAddons").checked) {
|
||||
disableAddons();
|
||||
// disableAddons will asynchronously restart the application
|
||||
return false;
|
||||
}
|
||||
} catch(e) {
|
||||
}
|
||||
|
||||
restartApp();
|
||||
return false;
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
|
@ -61,7 +61,7 @@
|
||||
#endif
|
||||
buttonlabelextra1="&continueButton.label;"
|
||||
width="&window.width;"
|
||||
ondialogaccept="onOK()"
|
||||
ondialogaccept="return onOK()"
|
||||
ondialogcancel="onCancel()"
|
||||
ondialogextra1="window.close()"
|
||||
onload="onLoad();"
|
||||
|
@ -147,12 +147,16 @@ let Change = {
|
||||
},
|
||||
|
||||
_updateStatusWithString: function Change__updateStatusWithString(string, state) {
|
||||
this._statusRow.hidden = false;
|
||||
document.getElementById("passphraseStrengthRow").hidden = true;
|
||||
this._status.value = string;
|
||||
this._statusIcon.setAttribute("status", state);
|
||||
|
||||
let error = state == "error";
|
||||
this._dialog.getButton("cancel").setAttribute("disabled", !error);
|
||||
this._dialog.getButton("accept").setAttribute("disabled", !error);
|
||||
document.getElementById("printSyncKeyButton").disabled = !error;
|
||||
document.getElementById("saveSyncKeyButton").disabled = !error;
|
||||
|
||||
if (state == "success")
|
||||
window.setTimeout(window.close, 1500);
|
||||
|
@ -135,10 +135,12 @@
|
||||
</vbox>
|
||||
|
||||
<hbox id="passphraseBackupButtons" pack="center">
|
||||
<button label="&button.syncKeyBackup.print.label;"
|
||||
<button id="printSyncKeyButton"
|
||||
label="&button.syncKeyBackup.print.label;"
|
||||
accesskey="&button.syncKeyBackup.print.accesskey;"
|
||||
oncommand="gSyncUtils.passphrasePrint('passphraseBox');"/>
|
||||
<button label="&button.syncKeyBackup.save.label;"
|
||||
<button id="saveSyncKeyButton"
|
||||
label="&button.syncKeyBackup.save.label;"
|
||||
accesskey="&button.syncKeyBackup.save.accesskey;"
|
||||
oncommand="gSyncUtils.passphraseSave('passphraseBox');"/>
|
||||
</hbox>
|
||||
|
@ -237,20 +237,24 @@ var gSyncSetup = {
|
||||
return true;
|
||||
},
|
||||
|
||||
onEmailChange: function () {
|
||||
onEmailInput: function () {
|
||||
// Check account validity when the user stops typing for 1 second.
|
||||
if (this._checkAccountTimer)
|
||||
window.clearTimeout(this._checkAccountTimer);
|
||||
this._checkAccountTimer = window.setTimeout(function () {
|
||||
gSyncSetup.checkAccount();
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
checkAccount: function() {
|
||||
delete this._checkAccountTimer;
|
||||
let value = document.getElementById("weaveEmail").value;
|
||||
if (!value) {
|
||||
this.status.email = false;
|
||||
this.checkFields();
|
||||
return;
|
||||
}
|
||||
// Do this async to avoid blocking the widget while we go to the server.
|
||||
window.setTimeout(function() {
|
||||
gSyncSetup.checkAccount(value);
|
||||
}, 0);
|
||||
},
|
||||
|
||||
checkAccount: function(value) {
|
||||
let re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
let feedback = document.getElementById("emailFeedbackRow");
|
||||
let valid = re.test(value);
|
||||
@ -337,7 +341,7 @@ var gSyncSetup = {
|
||||
// xxxmpc - hack, sigh
|
||||
if (el1.value == document.getElementById("weavePassword").value) {
|
||||
valid = false;
|
||||
str = Weave.Utils.getErrorString("change.passphrase.ppSameAsPassword");
|
||||
str = Weave.Utils.getErrorString("change.synckey.sameAsPassword");
|
||||
}
|
||||
else {
|
||||
[valid, str] = gSyncUtils.validatePassphrase(el1);
|
||||
@ -345,7 +349,14 @@ var gSyncSetup = {
|
||||
|
||||
let feedback = document.getElementById("passphraseFeedbackRow");
|
||||
this._setFeedback(feedback, valid, str);
|
||||
if (!valid)
|
||||
if (!valid) {
|
||||
// Hide strength meter if we're displaying an error.
|
||||
document.getElementById("passphraseStrengthRow").hidden = true;
|
||||
return valid;
|
||||
}
|
||||
|
||||
// No passphrase strength meter for the generated key.
|
||||
if (!this._haveCustomSyncKey)
|
||||
return valid;
|
||||
|
||||
// Display passphrase strength
|
||||
@ -373,8 +384,8 @@ var gSyncSetup = {
|
||||
this.wizard.getButton("extra1").hidden = true;
|
||||
break;
|
||||
case NEW_ACCOUNT_PP_PAGE:
|
||||
document.getElementById("saveSyncKeyButton").focus();
|
||||
let el = document.getElementById("weavePassphrase");
|
||||
el.blur();
|
||||
if (!el.value)
|
||||
this.onPassphraseGenerate();
|
||||
this.checkFields();
|
||||
@ -432,6 +443,14 @@ var gSyncSetup = {
|
||||
return true;
|
||||
|
||||
switch (this.wizard.pageIndex) {
|
||||
case NEW_ACCOUNT_START_PAGE:
|
||||
// If the user selects Next (e.g. by hitting enter) when we haven't
|
||||
// executed the delayed checks yet, execute them immediately.
|
||||
if (this._checkAccountTimer)
|
||||
this.checkAccount();
|
||||
if (this._checkServerTimer)
|
||||
this.checkServer();
|
||||
return this.wizard.canAdvance;
|
||||
case NEW_ACCOUNT_CAPTCHA_PAGE:
|
||||
let doc = this.captchaBrowser.contentDocument;
|
||||
let getField = function getField(field) {
|
||||
@ -628,29 +647,45 @@ var gSyncSetup = {
|
||||
|
||||
document.getElementById("serverRow").hidden = this._usingMainServers;
|
||||
document.getElementById("TOSRow").hidden = !this._usingMainServers;
|
||||
|
||||
if (!this._usingMainServers) {
|
||||
this.checkServer();
|
||||
return;
|
||||
}
|
||||
|
||||
Weave.Svc.Prefs.reset("serverURL");
|
||||
this.checkAccount();
|
||||
this.status.server = true;
|
||||
document.getElementById("serverFeedbackRow").hidden = true;
|
||||
this.checkFields();
|
||||
},
|
||||
|
||||
onServerInput: function () {
|
||||
// Check custom server validity when the user stops typing for 1 second.
|
||||
if (this._checkServerTimer)
|
||||
window.clearTimeout(this._checkServerTimer);
|
||||
this._checkServerTimer = window.setTimeout(function () {
|
||||
gSyncSetup.checkServer();
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
checkServer: function () {
|
||||
delete this._checkServerTimer;
|
||||
let el = document.getElementById("weaveServerURL");
|
||||
let valid = false;
|
||||
let feedback = document.getElementById("serverFeedbackRow");
|
||||
|
||||
if (this._usingMainServers) {
|
||||
Weave.Svc.Prefs.reset("serverURL");
|
||||
valid = true;
|
||||
feedback.hidden = true;
|
||||
}
|
||||
else {
|
||||
let el = document.getElementById("weaveServerURL");
|
||||
let str = "";
|
||||
if (el.value) {
|
||||
valid = this._validateServer(el, true);
|
||||
let str = valid ? "" : "serverInvalid.label";
|
||||
this._setFeedbackMessage(feedback, valid, str);
|
||||
}
|
||||
else
|
||||
this._setFeedbackMessage(feedback, true);
|
||||
let str = "";
|
||||
if (el.value) {
|
||||
valid = this._validateServer(el, true);
|
||||
let str = valid ? "" : "serverInvalid.label";
|
||||
this._setFeedbackMessage(feedback, valid, str);
|
||||
}
|
||||
else
|
||||
this._setFeedbackMessage(feedback, true);
|
||||
|
||||
// Recheck account against the new server.
|
||||
if (valid)
|
||||
this.onEmailChange();
|
||||
this.checkAccount();
|
||||
|
||||
this.status.server = valid;
|
||||
this.checkFields();
|
||||
@ -744,10 +779,12 @@ var gSyncSetup = {
|
||||
|
||||
if (stm.step())
|
||||
daysOfHistory = stm.getInt32(0);
|
||||
// Support %S for historical reasons (see bug 600141)
|
||||
document.getElementById("historyCount").value =
|
||||
PluralForm.get(daysOfHistory,
|
||||
this._stringBundle.GetStringFromName("historyDaysCount.label"))
|
||||
.replace("%S", daysOfHistory);
|
||||
.replace("%S", daysOfHistory)
|
||||
.replace("#1", daysOfHistory);
|
||||
|
||||
// bookmarks
|
||||
let bookmarks = 0;
|
||||
@ -759,17 +796,21 @@ var gSyncSetup = {
|
||||
stm.params.tag = Weave.Svc.Bookmark.tagsFolder;
|
||||
if (stm.executeStep())
|
||||
bookmarks = stm.row.bookmarks;
|
||||
// Support %S for historical reasons (see bug 600141)
|
||||
document.getElementById("bookmarkCount").value =
|
||||
PluralForm.get(bookmarks,
|
||||
this._stringBundle.GetStringFromName("bookmarksCount.label"))
|
||||
.replace("%S", bookmarks);
|
||||
.replace("%S", bookmarks)
|
||||
.replace("#1", bookmarks);
|
||||
|
||||
// passwords
|
||||
let logins = Weave.Svc.Login.getAllLogins({});
|
||||
// Support %S for historical reasons (see bug 600141)
|
||||
document.getElementById("passwordCount").value =
|
||||
PluralForm.get(logins.length,
|
||||
this._stringBundle.GetStringFromName("passwordsCount.label"))
|
||||
.replace("%S", logins.length);
|
||||
.replace("%S", logins.length)
|
||||
.replace("#1", logins.length);
|
||||
this._case1Setup = true;
|
||||
break;
|
||||
case 2:
|
||||
@ -794,10 +835,12 @@ var gSyncSetup = {
|
||||
appendNode(name);
|
||||
}
|
||||
if (count > 5) {
|
||||
// Support %S for historical reasons (see bug 600141)
|
||||
let label =
|
||||
PluralForm.get(count - 5,
|
||||
this._stringBundle.GetStringFromName("additionalClientCount.label"))
|
||||
.replace("%S", count - 5);
|
||||
.replace("%S", count - 5)
|
||||
.replace("#1", count - 5);
|
||||
appendNode(label);
|
||||
}
|
||||
this._case2Setup = true;
|
||||
|
@ -112,7 +112,7 @@
|
||||
accesskey="&setup.emailAddress.accesskey;"
|
||||
control="weaveEmail"/>
|
||||
<textbox id="weaveEmail"
|
||||
onchange="gSyncSetup.onEmailChange()"/>
|
||||
oninput="gSyncSetup.onEmailInput()"/>
|
||||
</row>
|
||||
<row id="emailFeedbackRow" align="center" hidden="true">
|
||||
<spacer/>
|
||||
@ -160,7 +160,7 @@
|
||||
<label value="&signIn.serverURL.label;"
|
||||
accesskey="&signIn.serverURL.accesskey;"
|
||||
control="weaveServerURL"/>
|
||||
<textbox id="weaveServerURL" onchange="gSyncSetup.onServerChange()"/>
|
||||
<textbox id="weaveServerURL" oninput="gSyncSetup.onServerInput()"/>
|
||||
</row>
|
||||
<row id="serverFeedbackRow" align="center" hidden="true">
|
||||
<spacer/>
|
||||
@ -217,7 +217,8 @@
|
||||
<textbox id="weavePassphrase"
|
||||
onkeyup="gSyncSetup.onPassphraseChange()"
|
||||
onchange="gSyncSetup.onPassphraseChange()"
|
||||
onfocus="this.select()"/>
|
||||
onfocus="this.select();
|
||||
gSyncSetup.afterBackup();"/>
|
||||
|
||||
<vbox id="passphraseFeedback" pack="center">
|
||||
<hbox id="passphraseFeedbackRow" hidden="true" align="center">
|
||||
@ -252,11 +253,13 @@
|
||||
<groupbox align="center">
|
||||
<description>&syncKeyBackup.description;</description>
|
||||
<hbox>
|
||||
<button label="&button.syncKeyBackup.print.label;"
|
||||
<button id="printSyncKeyButton"
|
||||
label="&button.syncKeyBackup.print.label;"
|
||||
accesskey="&button.syncKeyBackup.print.accesskey;"
|
||||
oncommand="gSyncUtils.passphrasePrint('weavePassphrase');
|
||||
gSyncSetup.afterBackup();"/>
|
||||
<button label="&button.syncKeyBackup.save.label;"
|
||||
<button id="saveSyncKeyButton"
|
||||
label="&button.syncKeyBackup.save.label;"
|
||||
accesskey="&button.syncKeyBackup.save.accesskey;"
|
||||
oncommand="gSyncUtils.passphraseSave('weavePassphrase');
|
||||
gSyncSetup.afterBackup();"/>
|
||||
|
@ -299,7 +299,9 @@ let gSyncUtils = {
|
||||
let val = el.value;
|
||||
let error = "";
|
||||
|
||||
if (val == Weave.Service.username)
|
||||
if (val.length < Weave.MIN_PP_LENGTH)
|
||||
error = "change.synckey.tooShort";
|
||||
else if (val == Weave.Service.username)
|
||||
error = "change.synckey.sameAsUsername";
|
||||
else if (val == Weave.Service.account)
|
||||
error = "change.synckey.sameAsEmail";
|
||||
@ -307,8 +309,6 @@ let gSyncUtils = {
|
||||
error = "change.synckey.sameAsPassword";
|
||||
else if (change && val == Weave.Service.passphrase)
|
||||
error = "change.synckey.sameAsSyncKey";
|
||||
else if (val.length < Weave.MIN_PP_LENGTH)
|
||||
error = "change.synckey.tooShort";
|
||||
else
|
||||
valid = true;
|
||||
|
||||
|
@ -23,11 +23,15 @@
|
||||
}
|
||||
|
||||
.tab-label[pinned] {
|
||||
display: none;
|
||||
width: 0;
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.tab-stack {
|
||||
vertical-align: middle; /* for pinned tabs */
|
||||
vertical-align: top; /* for pinned tabs */
|
||||
}
|
||||
|
||||
tabpanels {
|
||||
@ -39,19 +43,7 @@ tabpanels {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* tab progress */
|
||||
|
||||
.tab-progress {
|
||||
-moz-binding: url("chrome://global/content/bindings/progressmeter.xml#progressmeter") !important;
|
||||
margin: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tab-progress[selected],
|
||||
.tab-progress:not([busy]) {
|
||||
.tab-throbber:not([busy]),
|
||||
.tab-throbber[busy] + .tab-icon-image {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-progress-container {
|
||||
-moz-box-pack: start;
|
||||
}
|
||||
|
@ -183,6 +183,9 @@
|
||||
if (aTab.pinned)
|
||||
return;
|
||||
|
||||
if (aTab.hidden)
|
||||
this.showTab(aTab);
|
||||
|
||||
this.moveTabTo(aTab, this._numPinnedTabs);
|
||||
aTab.setAttribute("pinned", "true");
|
||||
this.tabContainer._positionPinnedTabs();
|
||||
@ -353,8 +356,6 @@
|
||||
mRequestCount: 0,
|
||||
|
||||
destroy: function () {
|
||||
this._cancelStalledTimer();
|
||||
this.mTab.removeAttribute("stalled");
|
||||
delete this.mTab;
|
||||
delete this.mBrowser;
|
||||
delete this.mTabBrowser;
|
||||
@ -373,10 +374,8 @@
|
||||
if (this.mBlank)
|
||||
return;
|
||||
|
||||
if (this.mTotalProgress) {
|
||||
let value = Math.ceil(this.mTotalProgress * 100);
|
||||
this.mTab.setAttribute("progresspercent", value);
|
||||
}
|
||||
if (this.mTotalProgress)
|
||||
this.mTab.setAttribute("progress", "true");
|
||||
|
||||
this._callProgressListeners("onProgressChange",
|
||||
[aWebProgress, aRequest,
|
||||
@ -432,8 +431,6 @@
|
||||
if (!this.mBlank) {
|
||||
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
this.mTab.setAttribute("progresspercent", "0");
|
||||
this._startStalledTimer();
|
||||
this.mTabBrowser.setTabTitleLoading(this.mTab);
|
||||
}
|
||||
|
||||
@ -459,9 +456,7 @@
|
||||
this.mBlank = false;
|
||||
|
||||
this.mTab.removeAttribute("busy");
|
||||
this.mTab.removeAttribute("progresspercent");
|
||||
this.mTab.removeAttribute("stalled");
|
||||
this._cancelStalledTimer();
|
||||
this.mTab.removeAttribute("progress");
|
||||
|
||||
var location = aRequest.QueryInterface(nsIChannel).URI;
|
||||
|
||||
@ -469,7 +464,7 @@
|
||||
if (location.scheme == "keyword")
|
||||
this.mBrowser.userTypedValue = null;
|
||||
|
||||
if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.loading"))
|
||||
if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.connecting"))
|
||||
this.mTabBrowser.setTabTitle(this.mTab);
|
||||
|
||||
if (this.mTab.selected)
|
||||
@ -565,20 +560,6 @@
|
||||
aIID.equals(Components.interfaces.nsISupports))
|
||||
return this;
|
||||
throw Components.results.NS_NOINTERFACE;
|
||||
},
|
||||
|
||||
_startStalledTimer: function () {
|
||||
this._cancelStalledTimer();
|
||||
this._stalledTimer = setTimeout(function (self) {
|
||||
self.mTab.setAttribute("stalled", "true");
|
||||
}, 700, this);
|
||||
},
|
||||
|
||||
_cancelStalledTimer: function () {
|
||||
if (this._stalledTimer) {
|
||||
clearTimeout(this._stalledTimer);
|
||||
this._stalledTimer = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
]]>
|
||||
@ -893,7 +874,7 @@
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
aTab.label = this.mStringBundle.getString("tabs.loading");
|
||||
aTab.label = this.mStringBundle.getString("tabs.connecting");
|
||||
aTab.crop = "end";
|
||||
this._tabAttrModified(aTab);
|
||||
]]>
|
||||
@ -1385,19 +1366,12 @@
|
||||
if (!this._beginRemoveTab(aTab, false, null, true))
|
||||
return;
|
||||
|
||||
/* Don't animate if:
|
||||
- the caller didn't opt in
|
||||
- this is the last tab in the window
|
||||
- this is a pinned tab
|
||||
- a bunch of other tabs are already closing (arbitrary threshold)
|
||||
- the fadein attribute hasn't been set yet
|
||||
- browser.tabs.animate is false */
|
||||
|
||||
if (!animate ||
|
||||
if (!animate /* the caller didn't opt in */ ||
|
||||
isLastTab ||
|
||||
aTab.pinned ||
|
||||
this._removingTabs.length > 3 ||
|
||||
aTab.getAttribute("fadein") != "true" ||
|
||||
this._removingTabs.length > 3 /* don't want lots of concurrent animations */ ||
|
||||
aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
|
||||
window.getComputedStyle(aTab).maxWidth == "1px" /* fade-in transition hasn't moved yet */ ||
|
||||
!Services.prefs.getBoolPref("browser.tabs.animate")) {
|
||||
this._endRemoveTab(aTab);
|
||||
return;
|
||||
@ -1844,7 +1818,7 @@
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aTab.hidden) {
|
||||
aTab.hidden = false;
|
||||
aTab.removeAttribute("hidden");
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("TabShow", true, false);
|
||||
aTab.dispatchEvent(event);
|
||||
@ -1859,7 +1833,7 @@
|
||||
<![CDATA[
|
||||
if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
|
||||
this._removingTabs.indexOf(aTab) == -1) {
|
||||
aTab.hidden = true;
|
||||
aTab.setAttribute("hidden", "true");
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("TabHide", true, false);
|
||||
aTab.dispatchEvent(event);
|
||||
@ -3324,12 +3298,11 @@
|
||||
|
||||
<content context="tabContextMenu" closetabtext="&closeTab.label;">
|
||||
<xul:stack class="tab-stack" flex="1">
|
||||
<xul:vbox class="tab-progress-container">
|
||||
<xul:progressmeter class="tab-progress" mode="normal"
|
||||
xbl:inherits="value=progresspercent,busy,stalled,fadein,selected"/>
|
||||
</xul:vbox>
|
||||
<xul:hbox class="tab-content" align="center">
|
||||
<xul:image xbl:inherits="validate,src=image,fadein,pinned,busy,stalled,selected"
|
||||
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
|
||||
class="tab-throbber"
|
||||
role="presentation"/>
|
||||
<xul:image xbl:inherits="validate,src=image,fadein,pinned,selected"
|
||||
class="tab-icon-image"
|
||||
role="presentation"/>
|
||||
<xul:label flex="1"
|
||||
@ -3351,6 +3324,11 @@
|
||||
return this.getAttribute("pinned") == "true";
|
||||
</getter>
|
||||
</property>
|
||||
<property name="hidden" readonly="true">
|
||||
<getter>
|
||||
return this.getAttribute("hidden") == "true";
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<field name="mOverCloseButton">false</field>
|
||||
<field name="mCorrespondingMenuitem">null</field>
|
||||
@ -3549,15 +3527,10 @@
|
||||
<![CDATA[
|
||||
var tab = event.target.tab;
|
||||
if (tab) {
|
||||
var statusText = tab.linkedBrowser.currentURI.spec;
|
||||
if (statusText == "about:blank") {
|
||||
// XXXhack: Passing a space here (and not "")
|
||||
// to make sure the the browser implementation would
|
||||
// still consider it a hovered link.
|
||||
statusText = " ";
|
||||
}
|
||||
|
||||
XULBrowserWindow.setOverLink(statusText, null);
|
||||
let overLink = tab.linkedBrowser.currentURI.spec;
|
||||
if (overLink == "about:blank")
|
||||
overLink = "";
|
||||
XULBrowserWindow.setOverLink(overLink, null);
|
||||
}
|
||||
]]></handler>
|
||||
|
||||
|
@ -118,8 +118,8 @@ Drag.prototype = {
|
||||
|
||||
// OH SNAP!
|
||||
|
||||
// if we aren't holding down the meta key...
|
||||
if (!Keys.meta) {
|
||||
// if we aren't holding down the meta key or have trenches disabled...
|
||||
if (!Keys.meta && !Trenches.disabled) {
|
||||
// snappable = true if we aren't a tab on top of something else, and
|
||||
// there's no active drop site...
|
||||
let snappable = !(this.item.isATabItem &&
|
||||
@ -272,7 +272,10 @@ Drag.prototype = {
|
||||
// ----------
|
||||
// Function: stop
|
||||
// Called in response to an <Item> draggable "stop" event.
|
||||
stop: function Drag_stop() {
|
||||
//
|
||||
// Parameters:
|
||||
// immediately - bool for doing the pushAway immediately, without animation
|
||||
stop: function Drag_stop(immediately) {
|
||||
Trenches.hideGuides();
|
||||
this.item.isDragging = false;
|
||||
|
||||
@ -288,7 +291,7 @@ Drag.prototype = {
|
||||
this.item.setZ(drag.zIndex);
|
||||
drag.zIndex++;
|
||||
|
||||
this.item.pushAway();
|
||||
this.item.pushAway(immediately);
|
||||
}
|
||||
|
||||
Trenches.disactivate();
|
||||
|
@ -63,6 +63,8 @@
|
||||
// container - a DOM element to use as the container for this groupItem; otherwise will create
|
||||
// title - the title for the groupItem; otherwise blank
|
||||
// dontPush - true if this groupItem shouldn't push away on creation; default is false
|
||||
// dontPush - true if this groupItem shouldn't push away or snap on creation; default is false
|
||||
// immediately - true if we want all placement immediately, not with animation
|
||||
function GroupItem(listOfEls, options) {
|
||||
if (typeof options == 'undefined')
|
||||
options = {};
|
||||
@ -110,6 +112,7 @@ function GroupItem(listOfEls, options) {
|
||||
}
|
||||
|
||||
var $container = options.container;
|
||||
let immediately = options.immediately || $container ? true : false;
|
||||
if (!$container) {
|
||||
$container = iQ('<div>')
|
||||
.addClass('groupItem')
|
||||
@ -164,21 +167,26 @@ function GroupItem(listOfEls, options) {
|
||||
this.$titleShield = iQ('.title-shield', this.$titlebar);
|
||||
this.setTitle(options.title || this.defaultName);
|
||||
|
||||
var titleUnfocus = function() {
|
||||
var titleUnfocus = function(immediately) {
|
||||
self.$titleShield.show();
|
||||
if (!self.getTitle()) {
|
||||
self.$title
|
||||
.addClass("defaultName")
|
||||
.val(self.defaultName);
|
||||
} else {
|
||||
self.$title
|
||||
.css({"background":"none"})
|
||||
.animate({
|
||||
"padding-left": "1px"
|
||||
}, {
|
||||
duration: 200,
|
||||
easing: "tabviewBounce"
|
||||
});
|
||||
self.$title.css({"background":"none"});
|
||||
if (immediately) {
|
||||
self.$title.css({
|
||||
"padding-left": "1px"
|
||||
});
|
||||
} else {
|
||||
self.$title.animate({
|
||||
"padding-left": "1px"
|
||||
}, {
|
||||
duration: 200,
|
||||
easing: "tabviewBounce"
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -221,7 +229,7 @@ function GroupItem(listOfEls, options) {
|
||||
.keydown(handleKeyDown)
|
||||
.keyup(handleKeyUp);
|
||||
|
||||
titleUnfocus();
|
||||
titleUnfocus(immediately);
|
||||
|
||||
if (this.locked.title)
|
||||
this.$title.addClass('name-locked');
|
||||
@ -284,21 +292,21 @@ function GroupItem(listOfEls, options) {
|
||||
this._addHandlers($container);
|
||||
|
||||
if (!this.locked.bounds)
|
||||
this.setResizable(true);
|
||||
this.setResizable(true, immediately);
|
||||
|
||||
GroupItems.register(this);
|
||||
|
||||
// ___ Position
|
||||
var immediately = $container ? true : false;
|
||||
this.setBounds(rectToBe, immediately);
|
||||
this.snap();
|
||||
if (options.dontPush) {
|
||||
this.setZ(drag.zIndex);
|
||||
drag.zIndex++;
|
||||
} else
|
||||
// Calling snap will also trigger pushAway
|
||||
this.snap(immediately);
|
||||
if ($container)
|
||||
this.setBounds(rectToBe, immediately);
|
||||
|
||||
// ___ Push other objects away
|
||||
if (!options.dontPush)
|
||||
this.pushAway();
|
||||
|
||||
this._inited = true;
|
||||
this.save();
|
||||
};
|
||||
@ -560,6 +568,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Function: closeAll
|
||||
// Closes the groupItem and all of its children.
|
||||
closeAll: function GroupItem_closeAll() {
|
||||
let closeCenter = this.getBounds().center();
|
||||
if (this._children.length > 0) {
|
||||
this._children.forEach(function(child) {
|
||||
iQ(child.container).hide();
|
||||
@ -580,6 +589,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (!this.locked.close)
|
||||
this.close();
|
||||
}
|
||||
// Find closest tab to make active
|
||||
UI.setActiveTab( UI.getClosestTab(closeCenter) );
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -590,7 +601,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.$undoContainer = iQ("<div/>")
|
||||
.addClass("undo")
|
||||
.attr("type", "button")
|
||||
.text("Undo Close Group")
|
||||
.text(tabviewString("groupItem.undoCloseGroup"))
|
||||
.appendTo("body");
|
||||
let undoClose = iQ("<span/>")
|
||||
.addClass("close")
|
||||
@ -701,7 +712,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// a - The item to add. Can be an <Item>, a DOM element or an iQ object.
|
||||
// The latter two must refer to the container of an <Item>.
|
||||
// dropPos - An object with left and top properties referring to the location dropped at. Optional.
|
||||
// options - An object with optional settings for this call. Currently the only one is dontArrange.
|
||||
// options - An object with optional settings for this call. Currently this includes dontArrange
|
||||
// and immediately
|
||||
add: function GroupItem_add(a, dropPos, options) {
|
||||
try {
|
||||
var item;
|
||||
@ -788,7 +800,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
item.setParent(this);
|
||||
|
||||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(false);
|
||||
item.setResizable(false, options.immediately);
|
||||
|
||||
// if it is visually active, set it as the active tab.
|
||||
if (iQ(item.container).hasClass("focus"))
|
||||
@ -801,9 +813,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
GroupItems.setActiveGroupItem(this);
|
||||
}
|
||||
|
||||
if (!options.dontArrange) {
|
||||
this.arrange();
|
||||
}
|
||||
if (!options.dontArrange)
|
||||
this.arrange({animate: !options.immediately});
|
||||
|
||||
this._sendToSubscribers("childAdded",{ groupItemId: this.id, item: item });
|
||||
|
||||
@ -820,7 +831,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
//
|
||||
// a - The item to remove. Can be an <Item>, a DOM element or an iQ object.
|
||||
// The latter two must refer to the container of an <Item>.
|
||||
// options - An object with optional settings for this call. Currently the only one is dontArrange.
|
||||
// options - An object with optional settings for this call. Currently this includes
|
||||
// dontArrange and immediately
|
||||
remove: function GroupItem_remove(a, options) {
|
||||
try {
|
||||
var $el;
|
||||
@ -858,12 +870,12 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
item.removeSubscriber(this, "close");
|
||||
|
||||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(true);
|
||||
item.setResizable(true, options.immediately);
|
||||
|
||||
if (!this._children.length && !this.locked.close && !this.getTitle() && !options.dontClose) {
|
||||
this.close();
|
||||
} else if (!options.dontArrange) {
|
||||
this.arrange();
|
||||
this.arrange({animate: !options.immediately});
|
||||
}
|
||||
|
||||
this._sendToSubscribers("childRemoved",{ groupItemId: this.id, item: item });
|
||||
@ -901,7 +913,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
return;
|
||||
|
||||
GroupItems.setActiveGroupItem(self);
|
||||
GroupItems._updateTabBar();
|
||||
UI.goToTab(iQ(this).data("xulTab"));
|
||||
});
|
||||
|
||||
@ -943,19 +954,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Function: showExpandControl
|
||||
// Show the control which expands a stacked groupItem into a quick-look view.
|
||||
showExpandControl: function GroupItem_showExpandControl() {
|
||||
var childBB = this.getChild(0).getBounds();
|
||||
var dT = childBB.top - this.getBounds().top;
|
||||
var dL = childBB.left - this.getBounds().left;
|
||||
|
||||
let parentBB = this.getBounds();
|
||||
let childBB = this.getChild(0).getBounds();
|
||||
let padding = 7;
|
||||
this.$expander
|
||||
.show()
|
||||
.css({
|
||||
opacity: .2,
|
||||
top: dT + childBB.height + Math.min(7, (this.getBounds().bottom-childBB.bottom)/2),
|
||||
// TODO: Why the magic -6? because the childBB.width seems to be over-sizing itself.
|
||||
// But who can blame an object for being a bit optimistic when self-reporting size.
|
||||
// It has to impress the ladies somehow. Bug 586549
|
||||
left: dL + childBB.width/2 - this.$expander.width()/2 - 6,
|
||||
top: childBB.top + childBB.height - parentBB.top + padding,
|
||||
left: parentBB.width/2 - this.$expander.width()/2
|
||||
});
|
||||
},
|
||||
|
||||
@ -973,7 +980,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
};
|
||||
|
||||
var rects = Items.arrange(null, bb, options);
|
||||
return (rects[0].width < TabItems.minTabWidth * 1.35);
|
||||
return (rects[0].width < 55);
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -992,15 +999,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
var bb = this.getContentBounds();
|
||||
var count = this._children.length;
|
||||
if (!this.shouldStack(count)) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
var animate;
|
||||
if (!options || typeof options.animate == 'undefined')
|
||||
if (typeof options.animate == 'undefined')
|
||||
animate = true;
|
||||
else
|
||||
animate = options.animate;
|
||||
|
||||
if (typeof options == 'undefined')
|
||||
options = {};
|
||||
|
||||
this._children.forEach(function(child) {
|
||||
child.removeClass("stacked")
|
||||
});
|
||||
@ -1312,47 +1319,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (!this.locked.bounds)
|
||||
this.draggable();
|
||||
|
||||
iQ(container)
|
||||
.mousedown(function(e) {
|
||||
self._mouseDown = {
|
||||
location: new Point(e.clientX, e.clientY),
|
||||
className: e.target.className
|
||||
};
|
||||
})
|
||||
.mouseup(function(e) {
|
||||
if (!self._mouseDown || !self._mouseDown.location || !self._mouseDown.className)
|
||||
return;
|
||||
|
||||
// Don't zoom in on clicks inside of the controls.
|
||||
var className = self._mouseDown.className;
|
||||
if (className.indexOf('title-shield') != -1 ||
|
||||
className.indexOf('name') != -1 ||
|
||||
className.indexOf('close') != -1 ||
|
||||
className.indexOf('newTabButton') != -1 ||
|
||||
className.indexOf('appTabTray') != -1 ||
|
||||
className.indexOf('appTabIcon') != -1 ||
|
||||
className.indexOf('stackExpander') != -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var location = new Point(e.clientX, e.clientY);
|
||||
|
||||
if (location.distance(self._mouseDown.location) > 1.0)
|
||||
return;
|
||||
|
||||
// Zoom into the last-active tab when the groupItem
|
||||
// is clicked, but only for non-stacked groupItems.
|
||||
var activeTab = self.getActiveTab();
|
||||
if (!self._isStacked) {
|
||||
if (activeTab)
|
||||
activeTab.zoomIn();
|
||||
else if (self.getChild(0))
|
||||
self.getChild(0).zoomIn();
|
||||
}
|
||||
|
||||
self._mouseDown = null;
|
||||
});
|
||||
|
||||
this.droppable(true);
|
||||
|
||||
this.$expander.click(function() {
|
||||
@ -1363,15 +1329,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// ----------
|
||||
// Function: setResizable
|
||||
// Sets whether the groupItem is resizable and updates the UI accordingly.
|
||||
setResizable: function GroupItem_setResizable(value) {
|
||||
setResizable: function GroupItem_setResizable(value, immediately) {
|
||||
this.resizeOptions.minWidth = 90;
|
||||
this.resizeOptions.minHeight = 90;
|
||||
|
||||
if (value) {
|
||||
this.$resizer.fadeIn();
|
||||
immediately ? this.$resizer.show() : this.$resizer.fadeIn();
|
||||
this.resizable(true);
|
||||
} else {
|
||||
this.$resizer.fadeOut();
|
||||
immediately ? this.$resizer.hide() : this.$resizer.fadeOut();
|
||||
this.resizable(false);
|
||||
}
|
||||
},
|
||||
@ -1386,39 +1352,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// TabItems will have handled the new tab and added the tabItem property.
|
||||
// We don't have to check if it's an app tab (and therefore wouldn't have a
|
||||
// TabItem), since we've just created it.
|
||||
let newItem = newTab.tabItem;
|
||||
|
||||
var self = this;
|
||||
iQ(newItem.container).css({opacity: 0});
|
||||
let $anim = iQ("<div>")
|
||||
.addClass("newTabAnimatee")
|
||||
.css({
|
||||
top: newItem.bounds.top + 5,
|
||||
left: newItem.bounds.left + 5,
|
||||
width: newItem.bounds.width - 10,
|
||||
height: newItem.bounds.height - 10,
|
||||
zIndex: 999,
|
||||
opacity: 0
|
||||
})
|
||||
.appendTo("body")
|
||||
.animate({opacity: 1}, {
|
||||
duration: 500,
|
||||
complete: function() {
|
||||
$anim.animate({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
}, {
|
||||
duration: 270,
|
||||
complete: function() {
|
||||
iQ(newItem.container).css({opacity: 1});
|
||||
newItem.zoomIn(!url);
|
||||
$anim.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
newTab.tabItem.zoomIn(!url);
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1542,6 +1476,7 @@ let GroupItems = {
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: _handleAttrModified
|
||||
// watch for icon changes on app tabs
|
||||
_handleAttrModified: function GroupItems__handleAttrModified(xulTab) {
|
||||
if (xulTab.ownerDocument.defaultView != gWindow || !xulTab.pinned)
|
||||
@ -1561,16 +1496,18 @@ let GroupItems = {
|
||||
},
|
||||
|
||||
// ----------
|
||||
// when a tab becomes pinned, add it to the app tab tray in all groups
|
||||
handleTabPin: function GroupItems_handleTabPin(xulTab) {
|
||||
// Function: addAppTab
|
||||
// Adds the given xul:tab to the app tab tray in all groups
|
||||
addAppTab: function GroupItems_addAppTab(xulTab) {
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
groupItem.addAppTab(xulTab);
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// when a tab becomes unpinned, remove it from the app tab tray in all groups
|
||||
handleTabUnpin: function GroupItems_handleTabUnpin(xulTab) {
|
||||
// Function: removeAppTab
|
||||
// Removes the given xul:tab from the app tab tray in all groups
|
||||
removeAppTab: function GroupItems_removeAppTab(xulTab) {
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
groupItem.removeAppTab(xulTab);
|
||||
});
|
||||
@ -1582,7 +1519,7 @@ let GroupItems = {
|
||||
getNextID: function GroupItems_getNextID() {
|
||||
var result = this.nextID;
|
||||
this.nextID++;
|
||||
this.save();
|
||||
this._save();
|
||||
return result;
|
||||
},
|
||||
|
||||
@ -1602,20 +1539,22 @@ let GroupItems = {
|
||||
// Function: saveAll
|
||||
// Saves GroupItems state, as well as the state of all of the groupItems.
|
||||
saveAll: function GroupItems_saveAll() {
|
||||
this.save();
|
||||
this._save();
|
||||
this.groupItems.forEach(function(groupItem) {
|
||||
groupItem.save();
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: save
|
||||
// Function: _save
|
||||
// Saves GroupItems state.
|
||||
save: function GroupItems_save() {
|
||||
_save: function GroupItems__save() {
|
||||
if (!this._inited) // too soon to save now
|
||||
return;
|
||||
|
||||
Storage.saveGroupItemsData(gWindow, {nextID:this.nextID});
|
||||
let activeGroupId = this._activeGroupItem ? this._activeGroupItem.id : null;
|
||||
Storage.saveGroupItemsData(
|
||||
gWindow, { nextID: this.nextID, activeGroupId: activeGroupId });
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1637,24 +1576,37 @@ let GroupItems = {
|
||||
// If no data, sets up blank slate (including "new tabs" groupItem).
|
||||
reconstitute: function GroupItems_reconstitute(groupItemsData, groupItemData) {
|
||||
try {
|
||||
if (groupItemsData && groupItemsData.nextID)
|
||||
this.nextID = groupItemsData.nextID;
|
||||
let activeGroupId;
|
||||
|
||||
if (groupItemsData) {
|
||||
if (groupItemsData.nextID)
|
||||
this.nextID = groupItemsData.nextID;
|
||||
if (groupItemsData.activeGroupId)
|
||||
activeGroupId = groupItemsData.activeGroupId;
|
||||
}
|
||||
|
||||
if (groupItemData) {
|
||||
for (var id in groupItemData) {
|
||||
var groupItem = groupItemData[id];
|
||||
if (this.groupItemStorageSanity(groupItem)) {
|
||||
var options = {
|
||||
dontPush: true
|
||||
dontPush: true,
|
||||
immediately: true
|
||||
};
|
||||
|
||||
new GroupItem([], Utils.extend({}, groupItem, options));
|
||||
}
|
||||
}
|
||||
}
|
||||
// set active group item
|
||||
if (activeGroupId) {
|
||||
let activeGroupItem = this.groupItem(activeGroupId);
|
||||
if (activeGroupItem)
|
||||
this.setActiveGroupItem(activeGroupItem);
|
||||
}
|
||||
|
||||
this._inited = true;
|
||||
this.save(); // for nextID
|
||||
this._save(); // for nextID
|
||||
} catch(e) {
|
||||
Utils.log("error in recons: "+e);
|
||||
}
|
||||
@ -1761,40 +1713,85 @@ let GroupItems = {
|
||||
// ----------
|
||||
// Function: newTab
|
||||
// Given a <TabItem>, files it in the appropriate groupItem.
|
||||
newTab: function GroupItems_newTab(tabItem) {
|
||||
newTab: function GroupItems_newTab(tabItem, options) {
|
||||
let activeGroupItem = this.getActiveGroupItem();
|
||||
let orphanTab = this.getActiveOrphanTab();
|
||||
// Utils.log('newTab', activeGroupItem, orphanTab);
|
||||
|
||||
// 1. Active group
|
||||
// 2. Active orphan
|
||||
// 3. First visible non-app tab (that's not the tab in question), whether it's an
|
||||
// orphan or not (make a new group if it's an orphan, add it to the group if it's
|
||||
// not)
|
||||
// 4. First group
|
||||
// 5. First orphan that's not the tab in question
|
||||
// 6. At this point there should be no groups or tabs (except for app tabs and the
|
||||
// tab in question): make a new group
|
||||
|
||||
if (activeGroupItem) {
|
||||
activeGroupItem.add(tabItem);
|
||||
} else if (orphanTab) {
|
||||
let newGroupItemBounds = orphanTab.getBoundsWithTitle();
|
||||
newGroupItemBounds.inset(-40,-40);
|
||||
let newGroupItem = new GroupItem([orphanTab, tabItem], {bounds: newGroupItemBounds});
|
||||
newGroupItem.snap();
|
||||
this.setActiveGroupItem(newGroupItem);
|
||||
} else {
|
||||
this.positionNewTabAtBottom(tabItem);
|
||||
activeGroupItem.add(tabItem, null, options);
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: positionNewTabAtBottom
|
||||
// Does what it says on the tin.
|
||||
// TODO: Make more robust and improve documentation,
|
||||
// Also, this probably belongs in tabitems.js
|
||||
// Bug 586558
|
||||
positionNewTabAtBottom: function GroupItems_positionNewTabAtBottom(tabItem) {
|
||||
let windowBounds = Items.getSafeWindowBounds();
|
||||
let orphanTabItem = this.getActiveOrphanTab();
|
||||
if (!orphanTabItem) {
|
||||
let otherTab;
|
||||
// find first visible non-app tab in the tabbar.
|
||||
gBrowser.visibleTabs.some(function(tab) {
|
||||
if (!tab.pinned && tab != tabItem.tab) {
|
||||
otherTab = tab;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
let itemBounds = new Rect(
|
||||
windowBounds.right - TabItems.tabWidth,
|
||||
windowBounds.bottom - TabItems.tabHeight,
|
||||
TabItems.tabWidth,
|
||||
TabItems.tabHeight
|
||||
);
|
||||
if (otherTab) {
|
||||
// the first visible tab belongs to a group, add the new tabItem into
|
||||
// that group
|
||||
if (otherTab.tabItem.parent) {
|
||||
let groupItem = otherTab.tabItem.parent;
|
||||
groupItem.add(tabItem);
|
||||
this.setActiveGroupItem(groupItem);
|
||||
return;
|
||||
}
|
||||
// the first visible tab is an orphan tab, set the orphan tab, and
|
||||
// create a new group for orphan tab and new tabItem
|
||||
orphanTabItem = otherTab.tabItem;
|
||||
}
|
||||
|
||||
tabItem.setBounds(itemBounds);
|
||||
if (!orphanTabItem) {
|
||||
// add the new tabItem to the first group item
|
||||
if (this.groupItems.length > 0) {
|
||||
let groupItem = this.groupItems[0];
|
||||
groupItem.add(tabItem);
|
||||
this.setActiveGroupItem(groupItem);
|
||||
return;
|
||||
}
|
||||
// set the orphan tab, and create a new group for orphan tab and
|
||||
// new tabItem
|
||||
let orphanedTabs = this.getOrphanedTabs();
|
||||
if (orphanedTabs.length > 0)
|
||||
orphanTabItem = orphanedTabs[0];
|
||||
}
|
||||
}
|
||||
|
||||
// create new group for orphan tab and new tabItem
|
||||
let tabItems;
|
||||
let newGroupItemBounds;
|
||||
// the orphan tab would be the same as tabItem when all tabs are app tabs
|
||||
// and a new tab is created.
|
||||
if (orphanTabItem && orphanTabItem.tab != tabItem.tab) {
|
||||
newGroupItemBounds = orphanTabItem.getBoundsWithTitle();
|
||||
tabItems = [orphanTabItem, tabItem];
|
||||
} else {
|
||||
tabItem.setPosition(60, 60, true);
|
||||
newGroupItemBounds = tabItem.getBounds();
|
||||
tabItems = [tabItem];
|
||||
}
|
||||
|
||||
newGroupItemBounds.inset(-40,-40);
|
||||
let newGroupItem =
|
||||
new GroupItem(tabItems, { bounds: newGroupItemBounds });
|
||||
newGroupItem.snap();
|
||||
this.setActiveGroupItem(newGroupItem);
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1825,6 +1822,7 @@ let GroupItems = {
|
||||
}
|
||||
|
||||
this._activeGroupItem = groupItem;
|
||||
this._save();
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -1909,6 +1907,13 @@ let GroupItems = {
|
||||
if (groupItems.length > 0) {
|
||||
groupItems.some(function(groupItem) {
|
||||
if (!groupItem.hidden) {
|
||||
// restore the last active tab in the group
|
||||
let activeTab = groupItem.getActiveTab();
|
||||
if (activeTab) {
|
||||
tabItem = activeTab;
|
||||
return true;
|
||||
}
|
||||
// if no tab is active, use the first one
|
||||
var child = groupItem.getChild(0);
|
||||
if (child) {
|
||||
tabItem = child;
|
||||
@ -1930,6 +1935,13 @@ let GroupItems = {
|
||||
var firstGroupItems = groupItems.slice(currentIndex + 1);
|
||||
firstGroupItems.some(function(groupItem) {
|
||||
if (!groupItem.hidden) {
|
||||
// restore the last active tab in the group
|
||||
let activeTab = groupItem.getActiveTab();
|
||||
if (activeTab) {
|
||||
tabItem = activeTab;
|
||||
return true;
|
||||
}
|
||||
// if no tab is active, use the first one
|
||||
var child = groupItem.getChild(0);
|
||||
if (child) {
|
||||
tabItem = child;
|
||||
@ -1947,6 +1959,13 @@ let GroupItems = {
|
||||
var secondGroupItems = groupItems.slice(0, currentIndex);
|
||||
secondGroupItems.some(function(groupItem) {
|
||||
if (!groupItem.hidden) {
|
||||
// restore the last active tab in the group
|
||||
let activeTab = groupItem.getActiveTab();
|
||||
if (activeTab) {
|
||||
tabItem = activeTab;
|
||||
return true;
|
||||
}
|
||||
// if no tab is active, use the first one
|
||||
var child = groupItem.getChild(0);
|
||||
if (child) {
|
||||
tabItem = child;
|
||||
|
@ -56,6 +56,7 @@
|
||||
// Possible options:
|
||||
// locked - see <Item.locked>; default is {}
|
||||
// dontPush - true if this infoItem shouldn't push away on creation; default is false
|
||||
// immediately - place the item immediately, without animation
|
||||
function InfoItem(bounds, options) {
|
||||
try {
|
||||
Utils.assertThrow(Utils.isRect(bounds), 'bounds');
|
||||
@ -105,11 +106,8 @@ function InfoItem(bounds, options) {
|
||||
this.draggable();
|
||||
|
||||
// ___ Position
|
||||
this.snap();
|
||||
|
||||
// ___ Push other objects away
|
||||
if (!options.dontPush)
|
||||
this.pushAway();
|
||||
this.snap(options.immediately);
|
||||
|
||||
this._inited = true;
|
||||
this.save();
|
||||
|
@ -187,7 +187,10 @@ Item.prototype = {
|
||||
stop: function() {
|
||||
drag.info.stop();
|
||||
drag.info = null;
|
||||
}
|
||||
},
|
||||
// The minimum the mouse must move after mouseDown in order to move an
|
||||
// item
|
||||
minDragDistance: 3
|
||||
};
|
||||
|
||||
// ___ drop
|
||||
@ -323,7 +326,10 @@ Item.prototype = {
|
||||
// ----------
|
||||
// Function: pushAway
|
||||
// Pushes all other items away so none overlap this Item.
|
||||
pushAway: function Item_pushAway() {
|
||||
//
|
||||
// Parameters:
|
||||
// immediately - boolean for doing the pushAway without animation
|
||||
pushAway: function Item_pushAway(immediately) {
|
||||
var buffer = Math.floor(Items.defaultGutter / 2);
|
||||
|
||||
var items = Items.getTopLevelItems();
|
||||
@ -496,7 +502,7 @@ Item.prototype = {
|
||||
var data = item.pushAwayData;
|
||||
var bounds = data.bounds;
|
||||
if (!bounds.equals(data.startBounds)) {
|
||||
item.setBounds(bounds);
|
||||
item.setBounds(bounds, immediately);
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -555,7 +561,10 @@ Item.prototype = {
|
||||
// ----------
|
||||
// Function: snap
|
||||
// The snap function used during groupItem creation via drag-out
|
||||
snap: function Item_snap() {
|
||||
//
|
||||
// Parameters:
|
||||
// immediately - bool for having the drag do the final positioning without animation
|
||||
snap: function Item_snap(immediately) {
|
||||
// make the snapping work with a wider range!
|
||||
var defaultRadius = Trenches.defaultRadius;
|
||||
Trenches.defaultRadius = 2 * defaultRadius; // bump up from 10 to 20!
|
||||
@ -564,7 +573,7 @@ Item.prototype = {
|
||||
var FauxDragInfo = new Drag(this,event,false,true);
|
||||
// false == isDragging, true == isFauxDrag
|
||||
FauxDragInfo.snap('none',false);
|
||||
FauxDragInfo.stop();
|
||||
FauxDragInfo.stop(immediately);
|
||||
|
||||
Trenches.defaultRadius = defaultRadius;
|
||||
},
|
||||
@ -592,64 +601,67 @@ Item.prototype = {
|
||||
// ___ mousemove
|
||||
var handleMouseMove = function(e) {
|
||||
// positioning
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
var box = self.getBounds();
|
||||
box.left = startPos.x + (mouse.x - startMouse.x);
|
||||
box.top = startPos.y + (mouse.y - startMouse.y);
|
||||
|
||||
self.setBounds(box, true);
|
||||
|
||||
// drag events
|
||||
var mouse = new Point(e.pageX, e.pageY);
|
||||
if (!startSent) {
|
||||
if (typeof self.dragOptions.start == "function")
|
||||
self.dragOptions.start.apply(self,
|
||||
[startEvent, {position: {left: startPos.x, top: startPos.y}}]);
|
||||
|
||||
startSent = true;
|
||||
if(Math.abs(mouse.x - startMouse.x) > self.dragOptions.minDragDistance ||
|
||||
Math.abs(mouse.y - startMouse.y) > self.dragOptions.minDragDistance) {
|
||||
if (typeof self.dragOptions.start == "function")
|
||||
self.dragOptions.start.apply(self,
|
||||
[startEvent, {position: {left: startPos.x, top: startPos.y}}]);
|
||||
startSent = true;
|
||||
}
|
||||
}
|
||||
if (startSent) {
|
||||
// drag events
|
||||
var box = self.getBounds();
|
||||
box.left = startPos.x + (mouse.x - startMouse.x);
|
||||
box.top = startPos.y + (mouse.y - startMouse.y);
|
||||
|
||||
if (typeof self.dragOptions.drag == "function")
|
||||
self.dragOptions.drag.apply(self, [e]);
|
||||
self.setBounds(box, true);
|
||||
|
||||
// drop events
|
||||
var best = {
|
||||
dropTarget: null,
|
||||
score: 0
|
||||
};
|
||||
if (typeof self.dragOptions.drag == "function")
|
||||
self.dragOptions.drag.apply(self, [e]);
|
||||
|
||||
droppables.forEach(function(droppable) {
|
||||
var intersection = box.intersection(droppable.bounds);
|
||||
if (intersection && intersection.area() > best.score) {
|
||||
var possibleDropTarget = droppable.item;
|
||||
var accept = true;
|
||||
if (possibleDropTarget != dropTarget) {
|
||||
var dropOptions = possibleDropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.accept == "function")
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [self]);
|
||||
// drop events
|
||||
var best = {
|
||||
dropTarget: null,
|
||||
score: 0
|
||||
};
|
||||
|
||||
droppables.forEach(function(droppable) {
|
||||
var intersection = box.intersection(droppable.bounds);
|
||||
if (intersection && intersection.area() > best.score) {
|
||||
var possibleDropTarget = droppable.item;
|
||||
var accept = true;
|
||||
if (possibleDropTarget != dropTarget) {
|
||||
var dropOptions = possibleDropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.accept == "function")
|
||||
accept = dropOptions.accept.apply(possibleDropTarget, [self]);
|
||||
}
|
||||
|
||||
if (accept) {
|
||||
best.dropTarget = possibleDropTarget;
|
||||
best.score = intersection.area();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (best.dropTarget != dropTarget) {
|
||||
var dropOptions;
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.out == "function")
|
||||
dropOptions.out.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
if (accept) {
|
||||
best.dropTarget = possibleDropTarget;
|
||||
best.score = intersection.area();
|
||||
dropTarget = best.dropTarget;
|
||||
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.over == "function")
|
||||
dropOptions.over.apply(dropTarget, [e]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (best.dropTarget != dropTarget) {
|
||||
var dropOptions;
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.out == "function")
|
||||
dropOptions.out.apply(dropTarget, [e]);
|
||||
}
|
||||
|
||||
dropTarget = best.dropTarget;
|
||||
|
||||
if (dropTarget) {
|
||||
dropOptions = dropTarget.dropOptions;
|
||||
if (dropOptions && typeof dropOptions.over == "function")
|
||||
dropOptions.over.apply(dropTarget, [e]);
|
||||
}
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
@ -724,13 +736,11 @@ Item.prototype = {
|
||||
droppable: function Item_droppable(value) {
|
||||
try {
|
||||
var $container = iQ(this.container);
|
||||
if (value)
|
||||
$container.addClass('iq-droppable');
|
||||
else {
|
||||
if (value) {
|
||||
Utils.assert(this.dropOptions, 'dropOptions');
|
||||
|
||||
$container.addClass('iq-droppable');
|
||||
} else
|
||||
$container.removeClass('iq-droppable');
|
||||
}
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
|
@ -363,11 +363,11 @@ SearchEventHandlerClass.prototype = {
|
||||
var matches = matcher.matched();
|
||||
var others = matcher.matchedTabsFromOtherWindows();
|
||||
if (event.which == event.DOM_VK_RETURN && (matches.length > 0 || others.length > 0)) {
|
||||
if (matches.length > 0)
|
||||
hideSearch(event);
|
||||
if (matches.length > 0)
|
||||
matches[0].zoomIn();
|
||||
else
|
||||
TabUtils.focus(others[0]);
|
||||
hideSearch(event);
|
||||
}
|
||||
},
|
||||
|
||||
@ -429,7 +429,8 @@ var TabHandlers = {
|
||||
// by the number of matches within the window.
|
||||
var item = iQ("<div/>")
|
||||
.addClass("inlineMatch")
|
||||
.click(function(){
|
||||
.click(function(event){
|
||||
hideSearch(event);
|
||||
TabUtils.focus(tab);
|
||||
});
|
||||
|
||||
|
@ -145,13 +145,14 @@ let Storage = {
|
||||
// Returns the data for all groupItems associated with the given window.
|
||||
readGroupItemData: function Storage_readGroupItemData(win) {
|
||||
var existingData = {};
|
||||
let data;
|
||||
try {
|
||||
existingData = JSON.parse(
|
||||
this._sessionStore.getWindowValue(win, this.GROUP_DATA_IDENTIFIER)
|
||||
);
|
||||
data = this._sessionStore.getWindowValue(win, this.GROUP_DATA_IDENTIFIER);
|
||||
if (data)
|
||||
existingData = JSON.parse(data);
|
||||
} catch (e) {
|
||||
// getWindowValue will fail if the property doesn't exist
|
||||
Utils.log("Error in readGroupItemData: "+e);
|
||||
Utils.log("Error in readGroupItemData: "+e, data);
|
||||
}
|
||||
return existingData;
|
||||
},
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user