140612: Introduce tab usage pref accessibility.tabfocus, to allow tab to go only to form elements or only to text controls. (r,sr)=(bryner,sfraser)

This commit is contained in:
akkana%netscape.com 2002-09-18 21:24:57 +00:00
Родитель c09b924557
Коммит 75743aa0f0
5 изменённых файлов: 89 добавлений и 16 удалений

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

@ -140,6 +140,8 @@ nsIContent * gLastFocusedContent = 0; // Strong reference
nsIDocument * gLastFocusedDocument = 0; // Strong reference nsIDocument * gLastFocusedDocument = 0; // Strong reference
nsIPresContext* gLastFocusedPresContext = 0; // Weak reference nsIPresContext* gLastFocusedPresContext = 0; // Weak reference
PRInt32 nsEventStateManager::sTabFocusModel = eTabFocus_unset;
PRUint32 nsEventStateManager::mInstanceCount = 0; PRUint32 nsEventStateManager::mInstanceCount = 0;
PRInt32 nsEventStateManager::gGeneralAccesskeyModifier = -1; // magic value of -1 means uninitialized PRInt32 nsEventStateManager::gGeneralAccesskeyModifier = -1; // magic value of -1 means uninitialized
@ -3286,7 +3288,7 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
if (mCurrentFocus) { if (mCurrentFocus) {
nsCOMPtr<nsIAtom> tag; nsCOMPtr<nsIAtom> tag;
mCurrentFocus->GetTag(*getter_AddRefs(tag)); mCurrentFocus->GetTag(*getter_AddRefs(tag));
if(nsHTMLAtoms::area==tag.get()) { if(nsHTMLAtoms::area==tag) {
//Focus is in an imagemap area //Focus is in an imagemap area
nsCOMPtr<nsIPresShell> presShell; nsCOMPtr<nsIPresShell> presShell;
if (mPresContext) { if (mPresContext) {
@ -3366,10 +3368,22 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
PRBool disabled = PR_TRUE; PRBool disabled = PR_TRUE;
PRBool hidden = PR_FALSE; PRBool hidden = PR_FALSE;
// Tab focus mode is constant across all windows.
// It would be nicer if ESM had a prefs callback,
// so we could store this and change behavior when it changes.
// But until the pref is exposed, that doesn't matter.
if (sTabFocusModel == eTabFocus_unset) {
sTabFocusModel = (eTabFocus_textControlsMask | eTabFocus_formElementsMask
| eTabFocus_linksMask);
nsresult rv = getPrefService();
if (NS_SUCCEEDED(rv))
mPrefService->GetIntPref("accessibility.tabfocus", &sTabFocusModel);
}
child->GetTag(*getter_AddRefs(tag)); child->GetTag(*getter_AddRefs(tag));
nsCOMPtr<nsIDOMHTMLElement> htmlElement(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLElement> htmlElement(do_QueryInterface(child));
if (htmlElement) { if (htmlElement) {
if (nsHTMLAtoms::input==tag.get()) { if (nsHTMLAtoms::input==tag) {
nsCOMPtr<nsIDOMHTMLInputElement> nextInput(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLInputElement> nextInput(do_QueryInterface(child));
if (nextInput) { if (nextInput) {
nextInput->GetDisabled(&disabled); nextInput->GetDisabled(&disabled);
@ -3377,30 +3391,49 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
nsAutoString type; nsAutoString type;
nextInput->GetType(type); nextInput->GetType(type);
if (type.EqualsIgnoreCase("hidden")) { if (type.EqualsIgnoreCase("text")) {
// It's a text field
disabled = !(sTabFocusModel & eTabFocus_textControlsMask);
}
else if (type.EqualsIgnoreCase("hidden")) {
hidden = PR_TRUE; hidden = PR_TRUE;
} }
else if (type.EqualsIgnoreCase("file")) { else if (type.EqualsIgnoreCase("file")) {
disabled = PR_TRUE; disabled = PR_TRUE;
} }
else {
// it's some other type of form element
disabled = !(sTabFocusModel & eTabFocus_formElementsMask);
} }
} }
else if (nsHTMLAtoms::select==tag.get()) { }
else if (nsHTMLAtoms::select==tag) {
// Select counts as form but not as text
disabled = !(sTabFocusModel & eTabFocus_formElementsMask);
if (!disabled) {
nsCOMPtr<nsIDOMHTMLSelectElement> nextSelect(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLSelectElement> nextSelect(do_QueryInterface(child));
if (nextSelect) { if (nextSelect) {
nextSelect->GetDisabled(&disabled); nextSelect->GetDisabled(&disabled);
nextSelect->GetTabIndex(&tabIndex); nextSelect->GetTabIndex(&tabIndex);
} }
} }
else if (nsHTMLAtoms::textarea==tag.get()) { }
else if (nsHTMLAtoms::textarea==tag) {
// it's a textarea
disabled = !(sTabFocusModel & eTabFocus_textControlsMask);
if (!disabled) {
nsCOMPtr<nsIDOMHTMLTextAreaElement> nextTextArea(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLTextAreaElement> nextTextArea(do_QueryInterface(child));
if (nextTextArea) { if (nextTextArea) {
nextTextArea->GetDisabled(&disabled); nextTextArea->GetDisabled(&disabled);
nextTextArea->GetTabIndex(&tabIndex); nextTextArea->GetTabIndex(&tabIndex);
} }
} }
else if(nsHTMLAtoms::a==tag.get()) { }
else if (nsHTMLAtoms::a==tag) {
// it's a link
disabled = !(sTabFocusModel & eTabFocus_linksMask);
nsCOMPtr<nsIDOMHTMLAnchorElement> nextAnchor(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLAnchorElement> nextAnchor(do_QueryInterface(child));
if (!disabled) {
if (nextAnchor) if (nextAnchor)
nextAnchor->GetTabIndex(&tabIndex); nextAnchor->GetTabIndex(&tabIndex);
nsAutoString href; nsAutoString href;
@ -3411,14 +3444,22 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
disabled = PR_FALSE; disabled = PR_FALSE;
} }
} }
else if(nsHTMLAtoms::button==tag.get()) { }
else if (nsHTMLAtoms::button==tag) {
// Button counts as a form element but not as text
disabled = !(sTabFocusModel & eTabFocus_formElementsMask);
if (!disabled) {
nsCOMPtr<nsIDOMHTMLButtonElement> nextButton(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLButtonElement> nextButton(do_QueryInterface(child));
if (nextButton) { if (nextButton) {
nextButton->GetTabIndex(&tabIndex); nextButton->GetTabIndex(&tabIndex);
nextButton->GetDisabled(&disabled); nextButton->GetDisabled(&disabled);
} }
} }
else if(nsHTMLAtoms::img==tag.get()) { }
else if (nsHTMLAtoms::img==tag) {
// Images are treated like links for tab focus purposes.
disabled = !(sTabFocusModel & eTabFocus_linksMask);
if (!disabled) {
nsCOMPtr<nsIDOMHTMLImageElement> nextImage(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLImageElement> nextImage(do_QueryInterface(child));
nsAutoString usemap; nsAutoString usemap;
if (nextImage) { if (nextImage) {
@ -3439,10 +3480,12 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
PRInt32 val = 0; PRInt32 val = 0;
TabIndexFrom(childArea, &val); TabIndexFrom(childArea, &val);
if (mCurrentTabIndex == val) { if (mCurrentTabIndex == val) {
//mCurrentFocus is in this map so we must start iterating past it. // mCurrentFocus is in this map so we must start
//We skip the case where mCurrentFocus has the same tab index // iterating past it.
//as mCurrentTabIndex since the next tab ordered element might // We skip the case where mCurrentFocus has the
//be before it (or after for backwards) in the child list. // same tab index as mCurrentTabIndex since the
// next tab ordered element might be before it
// (or after for backwards) in the child list.
break; break;
} }
} }
@ -3468,20 +3511,27 @@ nsEventStateManager::GetNextTabbableContent(nsIContent* aRootContent, nsIFrame*
} }
} }
} }
else if(nsHTMLAtoms::object==tag.get()) { }
else if (nsHTMLAtoms::object==tag) {
// OBJECT is treated as a form element.
disabled = !(sTabFocusModel & eTabFocus_formElementsMask);
if (!disabled) {
nsCOMPtr<nsIDOMHTMLObjectElement> nextObject(do_QueryInterface(child)); nsCOMPtr<nsIDOMHTMLObjectElement> nextObject(do_QueryInterface(child));
if (nextObject) if (nextObject)
nextObject->GetTabIndex(&tabIndex); nextObject->GetTabIndex(&tabIndex);
disabled = PR_FALSE; disabled = PR_FALSE;
} }
else if (nsHTMLAtoms::iframe==tag.get()) { }
else if (nsHTMLAtoms::iframe==tag) {
disabled = PR_FALSE; disabled = PR_FALSE;
} }
else if (nsHTMLAtoms::frame==tag.get()) { else if (nsHTMLAtoms::frame==tag) {
disabled = PR_FALSE; disabled = PR_FALSE;
} }
} }
else { // Check the tabindex attribute, unless the model specifies text only.
// If the model is unset then we'll depend on tabindex.
else if (sTabFocusModel != eTabFocus_textControlsMask) {
nsAutoString value; nsAutoString value;
child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, value); child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::disabled, value);
nsAutoString tabStr; nsAutoString tabStr;

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

@ -71,6 +71,13 @@ class nsEventStateManager : public nsSupportsWeakReference,
public nsIEventStateManager, public nsIEventStateManager,
public nsIObserver public nsIObserver
{ {
// Tab focus model bit field:
enum nsTabFocusModel {
eTabFocus_unset = 0, // unset, check preferences
eTabFocus_textControlsMask = (1<<0), // text elements
eTabFocus_formElementsMask = (1<<1), // non-text form elements
eTabFocus_linksMask = (1<<2) // links
};
public: public:
nsEventStateManager(); nsEventStateManager();
@ -273,6 +280,10 @@ protected:
// So we don't have to keep checking accessibility.browsewithcaret pref // So we don't have to keep checking accessibility.browsewithcaret pref
PRBool mBrowseWithCaret; PRBool mBrowseWithCaret;
// Tab focus policy (static, constant across the app):
// Which types of elements are in the tab order?
static PRInt32 sTabFocusModel;
// Recursion guard for tabbing // Recursion guard for tabbing
PRBool mTabbedThroughDocument; PRBool mTabbedThroughDocument;

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

@ -125,6 +125,10 @@ pref("browser.helperApps.neverAsk.openFile", "");
pref("accessibility.browsewithcaret", false); pref("accessibility.browsewithcaret", false);
pref("accessibility.warn_on_browsewithcaret", true); pref("accessibility.warn_on_browsewithcaret", true);
// Tab focus model bit field:
// 1 focuses text controls, 2 focuses other form elements, 4 adds links.
// Most users will want 1, 3, or 7.
pref("accessibility.tabfocus", 7);
pref("accessibility.usetexttospeech", ""); pref("accessibility.usetexttospeech", "");
pref("accessibility.usebrailledisplay", ""); pref("accessibility.usebrailledisplay", "");
pref("accessibility.accesskeycausesactivation", true); pref("accessibility.accesskeycausesactivation", true);

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

@ -180,6 +180,10 @@ pref("font.size.fixed.zh-CN", 16);
pref("font.size.variable.zh-TW", 15); pref("font.size.variable.zh-TW", 15);
pref("font.size.fixed.zh-TW", 16); pref("font.size.fixed.zh-TW", 16);
// Tab focus model bit field:
// 1 focuses text controls, 2 focuses other form elements, 4 adds links.
pref("accessibility.tabfocus", 1);
// Override the Windows settings: no menu key, meta accelerator key. ctrl for general access key in HTML/XUL // Override the Windows settings: no menu key, meta accelerator key. ctrl for general access key in HTML/XUL
// Use 17 for Ctrl, 18 for Option, 224 for Cmd, 0 for none // Use 17 for Ctrl, 18 for Option, 224 for Cmd, 0 for none
pref("ui.key.menuAccessKey", 0); pref("ui.key.menuAccessKey", 0);

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

@ -67,6 +67,10 @@ pref("clipboard.autocopy", true);
pref("browser.urlbar.clickSelectsAll", false); pref("browser.urlbar.clickSelectsAll", false);
// Tab focus model bit field:
// 1 focuses text controls, 2 focuses other form elements, 4 adds links.
pref("accessibility.tabfocus", 1);
// override double-click word selection behavior. // override double-click word selection behavior.
pref("layout.word_select.stop_at_punctuation", false); pref("layout.word_select.stop_at_punctuation", false);