mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 508477, add a flag to distinguish key focus navigation from other types of focus navigation, allows initial focused textboxes in a dialog to be selected by default, r=smaug
This commit is contained in:
parent
7f629101b9
commit
0beee44e9d
@ -1784,12 +1784,14 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && (mType == NS_FORM_INPUT_TEXT || mType == NS_FORM_INPUT_PASSWORD) &&
|
||||
SelectTextFieldOnFocus()) {
|
||||
// select the text if the field was focused by the keyboard.
|
||||
// select the text if the field was focused by the keyboard or a
|
||||
// navigation.
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
PRUint32 lastFocusMethod;
|
||||
fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
|
||||
if (lastFocusMethod & nsIFocusManager::FLAG_BYKEY) {
|
||||
if (lastFocusMethod &
|
||||
(nsIFocusManager::FLAG_BYKEY | nsIFocusManager::FLAG_BYMOVEFOCUS)) {
|
||||
nsCOMPtr<nsPresContext> presContext = GetPresContext();
|
||||
if (DispatchSelectEvent(presContext)) {
|
||||
SelectAll(presContext);
|
||||
|
@ -292,12 +292,13 @@ nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
|
||||
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
// Use FLAG_BYKEY here so that the label is scrolled to. Also,
|
||||
// within nsHTMLInputElement::PostHandleEvent, inputs will be
|
||||
// selected only when focused via a key and we want to select
|
||||
// the text on label clicks as well.
|
||||
// Use FLAG_BYMOVEFOCUS here so that the label is scrolled to.
|
||||
// Also, within nsHTMLInputElement::PostHandleEvent, inputs will
|
||||
// be selected only when focused via a key or when the navigation
|
||||
// flag is used and we want to select the text on label clicks as
|
||||
// well.
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(content);
|
||||
fm->SetFocus(elem, nsIFocusManager::FLAG_BYKEY);
|
||||
fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOVEFOCUS);
|
||||
}
|
||||
|
||||
// Dispatch a new click event to |content|
|
||||
|
@ -434,6 +434,14 @@ nsFocusManager::MoveFocus(nsIDOMWindow* aWindow, nsIDOMElement* aStartElement,
|
||||
PRINTTAGF(">> $[[%s]]\n", mFocusedContent);
|
||||
#endif
|
||||
|
||||
// use FLAG_BYMOVEFOCUS when switching focus with MoveFocus unless one of
|
||||
// the other focus methods is already set, or we're just moving to the root
|
||||
// or caret position.
|
||||
if (aType != MOVEFOCUS_ROOT && aType != MOVEFOCUS_CARET &&
|
||||
(aFlags & FOCUSMETHOD_MASK) == 0) {
|
||||
aFlags |= FLAG_BYMOVEFOCUS;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window;
|
||||
nsCOMPtr<nsIContent> startContent;
|
||||
if (aStartElement) {
|
||||
|
@ -198,6 +198,14 @@ interface nsIFocusManager : nsISupports
|
||||
*/
|
||||
const unsigned long FLAG_BYKEY = 0x2000;
|
||||
|
||||
/**
|
||||
* Focus is changing due to a call to MoveFocus. This flag will be implied
|
||||
* when MoveFocus is called except when one of the other mechanisms (mouse
|
||||
* or key) is specified, or when the type is MOVEFOCUS_ROOT or
|
||||
* MOVEFOCUS_CARET.
|
||||
*/
|
||||
const unsigned long FLAG_BYMOVEFOCUS = 0x4000;
|
||||
|
||||
// these constants are used with the aType argument to MoveFocus
|
||||
|
||||
/** move focus forward one element, used when pressing TAB */
|
||||
|
@ -470,9 +470,11 @@ function startTest()
|
||||
// the focus() method on the legend element should focus the legend if it is
|
||||
// focusable, or the first element after the legend if it is not focusable.
|
||||
if (!gPartialTabbing) {
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
var legend = getById("legend");
|
||||
expectFocusShift(function () legend.focus(),
|
||||
null, "t28", true, "focus method on unfocusable legend");
|
||||
gLastFocusMethod = 0;
|
||||
legend.tabIndex = "0";
|
||||
expectFocusShift(function () legend.focus(),
|
||||
null, "legend", true, "focus method on focusable legend");
|
||||
@ -488,7 +490,8 @@ function startTest()
|
||||
for (var k = 0; k < keys.length; k++) {
|
||||
var key = String.fromCharCode(65 + k);
|
||||
|
||||
gLastFocusMethod = fm.FLAG_BYKEY;
|
||||
// accesskeys D and G are for labels so get redirected
|
||||
gLastFocusMethod = (key == "D" || key == "G") ? fm.FLAG_BYMOVEFOCUS : fm.FLAG_BYKEY;
|
||||
|
||||
// on Windows and Linux, the shift key must be pressed for content area access keys
|
||||
if (navigator.platform.indexOf("Mac") == -1)
|
||||
@ -499,18 +502,18 @@ function startTest()
|
||||
}
|
||||
|
||||
// clicking on the labels
|
||||
gLastFocusMethod = -1;
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
expectFocusShift(function () synthesizeMouse(getById("ad"), 2, 2, { }, gChildWindow),
|
||||
null, "t29", true, "mouse on html label with content inside");
|
||||
expectFocusShift(function () synthesizeMouse(getById("ag"), 2, 2, { }, gChildWindow),
|
||||
null, "n14", true, "mouse on html label with for attribute");
|
||||
gLastFocusMethod = 0;
|
||||
expectFocusShift(function () synthesizeMouse(getById("aj"), 2, 2, { }),
|
||||
null, "o9", true, "mouse on xul label with content inside");
|
||||
expectFocusShift(function () synthesizeMouse(getById("ak"), 2, 2, { }),
|
||||
null, "n6", true, "mouse on xul label with control attribute");
|
||||
|
||||
// test accesskeys that shouldn't work
|
||||
gLastFocusMethod = 0;
|
||||
k = "o".charCodeAt(0);
|
||||
while (k++ < "v".charCodeAt(0)) {
|
||||
var key = String.fromCharCode(k);
|
||||
@ -677,10 +680,10 @@ function startTest()
|
||||
if (!gPartialTabbing)
|
||||
doCommandDispatcherTests();
|
||||
|
||||
doRemoveTests();
|
||||
|
||||
testMoveFocus();
|
||||
|
||||
doRemoveTests();
|
||||
|
||||
// tests various focus manager apis for null checks
|
||||
var exh = false;
|
||||
try {
|
||||
@ -701,6 +704,7 @@ function startTest()
|
||||
|
||||
// ---- tests for the FLAG_NOSWITCHFRAME flag
|
||||
getById("o5").focus();
|
||||
gLastFocusMethod = 0;
|
||||
gEvents = "";
|
||||
// focus is being shifted in a child, so the focus should not change
|
||||
expectFocusShift(function () fm.setFocus(getById("t20"), fm.FLAG_NOSWITCHFRAME),
|
||||
@ -741,19 +745,24 @@ function startTest()
|
||||
$("innerbox").appendChild(textbox2);
|
||||
textbox2.inputField.id = "innerinput2";
|
||||
|
||||
gLastFocusMethod = 0;
|
||||
expectFocusShift(function () textbox2.focus(),
|
||||
null, "innerinput2", true, "focus on textbox");
|
||||
gLastFocusMethod = fm.FLAG_BYKEY;
|
||||
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
||||
null, "innerinput1", true, "shift+tab on textbox");
|
||||
|
||||
textbox1.tabIndex = 2;
|
||||
textbox2.tabIndex = 2;
|
||||
gLastFocusMethod = 0;
|
||||
expectFocusShift(function () textbox2.focus(),
|
||||
null, "innerinput2", true, "focus on textbox with tabindex set");
|
||||
gLastFocusMethod = fm.FLAG_BYKEY;
|
||||
expectFocusShift(function () synthesizeKey("VK_TAB", { shiftKey: true }),
|
||||
null, "innerinput1", true, "shift+tab on textbox with tabindex set");
|
||||
|
||||
setFocusTo("t9", window);
|
||||
gLastFocusMethod = -1;
|
||||
window.openDialog("focus_window2.xul", "_blank", "chrome", otherWindowFocused, null);
|
||||
}
|
||||
|
||||
@ -814,6 +823,7 @@ function testMoveFocus()
|
||||
|
||||
// moving focus while an element is already focused
|
||||
var newFocus;
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
var expectedFirst = gPartialTabbing ? "t3" : "t1";
|
||||
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
|
||||
window, expectedFirst, true, "moveFocus to first null window null content");
|
||||
@ -823,6 +833,7 @@ function testMoveFocus()
|
||||
window, "last", true, "moveFocus to last null window null content");
|
||||
is(newFocus, fm.focusedElement, "moveFocus to last null window null content return value");
|
||||
|
||||
gLastFocusMethod = 0;
|
||||
newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
|
||||
is(newFocus, null, "moveFocus to root null window null content return value");
|
||||
is(fm.focusedWindow, window, "moveFocus to root null window null content focusedWindow");
|
||||
@ -832,6 +843,7 @@ function testMoveFocus()
|
||||
fm.clearFocus(window);
|
||||
gEvents = "";
|
||||
gLastFocus = null;
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FIRST, 0),
|
||||
window, expectedFirst, true, "moveFocus to first null window null content no focus");
|
||||
is(newFocus, fm.focusedElement, "moveFocus to first null window null content no focus return value");
|
||||
@ -843,6 +855,7 @@ function testMoveFocus()
|
||||
is(newFocus, fm.focusedElement, "moveFocus to last null window null content no focus return value");
|
||||
fm.clearFocus(window);
|
||||
gEvents = "";
|
||||
gLastFocusMethod = 0;
|
||||
newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_ROOT, 0);
|
||||
is(newFocus, null, "moveFocus to root null window null content no focus return value");
|
||||
is(fm.focusedWindow, window, "moveFocus to root null window null content no focus focusedWindow");
|
||||
@ -850,6 +863,7 @@ function testMoveFocus()
|
||||
|
||||
// moving focus from a specified element
|
||||
setFocusTo("t6", window);
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
expectFocusShift(function () newFocus = fm.moveFocus(null, getById("specialroot"), fm.MOVEFOCUS_FIRST, 0),
|
||||
window, "t3", true, "moveFocus to first null window with content");
|
||||
// XXXndeakin P3 this doesn't work
|
||||
@ -875,6 +889,7 @@ function testMoveFocus()
|
||||
// move focus to root in child window
|
||||
setFocusTo("t6", window);
|
||||
var childroot = getById("t" + kChildDocumentRootIndex);
|
||||
gLastFocusMethod = 0;
|
||||
newFocus = fm.moveFocus(gChildWindow, null, fm.MOVEFOCUS_ROOT, 0),
|
||||
is(newFocus, childroot, "moveFocus to root child window null content return value");
|
||||
is(fm.focusedWindow, gChildWindow, "moveFocus to root child window null content focusedWindow");
|
||||
@ -919,6 +934,24 @@ function testMoveFocus()
|
||||
is(fm.focusedElement, getById("t24"), "move caret away onto link");
|
||||
|
||||
prefs.setBoolPref("accessibility.browsewithcaret", false);
|
||||
|
||||
var t19 = getById("t19");
|
||||
t19.setSelectionRange(0, 0);
|
||||
setFocusTo("t18", gChildWindow);
|
||||
|
||||
gLastFocusMethod = fm.FLAG_BYMOVEFOCUS;
|
||||
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, 0),
|
||||
gChildWindow, t19, true, "moveFocus to next textbox");
|
||||
is(t19.selectionStart, 0, "input focused after moveFocus selectionStart");
|
||||
is(t19.selectionEnd, 5, "input focused after moveFocus selectionEnd");
|
||||
|
||||
t19.setSelectionRange(0, 0);
|
||||
setFocusTo("t18", gChildWindow);
|
||||
gLastFocusMethod = fm.FLAG_BYKEY;
|
||||
expectFocusShift(function () newFocus = fm.moveFocus(null, null, fm.MOVEFOCUS_FORWARD, fm.FLAG_BYKEY),
|
||||
gChildWindow, t19, true, "moveFocus to next textbox by key");
|
||||
is(t19.selectionStart, 0, "input focused after moveFocus by key selectionStart");
|
||||
is(t19.selectionEnd, 5, "input focused after moveFocus by key selectionEnd");
|
||||
}
|
||||
|
||||
function otherWindowFocused(otherWindow)
|
||||
|
@ -204,7 +204,7 @@ nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
fm->MoveFocus(win, from,
|
||||
forward ? nsIFocusManager::MOVEFOCUS_FORWARD :
|
||||
nsIFocusManager::MOVEFOCUS_BACKWARD,
|
||||
0, getter_AddRefs(result));
|
||||
nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user