Bug 686196 - F6 should switch between the folder pane and the account central pane when applicable; r=asuth
authorJim Porter <squibblyflabbetydoo@gmail.com>
Fri, 16 Sep 2011 23:33:03 -0500
changeset 9189 295d8878ce8a49a2d5104b2372fe16e1a70fba09
parent 9188 6d68cf105f8d5e702d964676cdebbedfd2d7b3a7
child 9190 108bd8f798118773383af335d8536f474d0e747b
push id230
push userbugzilla@standard8.plus.com
push dateTue, 08 Nov 2011 22:55:24 +0000
treeherdercomm-beta@63dad5648415 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs686196
Bug 686196 - F6 should switch between the folder pane and the account central pane when applicable; r=asuth
mail/base/content/folderDisplay.js
mail/base/content/mail3PaneWindowCommands.js
mail/base/content/messenger.xul
mail/test/mozmill/folder-display/test-pane-focus.js
mail/themes/gnomestripe/mail/accountCentral.css
mail/themes/pinstripe/mail/accountCentral.css
mail/themes/qute/mail/accountCentral.css
mailnews/base/content/msgAccountCentral.js
--- a/mail/base/content/folderDisplay.js
+++ b/mail/base/content/folderDisplay.js
@@ -261,27 +261,27 @@ FolderDisplayWidget.prototype = {
     if (this.view.dbView)
       return this.view.dbView.selection;
     else
       return null;
   },
 
   /**
    * Determine which pane currently has focus (one of the folder pane, thread
-   * pane, or message pane). The message pane node is the common ancestor of
-   * the single- and multi-message content windows. When changing focus to the
-   * message pane, be sure to focus the appropriate content window in addition
-   * to the messagepanebox (doing both is required in order to blur the
-   * previously-focused chrome element).
+   * pane, message pane, or account central pane). The message pane node is the
+   * common ancestor of the single- and multi-message content windows. When
+   * changing focus to the message pane, be sure to focus the appropriate
+   * content window in addition to the messagepanebox (doing both is required in
+   * order to blur the previously-focused chrome element).
    *
    * @return the focused pane
    */
   get focusedPane() {
     let panes = [document.getElementById(id) for each (id in [
-      "threadTree", "folderTree", "messagepanebox"
+      "threadTree", "folderTree", "messagepanebox", "accountCentralPane"
     ])];
 
     let currentNode = top.document.activeElement;
 
     while (currentNode) {
       if (panes.indexOf(currentNode) != -1)
         return currentNode;
 
--- a/mail/base/content/mail3PaneWindowCommands.js
+++ b/mail/base/content/mail3PaneWindowCommands.js
@@ -1107,20 +1107,26 @@ function SetFocusThreadPaneIfNotOnMessag
  * @param event the event that triggered us
  */
 function SwitchPaneFocus(event)
 {
   let messagePane = GetMessagePane();
 
   // First, build an array of panes to cycle through based on our current state.
   // This will usually be something like [threadPane, messagePane, folderPane].
-  let panes = [GetThreadTree()];
+  let panes = [];
+  if (gFolderDisplay.isAccountCentralDisplayed) {
+    panes.push(document.getElementById("accountCentralPane"));
+  }
+  else {
+    panes.push(GetThreadTree());
 
-  if (!IsMessagePaneCollapsed())
-    panes.push(messagePane);
+    if (!IsMessagePaneCollapsed())
+      panes.push(messagePane);
+  }
 
   if (gFolderDisplay.folderPaneVisible)
     panes.push(document.getElementById("folderTree"));
 
   // Find our focused element in the array. If focus is not on one of the main
   // panes (it's probably on the toolbar), then act as if it's on the thread
   // tree.
   let focusedElement = gFolderDisplay.focusedPane;
--- a/mail/base/content/messenger.xul
+++ b/mail/base/content/messenger.xul
@@ -306,17 +306,18 @@
 
             <vbox flex="1">
               <box orient="vertical" id="messagesBox" flex="1">
                 <deck id="displayDeck" flex="1" selectedIndex="0"
                       minheight="100" height="100" persist="height"
                       >
                   <!-- first panel in displayDeck is Account Central -->
                   <vbox id="accountCentralBox" flex="1">
-                    <iframe name="accountCentralPane" width="150" flex="1" src="about:blank"/>
+                    <iframe name="accountCentralPane" id="accountCentralPane"
+                            width="150" flex="1" src="about:blank"/>
                   </vbox>
                   <!-- The threadPaneBox is the basis for the vertical view and you
                        should not put anything in it, because the messagepane will
                        get transplanted in there. (In the vertical view, the elements
                        end up being: threadPaneBox, threadpane-splitter, messagepanebox)
                     -->
                   <!-- second panel is the threadPane -->
                   <hbox id="threadPaneBox">
--- a/mail/test/mozmill/folder-display/test-pane-focus.js
+++ b/mail/test/mozmill/folder-display/test-pane-focus.js
@@ -36,44 +36,50 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Test that cycling through the focus of the 3pane's panes works correctly.
  */
 var MODULE_NAME = "test-pane-focus";
 
 var RELATIVE_ROOT = "../shared-modules";
-var MODULE_REQUIRES = ["folder-display-helpers"];
+var MODULE_REQUIRES = ["folder-display-helpers", "window-helpers"];
+
+var elib = {};
+Cu.import('resource://mozmill/modules/elementslib.js', elib);
 
 var folder;
 
 function setupModule(module) {
   let fdh = collector.getModule("folder-display-helpers");
   fdh.installInto(module);
+  let wh = collector.getModule("window-helpers");
+  wh.installInto(module);
 
   folder = create_folder("PaneFocus");
   let msg1 = create_thread(1);
   thread = create_thread(3);
   let msg2 = create_thread(1);
   add_sets_to_folders([folder], [msg1, thread, msg2]);
 
   be_in_folder(folder);
   make_display_threaded();
   collapse_all_threads();
 }
 
 /**
  * Get the currently-focused pane in the 3pane. One of the folder pane, thread
- * pane, or message pane (single- or multi-message).
+ * pane, message pane (single- or multi-message), or account central pane.
  *
  * @return the focused pane
  */
 function get_focused_pane() {
   let panes = [mc.e(id) for each (id in [
-    "threadTree", "folderTree", "messagepane", "multimessage"
+    "threadTree", "folderTree", "messagepane", "multimessage",
+    "accountCentralPane"
   ])];
 
   let currentNode = mc.window.top.document.activeElement;
 
   while (currentNode) {
     if (panes.indexOf(currentNode) != -1)
       return currentNode;
 
@@ -83,17 +89,17 @@ function get_focused_pane() {
 }
 
 /**
  * Check that it's possible to cycle through the 3pane's panes forward and
  * backward.
  *
  * @param multimessage true if the multimessage pane should be active
  */
-function check_pane_cycling(multimessage) {
+function check_folder_pane_cycling(multimessage) {
   let folderPane = mc.e("folderTree");
   let threadPane = mc.e("threadTree");
   let messagePane = mc.e(multimessage ? "multimessage" : "messagepane");
 
   folderPane.focus();
 
   mc.keypress(null, "VK_F6", {});
   assert_equals(threadPane, get_focused_pane());
@@ -105,38 +111,93 @@ function check_pane_cycling(multimessage
   mc.keypress(null, "VK_F6", {shiftKey: true});
   assert_equals(messagePane, get_focused_pane());
   mc.keypress(null, "VK_F6", {shiftKey: true});
   assert_equals(threadPane, get_focused_pane());
   mc.keypress(null, "VK_F6", {shiftKey: true});
   assert_equals(folderPane, get_focused_pane());
 }
 
+function test_account_central() {
+  be_in_folder(folder.rootFolder);
+
+  let folderPane = mc.e("folderTree");
+  let accountCentralPane = mc.e("accountCentralPane");
+
+  folderPane.focus();
+
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(accountCentralPane, get_focused_pane());
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(folderPane, get_focused_pane());
+
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  assert_equals(accountCentralPane, get_focused_pane());
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  assert_equals(folderPane, get_focused_pane());
+}
+
+function test_account_central_focus_tweaks() {
+  be_in_folder(folder.rootFolder);
+
+  let folderPane = mc.e("folderTree");
+  let accountCentralPane = mc.e("accountCentralPane");
+
+  folderPane.focus();
+
+  // Ensure we focus the first clickable item in the account central pane.
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(accountCentralPane.contentDocument.activeElement.value,
+                "View settings for this account");
+
+  // Ensure that focusing elsewhere in the 3pane and then returning to account
+  // central maintains the previous focus.
+  mc.keypress(null, "VK_TAB", {});
+  let focusedElement = accountCentralPane.contentDocument.activeElement;
+  assert_equals(focusedElement.value, "Create a new account");
+
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(accountCentralPane.contentDocument.activeElement,
+                focusedElement);
+
+  // Ensure that opening a dialog from account central and closing it maintains
+  // focus.
+  plan_for_modal_dialog("mail:autoconfig", function(acc) {
+    close_window(acc);
+  });
+  mc.click(new elib.Elem(focusedElement));
+  let acc = wait_for_modal_dialog("mail:autoconfig");
+
+  assert_equals(accountCentralPane.contentDocument.activeElement,
+                focusedElement);
+}
+
 function test_no_messages_selected() {
   be_in_folder(folder);
 
   // Select nothing
   select_none();
-  check_pane_cycling(false);
+  check_folder_pane_cycling(false);
 }
 
 function test_one_message_selected() {
   be_in_folder(folder);
 
   // Select a message
   select_click_row(0);
-  check_pane_cycling(false);
+  check_folder_pane_cycling(false);
 }
 
 function test_n_messages_selected() {
   be_in_folder(folder);
 
   // Select a thread
   select_click_row(1);
-  check_pane_cycling(true);
+  check_folder_pane_cycling(true);
 }
 
 function test_between_tab_and_single_message() {
   be_in_folder(folder);
   select_click_row(0);
   let tab = open_selected_message_in_new_tab(true);
 
   select_click_row(2);
--- a/mail/themes/gnomestripe/mail/accountCentral.css
+++ b/mail/themes/gnomestripe/mail/accountCentral.css
@@ -104,16 +104,21 @@ separator.thin {
 .acctCentralLinkText:hover {
   color: -moz-nativehyperlinktext;
 }
 
 .acctCentralLinkText:active {
   color: -moz-activehyperlinktext;
 }
 
+.acctCentralLinkText:-moz-focusring {
+  outline: 1px dotted -moz-nativehyperlinktext;
+  outline-offset: -1px;
+}
+
 #ReadMessages label {
   background: url("chrome://messenger/skin/accountcentral/read-messages.png")  no-repeat !important;
 }
 
 #ReadMessages label:-moz-locale-dir(rtl) {
   background: url("chrome://messenger/skin/accountcentral/read-messages.png") right no-repeat !important;
 }
 
--- a/mail/themes/pinstripe/mail/accountCentral.css
+++ b/mail/themes/pinstripe/mail/accountCentral.css
@@ -109,16 +109,21 @@ separator.thin {
   color: -moz-nativehyperlinktext;
   text-decoration: underline;
 }
 
 .acctCentralLinkText:active {
   color: -moz-activehyperlinktext;
 }
 
+.acctCentralLinkText:-moz-focusring {
+  outline: 1px dotted -moz-nativehyperlinktext;
+  outline-offset: -1px;
+}
+
 #ReadMessages label {
   background: url("chrome://messenger/skin/accountcentral/mailbox.png")  no-repeat !important;
   -moz-padding-start: 50px;
   font-size: 11px;
   padding-top: 7px;
 }
 
 #ComposeMessage label {
--- a/mail/themes/qute/mail/accountCentral.css
+++ b/mail/themes/qute/mail/accountCentral.css
@@ -107,16 +107,21 @@ separator.thin {
 .acctCentralLinkText:hover {
   color: -moz-NativehyperlinkText;
 }
 
 .acctCentralLinkText:hover:active {
   color: -moz-html-CellHighlight;
 }
 
+.acctCentralLinkText:-moz-focusring {
+  outline: 1px dotted -moz-NativeHyperlinkText;
+  outline-offset: -1px;
+}
+
 #ReadMessages label {
   background: url("chrome://messenger/skin/accountcentral/read-messages.png") no-repeat !important;
 }
 
 #ReadMessages label:-moz-locale-dir(rtl) {
   background: url("chrome://messenger/skin/accountcentral/read-messages.png") right no-repeat !important;
 }
 
--- a/mailnews/base/content/msgAccountCentral.js
+++ b/mailnews/base/content/msgAccountCentral.js
@@ -92,16 +92,25 @@ function OnInit()
                                                     acctName]);
 
         titleElement.setAttribute("value", title);
 
         // Display and collapse items presented to the user based on account type
         var protocolInfo = Components.classes["@mozilla.org/messenger/protocol/info;1?type=" + serverType];
         protocolInfo = protocolInfo.getService(Components.interfaces.nsIMsgProtocolInfo);
         ArrangeAccountCentralItems(selectedServer, protocolInfo, msgFolder);
+
+        // If something directly focuses the window and nothing else inside has
+        // focus, then focus on the first element. This allows scrolling with
+        // the arrow keys to work properly when hitting F6 from the folder pane.
+        window.addEventListener("focus", function(e) {
+            if (e.explicitOriginalTarget == window &&
+                document.commandDispatcher.focusedElement === null)
+                document.commandDispatcher.advanceFocus();
+        }, false);
     }
     catch(ex) {
         dump("Error -> " + ex + "\n");
     }
 }
  
 // Show items in the AccountCentral page depending on the capabilities
 // of the given account