diff options
Diffstat (limited to 'WebCore/platform/ContextMenu.cpp')
-rw-r--r-- | WebCore/platform/ContextMenu.cpp | 887 |
1 files changed, 29 insertions, 858 deletions
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp index 93cdfdf..a51d818 100644 --- a/WebCore/platform/ContextMenu.cpp +++ b/WebCore/platform/ContextMenu.cpp @@ -1,7 +1,5 @@ /* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008 Christian Dywan <christian@imendio.com> - * Copyright (C) 2010 Igalia S.L + * Copyright (C) 2010 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -12,879 +10,52 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "ContextMenu.h" -#if ENABLE(CONTEXT_MENUS) - -#include "BackForwardController.h" -#include "ContextMenuController.h" -#include "ContextMenuClient.h" -#include "CSSComputedStyleDeclaration.h" -#include "CSSProperty.h" -#include "CSSPropertyNames.h" -#include "Document.h" -#include "DocumentLoader.h" -#include "Editor.h" -#include "Frame.h" -#include "FrameLoader.h" -#include "InspectorController.h" -#include "KURL.h" -#include "LocalizedStrings.h" -#include "Node.h" -#include "Page.h" -#include "ResourceRequest.h" -#include "SelectionController.h" -#include "Settings.h" -#include "TextIterator.h" -#include <wtf/text/CString.h> - -using namespace std; -using namespace WTF; -using namespace Unicode; +#if USE(CROSS_PLATFORM_CONTEXT_MENUS) namespace WebCore { -ContextMenuController* ContextMenu::controller() const -{ - if (Node* node = m_hitTestResult.innerNonSharedNode()) - if (Frame* frame = node->document()->frame()) - if (Page* page = frame->page()) - return page->contextMenuController(); - return 0; -} - -static PassOwnPtr<ContextMenuItem> separatorItem() -{ - return new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()); -} - -static void createAndAppendFontSubMenu(const HitTestResult& result, ContextMenuItem& fontMenuItem) -{ - ContextMenu fontMenu(result); - -#if PLATFORM(MAC) - ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts()); -#endif - ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold()); - ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic()); - ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline()); - ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline()); -#if PLATFORM(MAC) - ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles()); - ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors()); -#endif - -#if PLATFORM(MAC) - fontMenu.appendItem(showFonts); -#endif - fontMenu.appendItem(bold); - fontMenu.appendItem(italic); - fontMenu.appendItem(underline); - fontMenu.appendItem(outline); -#if PLATFORM(MAC) - fontMenu.appendItem(styles); - fontMenu.appendItem(*separatorItem()); - fontMenu.appendItem(showColors); -#endif - - fontMenuItem.setSubMenu(&fontMenu); -} - -#if !defined(BUILDING_ON_TIGER) - -#if !PLATFORM(GTK) - -static void createAndAppendSpellingAndGrammarSubMenu(const HitTestResult& result, ContextMenuItem& spellingAndGrammarMenuItem) -{ - ContextMenu spellingAndGrammarMenu(result); - - ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel, - contextMenuItemTagShowSpellingPanel(true)); - ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling, - contextMenuItemTagCheckSpelling()); - ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping, - contextMenuItemTagCheckSpellingWhileTyping()); - ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling, - contextMenuItemTagCheckGrammarWithSpelling()); -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) - ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically, - contextMenuItemTagCorrectSpellingAutomatically()); -#endif - - spellingAndGrammarMenu.appendItem(showSpellingPanel); - spellingAndGrammarMenu.appendItem(checkSpelling); -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) - spellingAndGrammarMenu.appendItem(*separatorItem()); -#endif - spellingAndGrammarMenu.appendItem(checkAsYouType); - spellingAndGrammarMenu.appendItem(grammarWithSpelling); -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) - spellingAndGrammarMenu.appendItem(correctSpelling); -#endif - - spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu); -} - -#endif // !PLATFORM(GTK) - -#else - -static void createAndAppendSpellingSubMenu(const HitTestResult& result, ContextMenuItem& spellingMenuItem) -{ - ContextMenu spellingMenu(result); - - ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel, - contextMenuItemTagShowSpellingPanel(true)); - ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling, - contextMenuItemTagCheckSpelling()); - ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping, - contextMenuItemTagCheckSpellingWhileTyping()); - - spellingMenu.appendItem(showSpellingPanel); - spellingMenu.appendItem(checkSpelling); - spellingMenu.appendItem(checkAsYouType); - - spellingMenuItem.setSubMenu(&spellingMenu); -} - -#endif - -#if PLATFORM(MAC) - -static void createAndAppendSpeechSubMenu(const HitTestResult& result, ContextMenuItem& speechMenuItem) -{ - ContextMenu speechMenu(result); - - ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking()); - ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking()); - - speechMenu.appendItem(start); - speechMenu.appendItem(stop); - - speechMenuItem.setSubMenu(&speechMenu); -} - -#endif - -#if !PLATFORM(GTK) - -static void createAndAppendWritingDirectionSubMenu(const HitTestResult& result, ContextMenuItem& writingDirectionMenuItem) -{ - ContextMenu writingDirectionMenu(result); - - ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection, - contextMenuItemTagDefaultDirection()); - ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight()); - ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft()); - - writingDirectionMenu.appendItem(defaultItem); - writingDirectionMenu.appendItem(ltr); - writingDirectionMenu.appendItem(rtl); - - writingDirectionMenuItem.setSubMenu(&writingDirectionMenu); -} - -static void createAndAppendTextDirectionSubMenu(const HitTestResult& result, ContextMenuItem& textDirectionMenuItem) -{ - ContextMenu textDirectionMenu(result); - - ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection()); - ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight()); - ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft()); - - textDirectionMenu.appendItem(defaultItem); - textDirectionMenu.appendItem(ltr); - textDirectionMenu.appendItem(rtl); - - textDirectionMenuItem.setSubMenu(&textDirectionMenu); -} - -#endif - -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - -static void createAndAppendSubstitutionsSubMenu(const HitTestResult& result, ContextMenuItem& substitutionsMenuItem) -{ - ContextMenu substitutionsMenu(result); - - ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true)); - ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste()); - ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes()); - ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes()); - ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks()); - ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement()); - - substitutionsMenu.appendItem(showSubstitutions); - substitutionsMenu.appendItem(*separatorItem()); - substitutionsMenu.appendItem(smartCopyPaste); - substitutionsMenu.appendItem(smartQuotes); - substitutionsMenu.appendItem(smartDashes); - substitutionsMenu.appendItem(smartLinks); - substitutionsMenu.appendItem(textReplacement); - - substitutionsMenuItem.setSubMenu(&substitutionsMenu); -} - -static void createAndAppendTransformationsSubMenu(const HitTestResult& result, ContextMenuItem& transformationsMenuItem) +ContextMenu::ContextMenu() { - ContextMenu transformationsMenu(result); - - ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase()); - ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase()); - ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize()); - - transformationsMenu.appendItem(makeUpperCase); - transformationsMenu.appendItem(makeLowerCase); - transformationsMenu.appendItem(capitalize); - - transformationsMenuItem.setSubMenu(&transformationsMenu); } -#endif - -static bool selectionContainsPossibleWord(Frame* frame) +static const ContextMenuItem* findItemWithAction(unsigned action, const Vector<ContextMenuItem>& items) { - // Current algorithm: look for a character that's not just a separator. - for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) { - int length = it.length(); - const UChar* characters = it.characters(); - for (int i = 0; i < length; ++i) - if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph))) - return true; + for (size_t i = 0; i < items.size(); ++i) { + const ContextMenuItem& item = items[i]; + if (item.action() == action) + return &item; + if (item.type() != SubmenuType) + continue; + if (const ContextMenuItem* subMenuItem = findItemWithAction(action, item.subMenuItems())) + return subMenuItem; } - return false; -} - -void ContextMenu::populate() -{ - ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink()); - ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow, - contextMenuItemTagOpenLinkInNewWindow()); - ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk, - contextMenuItemTagDownloadLinkToDisk()); - ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard, - contextMenuItemTagCopyLinkToClipboard()); - ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow, - contextMenuItemTagOpenImageInNewWindow()); - ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk, - contextMenuItemTagDownloadImageToDisk()); - ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard, - contextMenuItemTagCopyImageToClipboard()); - ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String()); - ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard, - String()); - ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause, - contextMenuItemTagMediaPlay()); - ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute, - contextMenuItemTagMediaMute()); - ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls, - contextMenuItemTagToggleMediaControls()); - ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop, - contextMenuItemTagToggleMediaLoop()); - ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen, - contextMenuItemTagEnterVideoFullscreen()); -#if PLATFORM(MAC) - ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight, - contextMenuItemTagSearchInSpotlight()); - ContextMenuItem LookInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, - contextMenuItemTagLookUpInDictionary()); -#endif -#if !PLATFORM(GTK) - ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb()); -#endif - ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy()); - ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack()); - ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward()); - ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop()); - ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload()); - ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow, - contextMenuItemTagOpenFrameInNewWindow()); - ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound, - contextMenuItemTagNoGuessesFound()); - ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling, - contextMenuItemTagIgnoreSpelling()); - ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling, - contextMenuItemTagLearnSpelling()); - ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar, - contextMenuItemTagIgnoreGrammar()); - ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut()); - ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste()); -#if PLATFORM(GTK) - ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete()); - ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll()); -#endif - - HitTestResult result = hitTestResult(); - - Node* node = m_hitTestResult.innerNonSharedNode(); - if (!node) - return; -#if PLATFORM(GTK) - if (!result.isContentEditable() && (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement())) - return; -#endif - Frame* frame = node->document()->frame(); - if (!frame) - return; - - if (!result.isContentEditable()) { - FrameLoader* loader = frame->loader(); - KURL linkURL = result.absoluteLinkURL(); - if (!linkURL.isEmpty()) { - if (loader->canHandleRequest(ResourceRequest(linkURL))) { - appendItem(OpenLinkItem); - appendItem(OpenLinkInNewWindowItem); - appendItem(DownloadFileItem); - } - appendItem(CopyLinkItem); - } - - KURL imageURL = result.absoluteImageURL(); - if (!imageURL.isEmpty()) { - if (!linkURL.isEmpty()) - appendItem(*separatorItem()); - - appendItem(OpenImageInNewWindowItem); - appendItem(DownloadImageItem); - if (imageURL.isLocalFile() || m_hitTestResult.image()) - appendItem(CopyImageItem); - } - - KURL mediaURL = result.absoluteMediaURL(); - if (!mediaURL.isEmpty()) { - if (!linkURL.isEmpty() || !imageURL.isEmpty()) - appendItem(*separatorItem()); - appendItem(MediaPlayPause); - appendItem(MediaMute); - appendItem(ToggleMediaControls); - appendItem(ToggleMediaLoop); - appendItem(EnterVideoFullscreen); - - appendItem(*separatorItem()); - appendItem(CopyMediaLinkItem); - appendItem(OpenMediaInNewWindowItem); - } - - if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) { - if (result.isSelected()) { - if (selectionContainsPossibleWord(frame)) { -#if PLATFORM(MAC) - appendItem(SearchSpotlightItem); -#endif -#if !PLATFORM(GTK) - appendItem(SearchWebItem); - appendItem(*separatorItem()); -#endif -#if PLATFORM(MAC) - appendItem(LookInDictionaryItem); - appendItem(*separatorItem()); -#endif - } - appendItem(CopyItem); -#if PLATFORM(MAC) - appendItem(*separatorItem()); - ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu()); - createAndAppendSpeechSubMenu(m_hitTestResult, SpeechMenuItem); - appendItem(SpeechMenuItem); -#endif - } else { -#if ENABLE(INSPECTOR) - if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) { -#endif - if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1)) - appendItem(BackItem); - - if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1)) - appendItem(ForwardItem); - - // use isLoadingInAPISense rather than isLoading because Stop/Reload are - // intended to match WebKit's API, not WebCore's internal notion of loading status - if (loader->documentLoader()->isLoadingInAPISense()) - appendItem(StopItem); - else - appendItem(ReloadItem); -#if ENABLE(INSPECTOR) - } -#endif - - if (frame->page() && frame != frame->page()->mainFrame()) - appendItem(OpenFrameItem); - } - } - } else { // Make an editing context menu - SelectionController* selection = frame->selection(); - bool inPasswordField = selection->isInPasswordField(); - bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node); - - if (!inPasswordField && spellCheckingEnabled) { - // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range - // is never considered a misspelling and bad grammar at the same time) - bool misspelling; - bool badGrammar; - Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar); - if (misspelling || badGrammar) { - size_t size = guesses.size(); - if (size == 0) { - // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions - // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit) - if (misspelling) { - appendItem(NoGuessesItem); - appendItem(*separatorItem()); - } - } else { - for (unsigned i = 0; i < size; i++) { - const String &guess = guesses[i]; - if (!guess.isEmpty()) { - ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess); - appendItem(item); - } - } - appendItem(*separatorItem()); - } - - if (misspelling) { - appendItem(IgnoreSpellingItem); - appendItem(LearnSpellingItem); - } else - appendItem(IgnoreGrammarItem); - appendItem(*separatorItem()); -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - } else { - // If the string was autocorrected, generate a contextual menu item allowing it to be changed back. - String replacedString = result.replacedString(); - if (!replacedString.isEmpty()) { - ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString)); - appendItem(item); - appendItem(*separatorItem()); - } -#endif - } - } - - FrameLoader* loader = frame->loader(); - KURL linkURL = result.absoluteLinkURL(); - if (!linkURL.isEmpty()) { - if (loader->canHandleRequest(ResourceRequest(linkURL))) { - appendItem(OpenLinkItem); - appendItem(OpenLinkInNewWindowItem); - appendItem(DownloadFileItem); - } - appendItem(CopyLinkItem); - appendItem(*separatorItem()); - } - - if (result.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) { -#if PLATFORM(MAC) - appendItem(SearchSpotlightItem); -#endif -#if !PLATFORM(GTK) - appendItem(SearchWebItem); - appendItem(*separatorItem()); -#endif - -#if PLATFORM(MAC) - appendItem(LookInDictionaryItem); - appendItem(*separatorItem()); -#endif - } - - appendItem(CutItem); - appendItem(CopyItem); - appendItem(PasteItem); -#if PLATFORM(GTK) - appendItem(DeleteItem); - appendItem(*separatorItem()); - appendItem(SelectAllItem); -#endif - - if (!inPasswordField) { - appendItem(*separatorItem()); -#ifndef BUILDING_ON_TIGER -#if !PLATFORM(GTK) - ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, - contextMenuItemTagSpellingMenu()); - createAndAppendSpellingAndGrammarSubMenu(m_hitTestResult, SpellingAndGrammarMenuItem); - appendItem(SpellingAndGrammarMenuItem); -#endif -#else - ContextMenuItem SpellingMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu, - contextMenuItemTagSpellingMenu()); - createAndAppendSpellingSubMenu(m_hitTestResult, SpellingMenuItem); - appendItem(SpellingMenuItem); -#endif -#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu, - contextMenuItemTagSubstitutionsMenu()); - createAndAppendSubstitutionsSubMenu(m_hitTestResult, substitutionsMenuItem); - appendItem(substitutionsMenuItem); - ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu, - contextMenuItemTagTransformationsMenu()); - createAndAppendTransformationsSubMenu(m_hitTestResult, transformationsMenuItem); - appendItem(transformationsMenuItem); -#endif -#if PLATFORM(GTK) - bool shouldShowFontMenu = frame->editor()->canEditRichly(); -#else - bool shouldShowFontMenu = true; -#endif - if (shouldShowFontMenu) { - ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu, - contextMenuItemTagFontMenu()); - createAndAppendFontSubMenu(m_hitTestResult, FontMenuItem); - appendItem(FontMenuItem); - } -#if PLATFORM(MAC) - ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu()); - createAndAppendSpeechSubMenu(m_hitTestResult, SpeechMenuItem); - appendItem(SpeechMenuItem); -#endif -#if !PLATFORM(GTK) - ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu, - contextMenuItemTagWritingDirectionMenu()); - createAndAppendWritingDirectionSubMenu(m_hitTestResult, WritingDirectionMenuItem); - appendItem(WritingDirectionMenuItem); - if (Page* page = frame->page()) { - if (Settings* settings = page->settings()) { - bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded - || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection()); - if (includeTextDirectionSubmenu) { - ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu, - contextMenuItemTagTextDirectionMenu()); - createAndAppendTextDirectionSubMenu(m_hitTestResult, TextDirectionMenuItem); - appendItem(TextDirectionMenuItem); - } - } - } -#endif - } - } -} - -#if ENABLE(INSPECTOR) -void ContextMenu::addInspectElementItem() -{ - Node* node = m_hitTestResult.innerNonSharedNode(); - if (!node) - return; - - Frame* frame = node->document()->frame(); - if (!frame) - return; - - Page* page = frame->page(); - if (!page) - return; - - if (!page->inspectorController()) - return; - - ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement()); - appendItem(*separatorItem()); - appendItem(InspectElementItem); + return 0; } -#endif // ENABLE(INSPECTOR) -void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const +ContextMenuItem* ContextMenu::itemWithAction(unsigned action) { - if (item.type() == SeparatorType) - return; - - Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame(); - if (!frame) - return; - - // Custom items already have proper checked and enabled values. - if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag) - return; - - bool shouldEnable = true; - bool shouldCheck = false; - - switch (item.action()) { - case ContextMenuItemTagCheckSpelling: - shouldEnable = frame->editor()->canEdit(); - break; - case ContextMenuItemTagDefaultDirection: - shouldCheck = false; - shouldEnable = false; - break; - case ContextMenuItemTagLeftToRight: - case ContextMenuItemTagRightToLeft: { - ExceptionCode ec = 0; - RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); - String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl"; - style->setProperty(CSSPropertyDirection, direction, false, ec); - shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; - shouldEnable = true; - break; - } - case ContextMenuItemTagTextDirectionDefault: { - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural"); - shouldCheck = command.state() == TrueTriState; - shouldEnable = command.isEnabled(); - break; - } - case ContextMenuItemTagTextDirectionLeftToRight: { - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight"); - shouldCheck = command.state() == TrueTriState; - shouldEnable = command.isEnabled(); - break; - } - case ContextMenuItemTagTextDirectionRightToLeft: { - Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft"); - shouldCheck = command.state() == TrueTriState; - shouldEnable = command.isEnabled(); - break; - } - case ContextMenuItemTagCopy: - shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy(); - break; - case ContextMenuItemTagCut: - shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut(); - break; - case ContextMenuItemTagIgnoreSpelling: - case ContextMenuItemTagLearnSpelling: - shouldEnable = frame->selection()->isRange(); - break; - case ContextMenuItemTagPaste: - shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste(); - break; -#if PLATFORM(GTK) - case ContextMenuItemTagDelete: - shouldEnable = frame->editor()->canDelete(); - break; - case ContextMenuItemTagSelectAll: - case ContextMenuItemTagInputMethods: - case ContextMenuItemTagUnicode: - shouldEnable = true; - break; -#endif - case ContextMenuItemTagUnderline: { - ExceptionCode ec = 0; - RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); - style->setProperty(CSSPropertyWebkitTextDecorationsInEffect, "underline", false, ec); - shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; - shouldEnable = frame->editor()->canEditRichly(); - break; - } - case ContextMenuItemTagLookUpInDictionary: - shouldEnable = frame->selection()->isRange(); - break; - case ContextMenuItemTagCheckGrammarWithSpelling: -#ifndef BUILDING_ON_TIGER - if (frame->editor()->isGrammarCheckingEnabled()) - shouldCheck = true; - shouldEnable = true; -#endif - break; - case ContextMenuItemTagItalic: { - ExceptionCode ec = 0; - RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); - style->setProperty(CSSPropertyFontStyle, "italic", false, ec); - shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; - shouldEnable = frame->editor()->canEditRichly(); - break; - } - case ContextMenuItemTagBold: { - ExceptionCode ec = 0; - RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); - style->setProperty(CSSPropertyFontWeight, "bold", false, ec); - shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; - shouldEnable = frame->editor()->canEditRichly(); - break; - } - case ContextMenuItemTagOutline: - shouldEnable = false; - break; - case ContextMenuItemTagShowSpellingPanel: -#ifndef BUILDING_ON_TIGER - if (frame->editor()->spellingPanelIsShowing()) - item.setTitle(contextMenuItemTagShowSpellingPanel(false)); - else - item.setTitle(contextMenuItemTagShowSpellingPanel(true)); -#endif - shouldEnable = frame->editor()->canEdit(); - break; - case ContextMenuItemTagNoGuessesFound: - shouldEnable = false; - break; - case ContextMenuItemTagCheckSpellingWhileTyping: - shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled(); - break; -#if PLATFORM(MAC) - case ContextMenuItemTagSubstitutionsMenu: - case ContextMenuItemTagTransformationsMenu: - break; - case ContextMenuItemTagShowSubstitutions: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - if (frame->editor()->substitutionsPanelIsShowing()) - item.setTitle(contextMenuItemTagShowSubstitutions(false)); - else - item.setTitle(contextMenuItemTagShowSubstitutions(true)); - shouldEnable = frame->editor()->canEdit(); -#endif - break; - case ContextMenuItemTagMakeUpperCase: - case ContextMenuItemTagMakeLowerCase: - case ContextMenuItemTagCapitalize: - case ContextMenuItemTagChangeBack: - shouldEnable = frame->editor()->canEdit(); - break; - case ContextMenuItemTagCorrectSpellingAutomatically: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled(); -#endif - break; - case ContextMenuItemTagSmartCopyPaste: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->smartInsertDeleteEnabled(); -#endif - break; - case ContextMenuItemTagSmartQuotes: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled(); -#endif - break; - case ContextMenuItemTagSmartDashes: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled(); -#endif - break; - case ContextMenuItemTagSmartLinks: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled(); -#endif - break; - case ContextMenuItemTagTextReplacement: -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) - shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled(); -#endif - break; - case ContextMenuItemTagStopSpeaking: - shouldEnable = controller() && controller()->client() && controller()->client()->isSpeaking(); - break; -#else // PLATFORM(MAC) ends here - case ContextMenuItemTagStopSpeaking: - break; -#endif -#if PLATFORM(GTK) - case ContextMenuItemTagGoBack: - shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1); - break; - case ContextMenuItemTagGoForward: - shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1); - break; - case ContextMenuItemTagStop: - shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense(); - break; - case ContextMenuItemTagReload: - shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense(); - break; - case ContextMenuItemTagFontMenu: - shouldEnable = frame->editor()->canEditRichly(); - break; -#else - case ContextMenuItemTagGoBack: - case ContextMenuItemTagGoForward: - case ContextMenuItemTagStop: - case ContextMenuItemTagReload: - case ContextMenuItemTagFontMenu: -#endif - case ContextMenuItemTagNoAction: - case ContextMenuItemTagOpenLinkInNewWindow: - case ContextMenuItemTagDownloadLinkToDisk: - case ContextMenuItemTagCopyLinkToClipboard: - case ContextMenuItemTagOpenImageInNewWindow: - case ContextMenuItemTagDownloadImageToDisk: - case ContextMenuItemTagCopyImageToClipboard: - break; - case ContextMenuItemTagOpenMediaInNewWindow: - if (m_hitTestResult.mediaIsVideo()) - item.setTitle(contextMenuItemTagOpenVideoInNewWindow()); - else - item.setTitle(contextMenuItemTagOpenAudioInNewWindow()); - break; - case ContextMenuItemTagCopyMediaLinkToClipboard: - if (m_hitTestResult.mediaIsVideo()) - item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard()); - else - item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard()); - break; - case ContextMenuItemTagToggleMediaControls: - shouldCheck = m_hitTestResult.mediaControlsEnabled(); - break; - case ContextMenuItemTagToggleMediaLoop: - shouldCheck = m_hitTestResult.mediaLoopEnabled(); - break; - case ContextMenuItemTagEnterVideoFullscreen: - shouldEnable = m_hitTestResult.mediaSupportsFullscreen(); - break; - case ContextMenuItemTagOpenFrameInNewWindow: - case ContextMenuItemTagSpellingGuess: - case ContextMenuItemTagOther: - case ContextMenuItemTagSearchInSpotlight: - case ContextMenuItemTagSearchWeb: - case ContextMenuItemTagOpenWithDefaultApplication: - case ContextMenuItemPDFActualSize: - case ContextMenuItemPDFZoomIn: - case ContextMenuItemPDFZoomOut: - case ContextMenuItemPDFAutoSize: - case ContextMenuItemPDFSinglePage: - case ContextMenuItemPDFFacingPages: - case ContextMenuItemPDFContinuous: - case ContextMenuItemPDFNextPage: - case ContextMenuItemPDFPreviousPage: - case ContextMenuItemTagOpenLink: - case ContextMenuItemTagIgnoreGrammar: - case ContextMenuItemTagSpellingMenu: - case ContextMenuItemTagShowFonts: - case ContextMenuItemTagStyles: - case ContextMenuItemTagShowColors: - case ContextMenuItemTagSpeechMenu: - case ContextMenuItemTagStartSpeaking: - case ContextMenuItemTagWritingDirectionMenu: - case ContextMenuItemTagTextDirectionMenu: - case ContextMenuItemTagPDFSinglePageScrolling: - case ContextMenuItemTagPDFFacingPagesScrolling: -#if ENABLE(INSPECTOR) - case ContextMenuItemTagInspectElement: -#endif - case ContextMenuItemBaseCustomTag: - case ContextMenuItemCustomTagNoAction: - case ContextMenuItemLastCustomTag: - case ContextMenuItemBaseApplicationTag: - break; - case ContextMenuItemTagMediaPlayPause: - if (m_hitTestResult.mediaPlaying()) - item.setTitle(contextMenuItemTagMediaPause()); - else - item.setTitle(contextMenuItemTagMediaPlay()); - break; - case ContextMenuItemTagMediaMute: - shouldEnable = m_hitTestResult.mediaHasAudio(); - shouldCheck = shouldEnable && m_hitTestResult.mediaMuted(); - break; - } - - item.setChecked(shouldCheck); - item.setEnabled(shouldEnable); + // FIXME: When more platforms switch over, this fucntion should return a const ContextMenuItem*'s, and the const_cast + // won't be needed anymore. + return const_cast<ContextMenuItem*>(findItemWithAction(action, m_items)); } } // namespace WebCore -#endif // ENABLE(CONTEXT_MENUS) +#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS) |