Bug 488846, use a custom controller finding method which checks for open context menus for places, r=mak (CLOSED TREE)
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -122,33 +122,37 @@ PlacesController.prototype = {
isCommandEnabled: function PC_isCommandEnabled(aCommand) {
switch (aCommand) {
case "cmd_undo":
return PlacesUIUtils.ptm.numberOfUndoItems > 0;
case "cmd_redo":
return PlacesUIUtils.ptm.numberOfRedoItems > 0;
case "cmd_cut":
+ case "placesCmd_cut":
var nodes = this._view.getSelectionNodes();
// If selection includes history nodes there's no reason to allow cut.
for (var i = 0; i < nodes.length; i++) {
if (nodes[i].itemId == -1)
return false;
}
// Otherwise fallback to cmd_delete check.
case "cmd_delete":
+ case "placesCmd_delete":
return this._hasRemovableSelection(false);
case "placesCmd_deleteDataHost":
return this._hasRemovableSelection(false) &&
!PlacesUIUtils.privateBrowsing.privateBrowsingEnabled;
case "placesCmd_moveBookmarks":
return this._hasRemovableSelection(true);
case "cmd_copy":
+ case "placesCmd_copy":
return this._view.hasSelection;
case "cmd_paste":
+ case "placesCmd_paste":
return this._canInsert(true) && this._isClipboardDataPasteable();
case "cmd_selectAll":
if (this._view.selType != "single") {
var result = this._view.getResult();
if (result) {
var container = asContainer(result.root);
if (container.childCount > 0);
return true;
@@ -224,25 +228,29 @@ PlacesController.prototype = {
switch (aCommand) {
case "cmd_undo":
PlacesUIUtils.ptm.undoTransaction();
break;
case "cmd_redo":
PlacesUIUtils.ptm.redoTransaction();
break;
case "cmd_cut":
+ case "placesCmd_cut":
this.cut();
break;
case "cmd_copy":
+ case "placesCmd_copy":
this.copy();
break;
case "cmd_paste":
+ case "placesCmd_paste":
this.paste();
break;
case "cmd_delete":
+ case "placesCmd_delete":
this.remove("Remove Selection");
break;
case "placesCmd_deleteDataHost":
var host;
if (PlacesUtils.nodeIsHost(this._view.selectedNode)) {
var queries = this._view.selectedNode.getQueries({});
host = queries[0].domain;
}
@@ -1599,36 +1607,65 @@ var PlacesControllerDragHelper = {
var flavourSet = new FlavourSet();
var acceptedDropFlavours = this.GENERIC_VIEW_DROP_TYPES;
acceptedDropFlavours.forEach(flavourSet.appendFlavour, flavourSet);
return this.flavourSet = flavourSet;
}
};
function goUpdatePlacesCommands() {
- var placesController;
- try {
- // Or any other command...
- placesController = top.document.commandDispatcher
- .getControllerForCommand("placesCmd_open");
- }
- catch(ex) { return; }
+ // Get the controller for one of the places commands.
+ var placesController = doGetPlacesControllerForCommand("placesCmd_open");
+ if (!placesController)
+ return;
function updatePlacesCommand(aCommand) {
- var enabled = false;
- if (placesController)
- enabled = placesController.isCommandEnabled(aCommand);
- goSetCommandEnabled(aCommand, enabled);
+ goSetCommandEnabled(aCommand, placesController.isCommandEnabled(aCommand));
}
updatePlacesCommand("placesCmd_open");
updatePlacesCommand("placesCmd_open:window");
updatePlacesCommand("placesCmd_open:tab");
updatePlacesCommand("placesCmd_new:folder");
updatePlacesCommand("placesCmd_new:bookmark");
updatePlacesCommand("placesCmd_new:livemark");
updatePlacesCommand("placesCmd_new:separator");
updatePlacesCommand("placesCmd_show:info");
updatePlacesCommand("placesCmd_moveBookmarks");
updatePlacesCommand("placesCmd_reload");
updatePlacesCommand("placesCmd_reloadMicrosummary");
updatePlacesCommand("placesCmd_sortBy:name");
+ updatePlacesCommand("placesCmd_cut");
+ updatePlacesCommand("placesCmd_copy");
+ updatePlacesCommand("placesCmd_paste");
+ updatePlacesCommand("placesCmd_delete");
}
+
+function doGetPlacesControllerForCommand(aCommand)
+{
+ var placesController = top.document.commandDispatcher
+ .getControllerForCommand(aCommand);
+ if (!placesController) {
+ // If building commands for a context menu, look for an element in the
+ // current popup.
+ var element = document.popupNode;
+ while (element) {
+ var isContextMenuShown = ("_contextMenuShown" in element) && element._contextMenuShown;
+ // Check for the parent menupopup or the hbox used for toolbars
+ if ((element.localName == "menupopup" || element.localName == "hbox") &&
+ isContextMenuShown) {
+ placesController = element.controllers.getControllerForCommand(aCommand);
+ break;
+ }
+ element = element.parentNode;
+ }
+ }
+
+ return placesController;
+}
+
+function goDoPlacesCommand(aCommand)
+{
+ var controller = doGetPlacesControllerForCommand(aCommand);
+ if (controller && controller.isCommandEnabled(aCommand))
+ controller.doCommand(aCommand);
+}
+
--- a/browser/components/places/content/menu.xml
+++ b/browser/components/places/content/menu.xml
@@ -1019,21 +1019,17 @@
<property name="selType" readonly="true" onget="return 'single';"/>
<method name="buildContextMenu">
<parameter name="aPopup"/>
<body><![CDATA[
this._ensureInitialized();
this._contextMenuShown = true;
- // Activate the controller
- this.focus();
- // The above call may not always fire a consumable event for
- // commandUpdater, so we force a command update.
- window.updateCommands("focus");
+ window.updateCommands("places");
return this.controller.buildContextMenu(aPopup);
]]></body>
</method>
<method name="destroyContextMenu">
<parameter name="aPopup"/>
<body>
<![CDATA[
--- a/browser/components/places/content/placesOverlay.xul
+++ b/browser/components/places/content/placesOverlay.xul
@@ -57,50 +57,60 @@
src="chrome://browser/content/places/controller.js"/>
<script type="application/x-javascript"
src="chrome://browser/content/places/treeView.js"/>
<script type="application/x-javascript"
src="chrome://global/content/nsDragAndDrop.js"/>
<commandset id="placesCommands"
commandupdater="true"
- events="focus,sort"
+ events="focus,sort,places"
oncommandupdate="goUpdatePlacesCommands();">
<command id="placesCmd_open"
- oncommand="goDoCommand('placesCmd_open');"/>
+ oncommand="goDoPlacesCommand('placesCmd_open');"/>
<command id="placesCmd_open:window"
- oncommand="goDoCommand('placesCmd_open:window');"/>
+ oncommand="goDoPlacesCommand('placesCmd_open:window');"/>
<command id="placesCmd_open:tab"
- oncommand="goDoCommand('placesCmd_open:tab');"/>
+ oncommand="goDoPlacesCommand('placesCmd_open:tab');"/>
<command id="placesCmd_new:bookmark"
- oncommand="goDoCommand('placesCmd_new:bookmark');"/>
+ oncommand="goDoPlacesCommand('placesCmd_new:bookmark');"/>
<command id="placesCmd_new:livemark"
- oncommand="goDoCommand('placesCmd_new:livemark');"/>
+ oncommand="goDoPlacesCommand('placesCmd_new:livemark');"/>
<command id="placesCmd_new:folder"
- oncommand="goDoCommand('placesCmd_new:folder');"/>
+ oncommand="goDoPlacesCommand('placesCmd_new:folder');"/>
<command id="placesCmd_new:separator"
- oncommand="goDoCommand('placesCmd_new:separator');"/>
+ oncommand="goDoPlacesCommand('placesCmd_new:separator');"/>
<command id="placesCmd_show:info"
- oncommand="goDoCommand('placesCmd_show:info');"/>
+ oncommand="goDoPlacesCommand('placesCmd_show:info');"/>
<command id="placesCmd_rename"
- oncommand="goDoCommand('placesCmd_show:info');"
+ oncommand="goDoPlacesCommand('placesCmd_show:info');"
observes="placesCmd_show:info"/>
<command id="placesCmd_reload"
- oncommand="goDoCommand('placesCmd_reload');"/>
+ oncommand="goDoPlacesCommand('placesCmd_reload');"/>
<command id="placesCmd_reloadMicrosummary"
- oncommand="goDoCommand('placesCmd_reloadMicrosummary');"/>
+ oncommand="goDoPlacesCommand('placesCmd_reloadMicrosummary');"/>
<command id="placesCmd_sortBy:name"
- oncommand="goDoCommand('placesCmd_sortBy:name');"/>
+ oncommand="goDoPlacesCommand('placesCmd_sortBy:name');"/>
<command id="placesCmd_moveBookmarks"
- oncommand="goDoCommand('placesCmd_moveBookmarks');"/>
+ oncommand="goDoPlacesCommand('placesCmd_moveBookmarks');"/>
<command id="placesCmd_deleteDataHost"
- oncommand="goDoCommand('placesCmd_deleteDataHost');"/>
+ oncommand="goDoPlacesCommand('placesCmd_deleteDataHost');"/>
<command id="placesCmd_createBookmark"
- oncommand="goDoCommand('placesCmd_createBookmark');"/>
+ oncommand="goDoPlacesCommand('placesCmd_createBookmark');"/>
+
+ <!-- Special versions of cut/copy/paste/delete which check for an open context menu. -->
+ <command id="placesCmd_cut"
+ oncommand="goDoPlacesCommand('placesCmd_cut');"/>
+ <command id="placesCmd_copy"
+ oncommand="goDoPlacesCommand('placesCmd_copy');"/>
+ <command id="placesCmd_paste"
+ oncommand="goDoPlacesCommand('placesCmd_paste');"/>
+ <command id="placesCmd_delete"
+ oncommand="goDoPlacesCommand('placesCmd_delete');"/>
</commandset>
<popup id="placesContext"
onpopupshowing="this._view = PlacesUIUtils.getViewForNode(document.popupNode);
return this._view.buildContextMenu(this);"
onpopuphiding="this._view.destroyContextMenu();">
<menuitem id="placesContext_open"
command="placesCmd_open"
@@ -160,44 +170,44 @@
<menuseparator id="placesContext_newSeparator"/>
<menuitem id="placesContext_createBookmark"
command="placesCmd_createBookmark"
label="&cmd.bookmarkLink.label;"
accesskey="&cmd.bookmarkLink.accesskey;"
selection="link"
forcehideselection="bookmark|tagChild"/>
<menuitem id="placesContext_cut"
- command="cmd_cut"
+ command="placesCmd_cut"
label="&cutCmd.label;"
accesskey="&cutCmd.accesskey;"
closemenu="single"
selection="bookmark|folder|separator|query"
forcehideselection="tagChild|livemarkChild"/>
<menuitem id="placesContext_copy"
- command="cmd_copy"
+ command="placesCmd_copy"
label="©Cmd.label;"
closemenu="single"
accesskey="©Cmd.accesskey;"
selection="any"/>
<menuitem id="placesContext_paste"
- command="cmd_paste"
+ command="placesCmd_paste"
label="&pasteCmd.label;"
closemenu="single"
accesskey="&pasteCmd.accesskey;"
selection="any"
hideifnoinsertionpoint="true"/>
<menuseparator id="placesContext_editSeparator"/>
<menuitem id="placesContext_delete"
- command="cmd_delete"
+ command="placesCmd_delete"
label="&deleteCmd.label;"
accesskey="&deleteCmd.accesskey;"
closemenu="single"
selection="bookmark|tagChild|folder|query|dynamiccontainer|separator|host"/>
<menuitem id="placesContext_delete_history"
- command="cmd_delete"
+ command="placesCmd_delete"
label="&cmd.delete.label;"
accesskey="&cmd.delete.accesskey;"
closemenu="single"
selection="link"
forcehideselection="bookmark"/>
<menuitem id="placesContext_deleteHost"
command="placesCmd_deleteDataHost"
label="&cmd.deleteDomainData.label;"
--- a/browser/components/places/content/toolbar.xml
+++ b/browser/components/places/content/toolbar.xml
@@ -720,21 +720,17 @@
})]]></field>
<property name="selType" onget="return 'single';"/>
<method name="buildContextMenu">
<parameter name="aPopup"/>
<body><![CDATA[
this._contextMenuShown = true;
- // Activate the controller
- this.focus();
- // The above call may not always fire a consumable event for
- // commandUpdater, so we force a command update.
- window.updateCommands("focus");
+ window.updateCommands("places");
return this.controller.buildContextMenu(aPopup);
]]></body>
</method>
<method name="destroyContextMenu">
<parameter name="aPopup"/>
<body><![CDATA[
this._contextMenuShown = false;