Bug 263942 - Reload button should have middle click support. r=gavin, ui-r=beltzner
authorKlaas Heidstra <klaas1988@gmail.com>
Sun, 31 Aug 2008 23:00:59 +0200
changeset 18545 903096fec9b4d1ae332cfc040de1f48067b81382
parent 18544 371ecb35eeb40e21cba226573c5b5fc812ac9b5b
child 18546 daedaaa2059e6e435df36de117d012a1b8afe452
push id1631
push userdgottwald@mozilla.com
push dateSun, 31 Aug 2008 21:01:22 +0000
treeherdermozilla-central@903096fec9b4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin, beltzner
bugs263942
milestone1.9.1b1pre
Bug 263942 - Reload button should have middle click support. r=gavin, ui-r=beltzner
browser/base/content/browser-context.inc
browser/base/content/browser-menubar.inc
browser/base/content/browser-sets.inc
browser/base/content/browser.js
browser/base/content/browser.xul
browser/base/content/utilityOverlay.js
browser/themes/gnomestripe/browser/browser.css
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -118,17 +118,18 @@
       <menuitem id="context-forward"
                 label="&forwardCmd.label;"
                 accesskey="&forwardCmd.accesskey;"
                 chromedir="&locale.dir;"
                 command="Browser:Forward"/>
       <menuitem id="context-reload"
                 label="&reloadCmd.label;"
                 accesskey="&reloadCmd.accesskey;"
-                command="Browser:Reload"/>
+                command="Browser:ReloadOrDuplicate"
+                onclick="checkForMiddleClick(this, event);"/>
       <menuitem id="context-stop"
                 label="&stopCmd.label;"
                 accesskey="&stopCmd.accesskey;"
                 command="Browser:Stop"/>
       <menuseparator id="context-sep-stop"/>
       <menuitem id="context-bookmarkpage"
                 label="&bookmarkPageCmd2.label;"
                 accesskey="&bookmarkPageCmd2.accesskey;"
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -181,17 +181,19 @@
                 <menuitem label="&stopCmd.label;"
                           accesskey="&stopCmd.accesskey;"
                           command="Browser:Stop"
 #ifdef XP_MACOSX
                           key="key_stop_mac"/>
 #else
                           key="key_stop"/>
 #endif
-                <menuitem label="&reloadCmd.label;" accesskey="&reloadCmd.accesskey;" command="Browser:Reload" key="key_reload"/>
+                <menuitem label="&reloadCmd.label;" accesskey="&reloadCmd.accesskey;" key="key_reload"
+                          command="Browser:ReloadOrDuplicate"
+                          onclick="checkForMiddleClick(this, event);"/>
                 <menuseparator/>
                 <menu id="viewFullZoomMenu" label="&fullZoom.label;" accesskey="&fullZoom.accesskey;" onpopupshowing="FullZoom.updateMenu();">
                   <menupopup>
                     <menuitem key="key_fullZoomEnlarge" label="&fullZoomEnlargeCmd.label;" accesskey="&fullZoomEnlargeCmd.accesskey;"
                               command="cmd_fullZoomEnlarge"/>
                     <menuitem key="key_fullZoomReduce"  label="&fullZoomReduceCmd.label;"  accesskey="&fullZoomReduceCmd.accesskey;"
                               command="cmd_fullZoomReduce"/>
                     <menuseparator/>
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -96,17 +96,22 @@
     <command id="Browser:BookmarkAllTabs"
              oncommand="gBookmarkAllTabsHandler.doCommand();"
              disabled="true"/>
     <command id="Browser:Home"    oncommand="BrowserHome();"/>
     <command id="Browser:Back"    oncommand="BrowserBack();" disabled="true"/>
     <command id="Browser:Forward" oncommand="BrowserForward();" disabled="true"/>
     <command id="Browser:Stop"    oncommand="BrowserStop();" disabled="true"/>
     <command id="Browser:Reload"  oncommand="if (event.shiftKey) BrowserReloadSkipCache(); else BrowserReload()" disabled="true"/>
-    <command id="Browser:ReloadSkipCache"  oncommand="BrowserReloadSkipCache()" disabled="true"/>
+    <command id="Browser:ReloadOrDuplicate" oncommand="BrowserReloadOrDuplicate(event)" disabled="true">
+      <observes element="Browser:Reload" attribute="disabled"/>
+    </command>
+    <command id="Browser:ReloadSkipCache" oncommand="BrowserReloadSkipCache()" disabled="true">
+      <observes element="Browser:Reload" attribute="disabled"/>
+    </command>
     <command id="cmd_fullZoomReduce"  oncommand="FullZoom.reduce()"/>
     <command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
     <command id="cmd_fullZoomReset"   oncommand="FullZoom.reset()"/>
     <command id="cmd_fullZoomToggle"  oncommand="ZoomManager.toggleZoom();"/>
     <command id="Browser:OpenLocation" oncommand="openLocation();"/>
 
     <command id="Tools:Search" oncommand="BrowserSearch.webSearch();"/>    
     <command id="Tools:Downloads" oncommand="BrowserDownloadsUI();"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1182,19 +1182,19 @@ function BrowserShutdown()
 
 #ifdef XP_MACOSX
 // nonBrowserWindowStartup(), nonBrowserWindowDelayedStartup(), and
 // nonBrowserWindowShutdown() are used for non-browser windows in
 // macBrowserOverlay
 function nonBrowserWindowStartup()
 {
   // Disable inappropriate commands / submenus
-  var disabledItems = ['Browser:SavePage', 'Browser:SendLink',
-                       'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain', 'viewToolbarsMenu',
-                       'cmd_toggleTaskbar', 'viewSidebarMenuMenu', 'Browser:Reload', 'Browser:ReloadSkipCache',
+  var disabledItems = ['Browser:SavePage',
+                       'Browser:SendLink', 'cmd_pageSetup', 'cmd_print', 'cmd_find', 'cmd_findAgain',
+                       'viewToolbarsMenu', 'cmd_toggleTaskbar', 'viewSidebarMenuMenu', 'Browser:Reload',
                        'viewFullZoomMenu', 'pageStyleMenu', 'charsetMenu', 'View:PageSource', 'View:FullScreen',
                        'viewHistorySidebar', 'Browser:AddBookmarkAs', 'View:PageInfo', 'Tasks:InspectPage'];
   var element;
 
   for (var id in disabledItems)
   {
     element = document.getElementById(disabledItems[id]);
     if (element)
@@ -1429,27 +1429,44 @@ function BrowserStop()
   try {
     const stopFlags = nsIWebNavigation.STOP_ALL;
     getWebNavigation().stop(stopFlags);
   }
   catch(ex) {
   }
 }
 
-function BrowserReload()
-{
+function BrowserReloadOrDuplicate(aEvent) {
+  var backgroundTabModifier = aEvent.button == 1 ||
+#ifdef XP_MACOSX
+    aEvent.metaKey;
+#else
+    aEvent.ctrlKey;
+#endif
+  if (aEvent.shiftKey && !backgroundTabModifier) {
+    BrowserReloadSkipCache();
+    return;
+  }
+
+  var where = whereToOpenLink(aEvent, false, true);
+  if (where == "current")
+    BrowserReload();
+  else
+    openUILinkIn(getWebNavigation().currentURI.spec, where);
+}
+
+function BrowserReload() {
   const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE;
-  return BrowserReloadWithFlags(reloadFlags);
-}
-
-function BrowserReloadSkipCache()
-{
+  BrowserReloadWithFlags(reloadFlags);
+}
+
+function BrowserReloadSkipCache() {
   // Bypass proxy and cache.
   const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
-  return BrowserReloadWithFlags(reloadFlags);
+  BrowserReloadWithFlags(reloadFlags);
 }
 
 function BrowserHome()
 {
   var homePage = gHomeButton.getHomePage();
   loadOneOrMoreURIs(homePage);
 }
 
@@ -2364,18 +2381,17 @@ function getWebNavigation()
 {
   try {
     return gBrowser.webNavigation;
   } catch (e) {
     return null;
   }
 }
 
-function BrowserReloadWithFlags(reloadFlags)
-{
+function BrowserReloadWithFlags(reloadFlags) {
   /* First, we'll try to use the session history object to reload so
    * that framesets are handled properly. If we're in a special
    * window (such as view-source) that has no session history, fall
    * back on using the web navigation's reload method.
    */
 
   var webNav = getWebNavigation();
   try {
@@ -3699,46 +3715,44 @@ nsBrowserStatusHandler.prototype =
         aIID.equals(Ci.nsIXULBrowserWindow) ||
         aIID.equals(Ci.nsISupports))
       return this;
     throw Cr.NS_NOINTERFACE;
   },
 
   init : function()
   {
-    this.throbberElement        = document.getElementById("navigator-throbber");
-    this.statusMeter            = document.getElementById("statusbar-icon");
-    this.stopCommand            = document.getElementById("Browser:Stop");
-    this.reloadCommand          = document.getElementById("Browser:Reload");
-    this.reloadSkipCacheCommand = document.getElementById("Browser:ReloadSkipCache");
-    this.statusTextField        = document.getElementById("statusbar-display");
-    this.securityButton         = document.getElementById("security-button");
-    this.urlBar                 = document.getElementById("urlbar");
-    this.isImage                = document.getElementById("isImage");
+    this.throbberElement = document.getElementById("navigator-throbber");
+    this.statusMeter     = document.getElementById("statusbar-icon");
+    this.stopCommand     = document.getElementById("Browser:Stop");
+    this.reloadCommand   = document.getElementById("Browser:Reload");
+    this.statusTextField = document.getElementById("statusbar-display");
+    this.securityButton  = document.getElementById("security-button");
+    this.urlBar          = document.getElementById("urlbar");
+    this.isImage         = document.getElementById("isImage");
 
     // Initialize the security button's state and tooltip text.  Remember to reset
     // _hostChanged, otherwise onSecurityChange will short circuit.
     var securityUI = gBrowser.securityUI;
     this._hostChanged = true;
     this.onSecurityChange(null, null, securityUI.state);
   },
 
   destroy : function()
   {
     // XXXjag to avoid leaks :-/, see bug 60729
-    this.throbberElement        = null;
-    this.statusMeter            = null;
-    this.stopCommand            = null;
-    this.reloadCommand          = null;
-    this.reloadSkipCacheCommand = null;
-    this.statusTextField        = null;
-    this.securityButton         = null;
-    this.urlBar                 = null;
-    this.statusText             = null;
-    this.lastURI                = null;
+    this.throbberElement = null;
+    this.statusMeter     = null;
+    this.stopCommand     = null;
+    this.reloadCommand   = null;
+    this.statusTextField = null;
+    this.securityButton  = null;
+    this.urlBar          = null;
+    this.statusText      = null;
+    this.lastURI         = null;
   },
 
   setJSStatus : function(status)
   {
     this.jsStatus = status;
     this.updateStatusField();
   },
 
@@ -3973,20 +3987,18 @@ nsBrowserStatusHandler.prototype =
 
     var browser = gBrowser.selectedBrowser;
     if (aWebProgress.DOMWindow == content) {
 
       if ((location == "about:blank" && !content.opener) ||
            location == "") {  // Second condition is for new tabs, otherwise
                               // reload function is enabled until tab is refreshed.
         this.reloadCommand.setAttribute("disabled", "true");
-        this.reloadSkipCacheCommand.setAttribute("disabled", "true");
       } else {
         this.reloadCommand.removeAttribute("disabled");
-        this.reloadSkipCacheCommand.removeAttribute("disabled");
       }
 
       if (!gBrowser.mTabbedMode && aWebProgress.isLoadingDocument)
         gBrowser.setIcon(gBrowser.mCurrentTab, null);
 
       if (gURLBar) {
         URLBarSetURI(aLocationURI);
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -318,17 +318,18 @@
                      onpopupshowing="return FillHistoryMenu(event.target);"
                      oncommand="gotoHistoryIndex(event); event.stopPropagation();"
                      onclick="checkForMiddleClick(this, event);"/>
         </toolbarbutton>
       </toolbaritem>
 
       <toolbarbutton id="reload-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&reloadCmd.label;"
-                     command="Browser:Reload"
+                     command="Browser:ReloadOrDuplicate"
+                     onclick="checkForMiddleClick(this, event);"
                      tooltiptext="&reloadButton.tooltip;"/>
 
       <toolbarbutton id="stop-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
                      label="&stopCmd.label;"
                      command="Browser:Stop"
                      tooltiptext="&stopButton.tooltip;"/>
 
       <toolbarbutton id="home-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -253,31 +253,32 @@ function openUILinkIn( url, where, allow
   // Call focusElement(w.content) instead of w.content.focus() to make sure
   // that we don't raise the old window, since the URI we just loaded may have
   // resulted in a new frontmost window (e.g. "javascript:window.open('');").
   focusElement(w.content);
 }
 
 // Used as an onclick handler for UI elements with link-like behavior.
 // e.g. onclick="checkForMiddleClick(this, event);"
-function checkForMiddleClick(node, event)
-{
+function checkForMiddleClick(node, event) {
   // We should be using the disabled property here instead of the attribute,
   // but some elements that this function is used with don't support it (e.g.
   // menuitem).
   if (node.getAttribute("disabled") == "true")
     return; // Do nothing
 
   if (event.button == 1) {
-    /* Execute the node's oncommand.
+    /* Execute the node's oncommand or command.
      *
      * XXX: we should use node.oncommand(event) once bug 246720 is fixed.
      */
-    var fn = new Function("event", node.getAttribute("oncommand"));
-    fn.call(node, event);
+    var target = node.hasAttribute("oncommand") ? node :
+                 node.ownerDocument.getElementById(node.getAttribute("command"));
+    var fn = new Function("event", target.getAttribute("oncommand"));
+    fn.call(target, event);
 
     // If the middle-click was on part of a menu, close the menu.
     // (Menus close automatically with left-click but not with middle-click.)
     closeMenus(event.target);
   }
 }
 
 // Closes all popups that are ancestors of the node.
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -365,23 +365,23 @@ menuitem[command="Browser:Stop"],
 
 menuitem[command="Browser:Stop"][disabled],
 #context-stop[disabled] {
   list-style-image: url("moz-icon://stock/gtk-stop?size=menu&state=disabled");
 }
 
 #placesContext_reload,
 #placesContext_reloadMicrosummary,
-menuitem[command="Browser:Reload"],
+menuitem[command="Browser:ReloadOrDuplicate"],
 #context-reload,
 #context-reloadframe {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu");
 }
 
-menuitem[command="Browser:Reload"][disabled],
+menuitem[command="Browser:ReloadOrDuplicate"][disabled],
 #context-reload[disabled] {
   list-style-image: url("moz-icon://stock/gtk-refresh?size=menu&state=disabled");
 }
 
 menuitem[command="cmd_fullZoomEnlarge"] {
   list-style-image: url("moz-icon://stock/gtk-zoom-in?size=menu");
 }