author | Jim Mathies <jmathies@mozilla.com> |
Tue, 19 Feb 2013 19:51:02 -0600 | |
changeset 122441 | d3ee65f9f8c80f3d5cb7872b18d26b73df9be616 |
parent 122440 | 8b45c32b6028a944c3dddd538d5d9320c089c306 |
child 122442 | 17b80182ebd8b4502d1bef94b487018631794620 |
push id | 24342 |
push user | ryanvm@gmail.com |
push date | Thu, 21 Feb 2013 13:05:06 +0000 |
treeherder | mozilla-central@702d2814efbf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mbrubeck |
bugs | 782810 |
milestone | 22.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/metro/base/content/ContextCommands.js +++ b/browser/metro/base/content/ContextCommands.js @@ -18,73 +18,215 @@ var ContextCommands = { get docRef() { return Browser.selectedBrowser.contentWindow.document; }, /* * Context menu handlers */ + // Text specific + copy: function cc_copy() { let target = ContextMenuUI.popupState.target; if (target.localName == "browser") { + // content if (ContextMenuUI.popupState.string != "undefined") { this.clipboard.copyString(ContextMenuUI.popupState.string, this.docRef); + this.showToast(Strings.browser.GetStringFromName("selectionHelper.textCopied")); } else { let x = ContextMenuUI.popupState.x; let y = ContextMenuUI.popupState.y; let json = {x: x, y: y, command: "copy" }; target.messageManager.sendAsyncMessage("Browser:ContextCommand", json); } } else { + // chrome target.editor.copy(); + this.showToast(Strings.browser.GetStringFromName("selectionHelper.textCopied")); } if (target) target.focus(); }, paste: function cc_paste() { let target = ContextMenuUI.popupState.target; if (target.localName == "browser") { + // content let x = ContextMenuUI.popupState.x; let y = ContextMenuUI.popupState.y; let json = {x: x, y: y, command: "paste" }; target.messageManager.sendAsyncMessage("Browser:ContextCommand", json); } else { + // chrome target.editor.paste(Ci.nsIClipboard.kGlobalClipboard); target.focus(); } }, pasteAndGo: function cc_pasteAndGo() { let target = ContextMenuUI.popupState.target; target.editor.selectAll(); target.editor.paste(Ci.nsIClipboard.kGlobalClipboard); BrowserUI.goToURI(); }, + select: function cc_select() { + let contextInfo = { name: "", + json: ContextMenuUI.popupState, + target: ContextMenuUI.popupState.target }; + SelectionHelperUI.openEditSession(contextInfo); + }, + selectAll: function cc_selectAll() { let target = ContextMenuUI.popupState.target; if (target.localName == "browser") { + // content let x = ContextMenuUI.popupState.x; let y = ContextMenuUI.popupState.y; let json = {x: x, y: y, command: "select-all" }; target.messageManager.sendAsyncMessage("Browser:ContextCommand", json); + let contextInfo = { name: "", + json: ContextMenuUI.popupState, + target: ContextMenuUI.popupState.target }; + SelectionHelperUI.attachEditSession(contextInfo); } else { + // chrome target.editor.selectAll(); target.focus(); } }, - openInNewTab: function cc_openInNewTab() { + // called on display of the search text menu item + searchTextSetup: function cc_searchTextSetup(aRichListItem, aSearchString) { + let defaultURI; + let defaultName; + try { + let defaultPB = Services.prefs.getDefaultBranch(null); + const nsIPLS = Ci.nsIPrefLocalizedString; + defaultName = defaultPB.getComplexValue("browser.search.defaultenginename", nsIPLS).data; + let defaultEngine = Services.search.getEngineByName(defaultName); + defaultURI = defaultEngine.getSubmission(aSearchString).uri.spec; + } catch (ex) { + Cu.reportError(ex); + return false; + } + // label child node + let label = Services.strings + .createBundle("chrome://browser/locale/browser.properties") + .formatStringFromName("browser.search.contextTextSearchLabel", + [defaultName], 1); + aRichListItem.childNodes[0].setAttribute("value", label); + aRichListItem.setAttribute("searchString", defaultURI); + return true; + }, + + searchText: function cc_searchText(aRichListItem) { + let defaultURI = aRichListItem.getAttribute("searchString"); + aRichListItem.childNodes[0].setAttribute("value", ""); + aRichListItem.setAttribute("searchString", ""); + BrowserUI.newTab(defaultURI, Browser.selectedTab); + }, + + // Link specific + + openLinkInNewTab: function cc_openLinkInNewTab() { BrowserUI.newTab(ContextMenuUI.popupState.linkURL, Browser.selectedTab); }, + copyLink: function cc_copyLink() { + this.clipboard.copyString(ContextMenuUI.popupState.linkURL, + this.docRef); + this.showToast(Strings.browser.GetStringFromName("selectionHelper.linkCopied")); + }, + + bookmarkLink: function cc_bookmarkLink() { + let state = ContextMenuUI.popupState; + let uri = Util.makeURI(state.linkURL); + let title = state.linkTitle || state.linkURL; + + try { + Bookmarks.addForURI(uri, title); + } catch (e) { + return; + } + + this.showToast(Strings.browser.GetStringFromName("alertLinkBookmarked")); + }, + + // Image specific + + saveImageToLib: function cc_saveImageToLib() { + this.saveToWinLibrary("Pict"); + }, + + copyImage: function cc_copyImage() { + // copy to clibboard + this.sendCommand("copy-image-contents"); + }, + + copyImageSrc: function cc_copyImageSrc() { + this.clipboard.copyString(ContextMenuUI.popupState.mediaURL, + this.docRef); + this.showToast(Strings.browser.GetStringFromName("selectionHelper.linkCopied")); + }, + + openImageInNewTab: function cc_openImageInNewTab() { + BrowserUI.newTab(ContextMenuUI.popupState.mediaURL, Browser.selectedTab); + }, + + // Video specific + + saveVideoToLib: function cc_saveVideoToLib() { + this.saveToWinLibrary("Vids"); + }, + + copyVideoSrc: function cc_copyVideoSrc() { + this.clipboard.copyString(ContextMenuUI.popupState.mediaURL, + this.docRef); + this.showToast(Strings.browser.GetStringFromName("selectionHelper.linkCopied")); + }, + + openVideoInNewTab: function cc_openVideoInNewTab() { + BrowserUI.newTab(ContextMenuUI.popupState.mediaURL, Browser.selectedTab); + }, + + openVideoInFullscreen: function cc_openVideoInFullscreen() { + // XXX currently isn't working. + this.sendCommand('videotab'); + }, + + // Bookmarks + + editBookmark: function cc_editBookmark() { + let target = ContextMenuUI.popupState.target; + target.startEditing(); + }, + + removeBookmark: function cc_removeBookmark() { + let target = ContextMenuUI.popupState.target; + target.remove(); + }, + + // App bar + + findInPage: function cc_findInPage() { + FindHelperUI.show(); + }, + + viewOnDesktop: function cc_viewOnDesktop() { + Appbar.onViewOnDesktop(); + }, + + /* + * Utilities + */ + saveToWinLibrary: function cc_saveToWinLibrary(aType) { let popupState = ContextMenuUI.popupState; let browser = popupState.target; // ContentAreaUtils internalSave relies on various desktop related prefs, // values, and functionality. We want to be more direct by saving the // image to the users Windows Library. If users want to specify the // save location they can use the context menu option 'Save (type) To'. @@ -110,105 +252,27 @@ var ContextCommands = { targetFile : saveLocationPath, sourceCacheKey : null, sourcePostData : null, bypassCache : false, initiatingWindow : this.docRef.defaultView }); }, - // Video specific - - saveVideo: function cc_saveVideo() { - this.saveToWinLibrary("Vids"); - }, - - saveVideoTo: function cc_saveVideoTo() { - this.saveFileAs(ContextMenuUI.popupState); - }, - - // Image specific - - saveImageToLib: function cc_saveImageToLib() { - this.saveToWinLibrary("Pict"); - }, - - copyImage: function cc_copyImage() { - // copy to clibboard - this.sendCommand("copy-image-contents"); - }, - - copyImageLink: function cc_copyImage() { - this.clipboard.copyString(ContextMenuUI.popupState.mediaURL, - this.docRef); - }, - - openImageInNewTab: function cc_openImageInNewTab() { - BrowserUI.newTab(ContextMenuUI.popupState.mediaURL, Browser.selectedTab); - }, - - copyLink: function cc_copyLink() { - this.clipboard.copyString(ContextMenuUI.popupState.linkURL, - this.docRef); - }, - - copyEmail: function cc_copyEmail() { - this.clipboard.copyString(ContextMenuUI.popupState.linkURL.substr(ContextMenuUI.popupState.linkURL.indexOf(':')+1), - this.docRef); - }, - - copyPhone: function cc_copyPhone() { - this.clipboard.copyString(ContextMenuUI.popupState.linkURL.substr(ContextMenuUI.popupState.linkURL.indexOf(':')+1), - this.docRef); - }, - - bookmarkLink: function cc_bookmarkLink() { - let state = ContextMenuUI.popupState; - let uri = Util.makeURI(state.linkURL); - let title = state.linkTitle || state.linkURL; - - try { - Bookmarks.addForURI(uri, title); - } catch (e) { - return; - } - - let message = Strings.browser.GetStringFromName("alertLinkBookmarked"); + showToast: function showToast(aString) { let toaster = Cc["@mozilla.org/toaster-alerts-service;1"].getService(Ci.nsIAlertsService); - toaster.showAlertNotification(null, message, "", false, "", null); + toaster.showAlertNotification(null, aString, "", false, "", null); }, sendCommand: function cc_playVideo(aCommand) { // Send via message manager over to ContextMenuHandler let browser = ContextMenuUI.popupState.target; browser.messageManager.sendAsyncMessage("Browser:ContextCommand", { command: aCommand }); }, - editBookmark: function cc_editBookmark() { - let target = ContextMenuUI.popupState.target; - target.startEditing(); - }, - - removeBookmark: function cc_removeBookmark() { - let target = ContextMenuUI.popupState.target; - target.remove(); - }, - - findInPage: function cc_findInPage() { - FindHelperUI.show(); - }, - - viewOnDesktop: function cc_viewOnDesktop() { - Appbar.onViewOnDesktop(); - }, - - /* - * Utilities - */ - /* * isAccessibleDirectory * * Test to see if the directory exists and is writable. */ isAccessibleDirectory: function isAccessibleDirectory(aDirectory) { return aDirectory && aDirectory.exists() && aDirectory.isDirectory() && aDirectory.isWritable();
--- a/browser/metro/base/content/browser.xul +++ b/browser/metro/base/content/browser.xul @@ -52,31 +52,31 @@ </broadcasterset> <observerset id="observerset"> <observes id="observe_contentShowing" element="bcast_contentShowing" attribute="disabled" onbroadcast="BrowserUI.updateUIFocus();"/> </observerset> <commandset id="mainCommandSet"> <!-- basic navigation --> - <command id="cmd_back" label="&back.label;" disabled="true" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_forward" label="&forward.label;" disabled="true" oncommand="CommandUpdater.doCommand(this.id);" observes="bcast_urlbarState"/> + <command id="cmd_back" disabled="true" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_forward" disabled="true" oncommand="CommandUpdater.doCommand(this.id);" observes="bcast_urlbarState"/> <command id="cmd_handleBackspace" oncommand="BrowserUI.handleBackspace();" /> <command id="cmd_handleShiftBackspace" oncommand="BrowserUI.handleShiftBackspace();" /> - <command id="cmd_reload" label="&reload.label;" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_reload" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_forceReload" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_stop" label="&stop.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_go" label="&go.label;" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_stop" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_go" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_openLocation" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_home" oncommand="CommandUpdater.doCommand(this.id);"/> <!-- tabs --> - <command id="cmd_newTab" label="&newtab.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_closeTab" label="&closetab.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_undoCloseTab" label="&undoclosetab.label;" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_newTab" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_closeTab" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_undoCloseTab" oncommand="CommandUpdater.doCommand(this.id);"/> #ifdef MOZ_SERVICES_SYNC <command id="cmd_remoteTabs" oncommand="CommandUpdater.doCommand(this.id);"/> #endif <!-- misc --> <command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_quit" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_actions" oncommand="CommandUpdater.doCommand(this.id);"/> @@ -96,22 +96,22 @@ <command id="cmd_volumeLeft" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_volumeRight" observes="bcast_contentShowing" oncommand="CommandUpdater.doCommand(this.id);"/> <!-- scrolling --> <command id="cmd_scrollPageUp" oncommand="CommandUpdater.doCommand(this.id);"/> <command id="cmd_scrollPageDown" oncommand="CommandUpdater.doCommand(this.id);"/> <!-- editing --> - <command id="cmd_cut" label="&cut.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_copy" label="©.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_copylink" label="©link.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_paste" label="&paste.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_delete" label="&delete.label;" oncommand="CommandUpdater.doCommand(this.id);"/> - <command id="cmd_selectAll" label="&selectAll.label;" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_cut" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_copy" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_copylink" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_paste" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_delete" oncommand="CommandUpdater.doCommand(this.id);"/> + <command id="cmd_selectAll" oncommand="CommandUpdater.doCommand(this.id);"/> <!-- forms navigation --> <command id="cmd_formPrevious" oncommand="FormHelperUI.goToPrevious();"/> <command id="cmd_formNext" oncommand="FormHelperUI.goToNext();"/> <command id="cmd_formClose" oncommand="FormHelperUI.hide();"/> <!-- find navigation --> <command id="cmd_findPrevious" oncommand="FindHelperUI.goToPrevious();"/> @@ -190,20 +190,20 @@ <observes element="bcast_windowState" attribute="*"/> <observes element="bcast_urlbarState" attribute="*"/> <hbox id="unified-back-forward-button" class="chromeclass-toolbar-additional" observes="bcast_windowState" context="backForwardMenu" removable="true" forwarddisabled="true" title="Back/Forward"> <toolbarbutton id="back-button" class="toolbarbutton" - label="Back" + label="&back.label;" command="cmd_back"/> <toolbarbutton id="forward-button" class="toolbarbutton" - label="Forward" + label="&forward.label;" command="cmd_forward"/> <dummyobservertarget hidden="true" onbroadcast="if (this.getAttribute('disabled') == 'true') this.parentNode.setAttribute('forwarddisabled', 'true'); else this.parentNode.removeAttribute('forwarddisabled');"> <observes element="cmd_forward" attribute="disabled"/> </dummyobservertarget> @@ -240,17 +240,17 @@ <hbox id="urlbar-icons" observes="bcast_urlbarState"> <toolbarbutton id="tool-reload" oncommand="CommandUpdater.doCommand(event.shiftKey ? 'cmd_forceReload' : 'cmd_reload');"/> <toolbarbutton id="tool-stop" command="cmd_stop"/> </hbox> </toolbar> <box id="toolbar-transition" observes="bcast_windowState" > - <toolbarbutton id="tool-new-tab" command="cmd_newTab"/> + <toolbarbutton id="tool-new-tab" command="cmd_newTab" label="&newtab.label;"/> </box> </hbox> <hbox id="progress-control" layer="true"></hbox> <!-- Start UI --> <hbox id="start-container" flex="1" observes="bcast_windowState" class="meta content-height content-width" onclick="false;"> <!-- portrait/landscape/filled view --> @@ -554,88 +554,93 @@ </vbox> </dialog> </box> #endif <box id="context-container" class="menu-container" hidden="true"> <vbox id="context-popup" class="menu-popup"> <richlistbox id="context-commands" bindingType="contextmenu" flex="1"> + <!-- priority="low" items are hidden by default when a context is being displayed + for two or more media types. (e.g. a linked image) --> + <!-- Note the order of richlistitem here is important as it is reflected in the + menu itself. --> + <!-- ux spec: https://bug782810.bugzilla.mozilla.org/attachment.cgi?id=714804 --> + <!-- Text related --> - <richlistitem id="context-copy" type="copy" onclick="ContextCommands.copy();"> - <label value="©.label;"/> + <!-- for text inputs, this will copy selected text, or if no text is selected, copy all --> + <richlistitem id="context-copy" type="copy,selectable" onclick="ContextCommands.copy();"> + <label value="&contextTextCopy.label;"/> </richlistitem> - <richlistitem id="context-copy-all" type="copy-all" onclick="ContextCommands.copy();"> - <label value="©All.label;"/> - </richlistitem> + <!-- only displayed if there is text on the clipboard --> <richlistitem id="context-paste" type="paste" onclick="ContextCommands.paste();"> - <label value="&paste.label;"/> + <label value="&contextTextPaste.label;"/> </richlistitem> + <!-- Search Bing for "..." --> + <richlistitem id="context-search" type="copy,selected-text" onclick="ContextCommands.searchText(this);"> + <label id="context-search-label" value=""/> + </richlistitem> + <!-- only display if there is text on the clipboard and the target is the urlbar --> <richlistitem id="context-paste-n-go" type="paste-url" onclick="ContextCommands.pasteAndGo();"> - <label value="&pasteAndGo.label;"/> + <label value="&contextTextPasteAndGo.label;"/> </richlistitem> - <richlistitem id="context-select-all" type="select-all" onclick="ContextCommands.selectAll();"> - <label value="&selectAll.label;"/> + <!-- only displayed in inputs with text that do not have selection --> + <richlistitem id="context-select" type="selectable" onclick="ContextCommands.select();"> + <label value="&contextTextSelect.label;"/> + </richlistitem> + <!-- only displayed in inputs with text that do not have selection --> + <richlistitem id="context-select-all" type="selectable" onclick="ContextCommands.selectAll();"> + <label value="&contextTextSelectAll.label;"/> </richlistitem> <!-- Image related --> + <!-- save image to user pictures library --> <richlistitem id="context-save-image-lib" type="image" onclick="ContextCommands.saveImageToLib();"> <label value="&contextSaveImageLib.label;"/> </richlistitem> + <!-- copy image data to clipboard --> <richlistitem id="context-copy-image" type="image" onclick="ContextCommands.copyImage();"> <label value="&contextCopyImage.label;"/> </richlistitem> - <richlistitem id="context-copy-image-loc" type="image" onclick="ContextCommands.copyImageLink();"> + <!-- copy the uri of the image src --> + <richlistitem id="context-copy-image-loc" type="image" onclick="ContextCommands.copyImageSrc();"> <label value="&contextCopyImageLocation.label;"/> </richlistitem> - <richlistitem id="context-open-image-tab" type="image" onclick="ContextCommands.openImageInNewTab();"> + <!-- open the uri of the image src in a new tab --> + <richlistitem id="context-open-image-tab" type="image" priority="low" onclick="ContextCommands.openImageInNewTab();"> <label value="&contextOpenImageTab.label;"/> </richlistitem> + <!-- Video related --> + <!-- save video to user videos library --> + <richlistitem id="context-save-video-lib" type="video" onclick="ContextCommands.saveVideoToLib();"> + <label value="&contextSaveVideoLib.label;"/> + </richlistitem> + <!-- copy the uri of the video src --> + <richlistitem id="context-copy-video-loc" type="video" onclick="ContextCommands.copyVideoSrc();"> + <label value="&contextCopyVideoLocation.label;"/> + </richlistitem> + <!-- open the uri of the video src in a new tab --> + <richlistitem id="context-open-video-tab" type="video" priority="low" onclick="ContextCommands.openVideoInNewTab();"> + <label value="&contextOpenVideoTab.label;"/> + </richlistitem> + <!-- Link related --> - <richlistitem id="context-openinnewtab" type="link-openable" onclick="ContextCommands.openInNewTab();"> - <label value="&contextOpenInNewTab.label;"/> - </richlistitem> - <richlistitem id="context-bookmark-link" type="link" onclick="ContextCommands.bookmarkLink();"> - <label value="&contextBookmarkLink.label;"/> + <!-- all of these apply to underlying link href values --> + <richlistitem id="context-open-in-new-tab" type="link" onclick="ContextCommands.openLinkInNewTab();"> + <label value="&contextOpenLinkTab.label;"/> </richlistitem> <richlistitem id="context-copy-link" type="link" onclick="ContextCommands.copyLink();"> - <label value="&contextCopyLink.label;"/> + <label value="&contextCopyLinkHref.label;"/> </richlistitem> - <richlistitem id="context-copy-email" type="mailto" onclick="ContextCommands.copyEmail();"> - <label value="&contextCopyEmail.label;"/> - </richlistitem> - <richlistitem id="context-copy-phone" type="callto" onclick="ContextCommands.copyPhone();"> - <label value="&contextCopyPhone.label;"/> + <richlistitem id="context-bookmark-link" type="link" priority="low" onclick="ContextCommands.bookmarkLink();"> + <label value="&contextBookmarkLinkHref.label;"/> </richlistitem> - <!-- Video related --> - <richlistitem id="context-play-media" type="media-paused" onclick="ContextCommands.sendCommand('play');"> - <label value="&contextPlayMedia.label;"/> - </richlistitem> - <richlistitem id="context-pause-video" type="media-playing" onclick="ContextCommands.sendCommand('pause');"> - <label value="&contextPauseMedia.label;"/> - </richlistitem> - <richlistitem id="context-videotab" type="video" onclick="ContextCommands.sendCommand('videotab');"> - <label value="&contextVideoTab.label;"/> - </richlistitem> - <richlistitem id="context-save-video" type="video" onclick="ContextCommands.saveVideo();"> - <label value="&contextSaveVideo.label;"/> - </richlistitem> - <richlistitem id="context-save-video-to" type="video" onclick="ContextCommands.saveVideoTo();"> - <label value="&contextSaveVideoTo.label;"/> - </richlistitem> - - <!-- Misc. related --> - <richlistitem id="context-editbookmark" type="edit-bookmark" onclick="ContextCommands.editBookmark();"> - <label value="&contextEditBookmark.label;"/> - </richlistitem> - <richlistitem id="context-removebookmark" type="edit-bookmark" onclick="ContextCommands.removeBookmark();"> - <label value="&contextRemoveBookmark.label;"/> - </richlistitem> + <!-- App bar: 'more' button context menu --> <richlistitem id="context-findinpage" type="find-in-page" onclick="ContextCommands.findInPage();"> <label value="&appbarFindInPage.label;"/> </richlistitem> <richlistitem id="context-viewondesktop" type="view-on-desktop" onclick="ContextCommands.viewOnDesktop();"> <label value="&appbarViewOnDesktop.label;"/> </richlistitem> </richlistbox> </vbox>
--- a/browser/metro/base/content/contenthandlers/ContextMenuHandler.js +++ b/browser/metro/base/content/contenthandlers/ContextMenuHandler.js @@ -170,39 +170,38 @@ var ContextMenuHandler = { continue; } state.types.push("link"); state.label = state.linkURL = this._getLinkURL(elem); linkUrl = state.linkURL; state.linkTitle = popupNode.textContent || popupNode.title; state.linkProtocol = this._getProtocol(this._getURI(state.linkURL)); + // mark as text so we can pickup on selection below + isText = true; break; } else if (this._isTextInput(elem)) { let selectionStart = elem.selectionStart; let selectionEnd = elem.selectionEnd; state.types.push("input-text"); this._target = elem; // Don't include "copy" for password fields. if (!(elem instanceof Ci.nsIDOMHTMLInputElement) || elem.mozIsTextField(true)) { if (selectionStart != selectionEnd) { state.types.push("copy"); state.string = elem.value.slice(selectionStart, selectionEnd); - } else if (elem.value) { - state.types.push("copy-all"); + } + if (elem.value && (selectionStart > 0 || selectionEnd < elem.textLength)) { + state.types.push("selectable"); state.string = elem.value; } } - if (selectionStart > 0 || selectionEnd < elem.textLength) { - state.types.push("select-all"); - } - if (!elem.textLength) { state.types.push("input-empty"); } let flavors = ["text/unicode"]; let cb = Cc["@mozilla.org/widget/clipboard;1"].getService(Ci.nsIClipboard); let hasData = cb.hasDataMatchingFlavors(flavors, flavors.length, @@ -222,16 +221,17 @@ var ContextMenuHandler = { state.types.push("video"); } } } elem = elem.parentNode; } + // Over arching text tests if (isText) { // If this is text and has a selection, we want to bring // up the copy option on the context menu. if (content && content.getSelection() && content.getSelection().toString().length > 0) { state.string = content.getSelection().toString(); state.types.push("copy"); state.types.push("selected-text"); @@ -329,41 +329,8 @@ var ContextMenuHandler = { /** Remove all handlers registered for a given type. */ unregisterType: function unregisterType(aName) { this._types = this._types.filter(function(type) type.name != aName); } }; ContextMenuHandler.init(); - -ContextMenuHandler.registerType("mailto", function(aState, aElement) { - return aState.linkProtocol == "mailto"; -}); - -ContextMenuHandler.registerType("callto", function(aState, aElement) { - let protocol = aState.linkProtocol; - return protocol == "tel" || protocol == "callto" || protocol == "sip" || protocol == "voipto"; -}); - -ContextMenuHandler.registerType("link-openable", function(aState, aElement) { - return Util.isOpenableScheme(aState.linkProtocol); -}); - -["image", "video"].forEach(function(aType) { - ContextMenuHandler.registerType(aType+"-shareable", function(aState, aElement) { - if (aState.types.indexOf(aType) == -1) - return false; - - let protocol = ContextMenuHandler._getProtocol(ContextMenuHandler._getURI(aState.mediaURL)); - return Util.isShareableScheme(protocol); - }); -}); - -ContextMenuHandler.registerType("image-loaded", function(aState, aElement) { - if (aState.types.indexOf("image") != -1) { - let request = aElement.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST); - if (request && (request.imageStatus & request.STATUS_SIZE_AVAILABLE)) - return true; - } - return false; -}); -
--- a/browser/metro/base/content/contenthandlers/SelectionHandler.js +++ b/browser/metro/base/content/contenthandlers/SelectionHandler.js @@ -50,29 +50,31 @@ var SelectionHandler = { _frameOffset: { x:0, y:0 }, _domWinUtils: null, _selectionMoveActive: false, _lastMarker: "", _debugOptions: { dumpRanges: false, displayRanges: false }, init: function init() { addMessageListener("Browser:SelectionStart", this); + addMessageListener("Browser:SelectionAttach", this); addMessageListener("Browser:SelectionEnd", this); addMessageListener("Browser:SelectionMoveStart", this); addMessageListener("Browser:SelectionMove", this); addMessageListener("Browser:SelectionMoveEnd", this); addMessageListener("Browser:SelectionUpdate", this); addMessageListener("Browser:SelectionClose", this); addMessageListener("Browser:SelectionClear", this); addMessageListener("Browser:SelectionCopy", this); addMessageListener("Browser:SelectionDebug", this); }, shutdown: function shutdown() { removeMessageListener("Browser:SelectionStart", this); + removeMessageListener("Browser:SelectionAttach", this); removeMessageListener("Browser:SelectionEnd", this); removeMessageListener("Browser:SelectionMoveStart", this); removeMessageListener("Browser:SelectionMove", this); removeMessageListener("Browser:SelectionMoveEnd", this); removeMessageListener("Browser:SelectionUpdate", this); removeMessageListener("Browser:SelectionClose", this); removeMessageListener("Browser:SelectionClear", this); removeMessageListener("Browser:SelectionCopy", this); @@ -109,16 +111,27 @@ var SelectionHandler = { this._onFail("failed to set selection at point"); return; } // Update the position of our selection monocles this._updateSelectionUI(true, true); }, + _onSelectionAttach: function _onSelectionAttach(aX, aY) { + // Init content window information + if (!this._initTargetInfo(aX, aY)) { + this._onFail("failed to get frame offset"); + return; + } + + // Update the position of our selection monocles + this._updateSelectionUI(true, true); + }, + /* * Selection monocle start move event handler */ _onSelectionMoveStart: function _onSelectionMoveStart(aMsg) { if (!this._contentWindow) { this._onFail("_onSelectionMoveStart was called without proper view set up"); return; } @@ -889,16 +902,20 @@ var SelectionHandler = { Util.dumpLn("SelectionHandler:", aMessage.name); } let json = aMessage.json; switch (aMessage.name) { case "Browser:SelectionStart": this._onSelectionStart(json.xPos, json.yPos); break; + case "Browser:SelectionAttach": + this._onSelectionAttach(json.xPos, json.yPos); + break; + case "Browser:SelectionClose": this._onSelectionClose(); break; case "Browser:SelectionMoveStart": this._onSelectionMoveStart(json); break;
--- a/browser/metro/base/content/helperui/MenuUI.js +++ b/browser/metro/base/content/helperui/MenuUI.js @@ -113,37 +113,76 @@ var ContextMenuUI = { * * json: TBD */ showContextMenu: function ch_showContextMenu(aMessage) { this._popupState = aMessage.json; this._popupState.target = aMessage.target; let contentTypes = this._popupState.types; + /* + * Types in ContextMenuHandler: + * image + * link + * input-text - generic form input control + * copy - form input that has some selected text + * selectable - form input with text that can be selected + * input-empty - form input (empty) + * paste - form input and there's text on the clipboard + * selected-text - generic content text that is selected + * content-text - generic content text + * video + * media-paused, media-playing + * paste-url - url bar w/text on the clipboard + */ + + Util.dumpLn("contentTypes:", contentTypes); + + // Defines whether or not low priority items in images, text, and + // links are displayed. + let multipleMediaTypes = false; + if (contentTypes.indexOf("link") != -1 && + (contentTypes.indexOf("image") != -1 || + contentTypes.indexOf("video") != -1 || + contentTypes.indexOf("selected-text") != -1)) + multipleMediaTypes = true; + + for (let command of Array.slice(this._commands.childNodes)) { + command.hidden = true; + } + let optionsAvailable = false; - for (let i = 0; i < this._commands.childElementCount; i++) { - let command = this._commands.childNodes[i]; - command.hidden = true; + for (let command of Array.slice(this._commands.childNodes)) { + let types = command.getAttribute("type").split(","); + let lowPriority = (command.hasAttribute("priority") && + command.getAttribute("priority") == "low"); + let searchTextItem = (command.id == "context-search"); - let types = command.getAttribute("type").split(/\s+/); + // filter low priority items if we have more than one media type. + if (multipleMediaTypes && lowPriority) + continue; + for (let i = 0; i < types.length; i++) { if (contentTypes.indexOf(types[i]) != -1) { + // If this is the special search text item, we need to set its label dynamically. + if (searchTextItem && !ContextCommands.searchTextSetup(command, this._popupState.string)) { + break; + } optionsAvailable = true; command.hidden = false; break; } } } if (!optionsAvailable) { this._popupState = null; return false; } - this._menuPopup.show(this._popupState); let event = document.createEvent("Events"); event.initEvent("CancelTouchSequence", true, false); if (this._popupState.target) { this._popupState.target.dispatchEvent(event); } return true;
--- a/browser/metro/base/content/helperui/SelectionHelperUI.js +++ b/browser/metro/base/content/helperui/SelectionHelperUI.js @@ -221,19 +221,16 @@ var SelectionHelperUI = { /* * openEditSession * * Attempts to select underlying text at a point and begins editing * the section. */ openEditSession: function openEditSession(aMessage) { - if (!this.canHandle(aMessage)) - return; - /* * aMessage - from _onContentContextMenu in ContextMenuHandler * name: aMessage.name, * target: aMessage.target * json: * types: [], * label: "", * linkURL: "", @@ -261,31 +258,51 @@ var SelectionHelperUI = { "Browser:SelectionStart", { xPos: this._popupState.xPos, yPos: this._popupState.yPos }); this._setupDebugOptions(); }, /* + * attachEditSession + * + * Attaches to existing selection and begins editing. + */ + attachEditSession: function attachEditSession(aMessage) { + this._popupState = aMessage.json; + this._popupState._target = aMessage.target; + + this._init(); + + Util.dumpLn("enableSelection target:", this._popupState._target); + + // Set the track bounds for each marker NIY + this.startMark.setTrackBounds(this._popupState.xPos, this._popupState.yPos); + this.endMark.setTrackBounds(this._popupState.xPos, this._popupState.yPos); + + // Send this over to SelectionHandler in content, they'll message us + // back with information on the current selection. + this._popupState._target.messageManager.sendAsyncMessage( + "Browser:SelectionAttach", + { xPos: this._popupState.xPos, + yPos: this._popupState.yPos }); + + this._setupDebugOptions(); + }, + + /* * canHandle * * Determines if we can handle a ContextMenuHandler message. */ canHandle: function canHandle(aMessage) { - // Reject empty text inputs, nothing to do here - if (aMessage.json.types.indexOf("input-empty") != -1) { - return false; - } - // Input with text or general text in a page - if (aMessage.json.types.indexOf("content-text") == -1 && - aMessage.json.types.indexOf("input-text") == -1) { - return false; - } - return true; + if (aMessage.json.types.indexOf("content-text") != -1) + return true; + return false; }, /* * isActive * * Determines if an edit session is currently active. */ isActive: function isActive() {
--- a/browser/metro/base/content/input.js +++ b/browser/metro/base/content/input.js @@ -160,18 +160,16 @@ var TouchModule = { this._doDragStop(); // Kinetic panning may have already been active or drag stop above may have // made kinetic panning active. this._kinetic.end(); this._targetScrollbox = null; this._targetScrollInterface = null; - - this._cleanClickBuffer(); }, _onContextMenu: function _onContextMenu(aEvent) { // Special case when running on the desktop, fire off // a edge ui event when we get the contextmenu event. if (this._treatMouseAsTouch) { let event = document.createEvent("Events"); event.initEvent("MozEdgeUIGesture", true, false);
--- a/browser/metro/locales/en-US/chrome/browser.dtd +++ b/browser/metro/locales/en-US/chrome/browser.dtd @@ -2,49 +2,33 @@ - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> <!ENTITY urlbar.emptytext "Enter Search or Address"> <!ENTITY urlbar.accesskey "d"> <!ENTITY back.label "Back"> <!ENTITY forward.label "Forward"> -<!ENTITY reload.label "Reload"> -<!ENTITY stop.label "Stop"> -<!ENTITY go.label "Go"> -<!ENTITY star.label "Star"> - <!ENTITY toggleTabsOnly.label "Always show tabs"> <!ENTITY showTabs.label "Show Tabs"> <!ENTITY newtab.label "New Tab"> <!ENTITY closetab.label "Close Tab"> <!ENTITY undoclosetab.label "Undo Close Tab"> -<!ENTITY cut.label "Cut"> -<!ENTITY copy.label "Copy"> -<!ENTITY copyAll.label "Copy All"> -<!ENTITY copylink.label "Copy Link Location"> -<!ENTITY paste.label "Paste"> -<!ENTITY pasteAndGo.label "Paste & Go"> -<!ENTITY delete.label "Delete"> -<!ENTITY selectAll.label "Select All"> - <!ENTITY appbarFindInPage.label "Find in Page"> <!ENTITY appbarViewOnDesktop.label "View on Desktop"> <!ENTITY startTopSitesHeader.label "Top Sites"> <!ENTITY startBookmarksHeader.label "Bookmarks"> <!ENTITY startHistoryHeader.label "Recent History"> <!ENTITY startRemoteTabsHeader.label "Tabs from Other Devices"> <!ENTITY autocompleteResultsHeader.label "Your Results"> <!ENTITY autocompleteSearchesHeader.label "Internet Searches"> -<!ENTITY selectHelper.done "Done"> - <!ENTITY downloadsHeader.label "Downloads"> <!ENTITY downloadShowPage.label "Go to Page"> <!ENTITY downloadShow2.label "Find"> <!ENTITY downloadOpen2.label "Open"> <!ENTITY downloadCancel.label "Cancel"> <!ENTITY downloadPause.label "Pause"> <!ENTITY downloadResume.label "Resume"> <!ENTITY downloadRetry.label "Retry"> @@ -71,38 +55,37 @@ <!ENTITY consoleMessages.label "Messages"> <!ENTITY consoleCodeEval.label "Code:"> <!ENTITY consoleClear.label "Clear"> <!ENTITY consoleEvaluate.label "…"> <!ENTITY consoleErrFile.label "Source File:"> <!ENTITY consoleErrLine.label "Line:"> <!ENTITY consoleErrColumn.label "Column:"> -<!ENTITY contextOpenInNewTab.label "Open Link in New Tab"> -<!ENTITY contextViewInNewTab.label "View in New Tab"> -<!ENTITY contextCopyLink.label "Copy Link"> -<!ENTITY contextCopyEmail.label "Copy Email Address"> -<!ENTITY contextCopyPhone.label "Copy Phone Number"> -<!ENTITY contextCopyImage.label "Copy Image"> -<!ENTITY contextShareLink.label "Share Link"> -<!ENTITY contextShareImage.label "Share Image"> -<!ENTITY contextBookmarkLink.label "Bookmark Link"> -<!ENTITY contextSaveVideo.label "Save Video"> -<!ENTITY contextSaveVideoTo.label "Save Video To"> -<!ENTITY contextShareVideo.label "Share Video"> -<!ENTITY contextPlayMedia.label "Play"> -<!ENTITY contextPauseMedia.label "Pause"> -<!ENTITY contextVideoTab.label "Open In New Tab"> -<!ENTITY contextEditBookmark.label "Edit"> -<!ENTITY contextRemoveBookmark.label "Remove"> -<!ENTITY contextShortcutBookmark.label "Add to Home Screen"> +<!-- TEXT CONTEXT MENU --> +<!ENTITY contextTextCopy.label "Copy"> +<!ENTITY contextTextPaste.label "Paste"> +<!-- unique item that is only added to the url bar context menu --> +<!ENTITY contextTextPasteAndGo.label "Paste & go"> +<!ENTITY contextTextSelect.label "Select"> +<!ENTITY contextTextSelectAll.label "Select all"> -<!-- * image context menu * --> +<!-- LINK CONTEXT MENU --> +<!ENTITY contextOpenLinkTab.label "Open link in new tab"> +<!ENTITY contextCopyLinkHref.label "Copy link"> +<!ENTITY contextBookmarkLinkHref.label "Bookmark link"> + +<!-- IMAGE CONTEXT MENU --> <!-- l10n: contextSaveImageLib saves an image to the users "pictures library" (Explorer -> left hand side navigation ppane -> Libraries -> Pictures) --> -<!ENTITY contextSaveImageLib.label "Save to pictures library"> -<!ENTITY contextCopyImage.label "Copy image"> -<!ENTITY contextCopyImageLocation.label "Copy image location"> -<!ENTITY contextOpenImageTab.label "Open image in new tab"> +<!ENTITY contextSaveImageLib.label "Save to picture library"> +<!ENTITY contextCopyImage.label "Copy image"> +<!ENTITY contextCopyImageLocation.label "Copy image location"> +<!ENTITY contextOpenImageTab.label "Open image in new tab"> + +<!-- VIDEO CONTEXT MENU --> +<!ENTITY contextSaveVideoLib.label "Save to video library"> +<!ENTITY contextCopyVideoLocation.label "Copy video location"> +<!ENTITY contextOpenVideoTab.label "Open video in new tab"> <!ENTITY pageactions.password.forget "Forget Password"> <!ENTITY pageactions.reset "Clear Site Preferences"> <!ENTITY pageactions.charEncoding "Character Encoding">
--- a/browser/metro/locales/en-US/chrome/browser.properties +++ b/browser/metro/locales/en-US/chrome/browser.properties @@ -5,16 +5,19 @@ # Default search engine browser.search.defaultenginename=Bing # Search engine order (order displayed in the search bar dropdown)s browser.search.order.1=Bing browser.search.order.2=Google browser.search.order.3=Yahoo +# l10n: search context menu item text will be: |Search (browser.search.defaultenginename) for ".." +browser.search.contextTextSearchLabel=Search %S for ".." + # Settings Charms aboutCharm1=About optionsCharm=Options helpOnlineCharm=Help (online) # General browserForSaveLocation=Save Location @@ -130,10 +133,11 @@ clearPrivateData.message=Delete your bro # This is not a string to translate. If users frequently use the "Character Encoding" # menu, set this to "true". Otherwise, you can leave it as "false". browser.menu.showCharacterEncoding=false # LOCALIZATION NOTE (intl.charsetmenu.browser.static): Set to a series of comma separated # values for charsets that the user can select from in the Character Encoding menu. intl.charsetmenu.browser.static=iso-8859-1,utf-8,x-gbk,big5,iso-2022-jp,shift_jis,euc-jp -#Text Selection +# Selection alerts selectionHelper.textCopied=Text copied to clipboard +selectionHelper.linkCopied=Link copied to clipboard