2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2010 Igalia S.L
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include "ContextMenuController.h"
30 #if ENABLE(CONTEXT_MENUS)
32 #include "BackForwardController.h"
34 #include "ContextMenu.h"
35 #include "ContextMenuClient.h"
36 #include "ContextMenuItem.h"
37 #include "ContextMenuProvider.h"
39 #include "DocumentFragment.h"
40 #include "DocumentLoader.h"
42 #include "EditorClient.h"
44 #include "EventHandler.h"
45 #include "EventNames.h"
46 #include "FormState.h"
48 #include "FrameLoadRequest.h"
49 #include "FrameLoader.h"
50 #include "FrameLoaderClient.h"
51 #include "FrameSelection.h"
52 #include "HTMLFormElement.h"
53 #include "HitTestRequest.h"
54 #include "HitTestResult.h"
55 #include "InspectorController.h"
56 #include "LocalizedStrings.h"
57 #include "MouseEvent.h"
58 #include "NavigationAction.h"
61 #include "PlatformEvent.h"
62 #include "RenderObject.h"
63 #include "ReplaceSelectionCommand.h"
64 #include "ResourceRequest.h"
66 #include "TextIterator.h"
67 #include "TypingCommand.h"
68 #include "UserTypingGestureIndicator.h"
69 #include "WindowFeatures.h"
71 #include <wtf/unicode/Unicode.h>
74 #include <wtf/gobject/GOwnPtr.h>
78 using namespace Unicode;
82 ContextMenuController::ContextMenuController(Page* page, ContextMenuClient* client)
86 ASSERT_ARG(page, page);
87 ASSERT_ARG(client, client);
90 ContextMenuController::~ContextMenuController()
92 #if ENABLE(TIZEN_CONTEXT_MENU)
93 //this fixes a bug which occured when WebKit was shut down if a context menu was active
94 //then ContextMenuController destructor was calling:
95 //- first m_client->contextMenuDestroyed which destroyed the m_client object explicitly and then
96 //- and then m_contextMenu implicitily
97 //m_contextMenu destructor was then trying to call freePlatformDescription on m_contextMenuClient
98 //which was already destroyed
99 if (contextMenu() && contextMenu()->platformDescription()) {
100 m_client->freePlatformDescription(contextMenu()->platformDescription());
101 contextMenu()->setPlatformDescription(0);
104 m_client->contextMenuDestroyed();
107 PassOwnPtr<ContextMenuController> ContextMenuController::create(Page* page, ContextMenuClient* client)
109 return adoptPtr(new ContextMenuController(page, client));
112 void ContextMenuController::clearContextMenu()
114 m_contextMenu.clear();
116 m_menuProvider->contextMenuCleared();
120 void ContextMenuController::handleContextMenuEvent(Event* event)
122 m_contextMenu = createContextMenu(event);
128 showContextMenu(event);
131 static PassOwnPtr<ContextMenuItem> separatorItem()
133 return adoptPtr(new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()));
136 void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenuProvider> menuProvider)
138 m_menuProvider = menuProvider;
140 m_contextMenu = createContextMenu(event);
141 if (!m_contextMenu) {
146 m_menuProvider->populateContextMenu(m_contextMenu.get());
147 if (m_hitTestResult.isSelected()) {
148 appendItem(*separatorItem(), m_contextMenu.get());
151 showContextMenu(event);
154 PassOwnPtr<ContextMenu> ContextMenuController::createContextMenu(Event* event)
156 if (!event->isMouseEvent())
159 MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
160 HitTestResult result(mouseEvent->absoluteLocation());
162 if (Frame* frame = event->target()->toNode()->document()->frame())
163 result = frame->eventHandler()->hitTestResultAtPoint(mouseEvent->absoluteLocation(), false);
165 if (!result.innerNonSharedNode())
168 m_hitTestResult = result;
170 #if ENABLE(TIZEN_CONTEXT_MENU)
171 return adoptPtr(new ContextMenu(result));
173 return adoptPtr(new ContextMenu);
177 void ContextMenuController::showContextMenu(Event* event)
179 #if ENABLE(INSPECTOR) && !ENABLE(TIZEN_CONTEXT_MENU)
180 if (m_page->inspectorController()->enabled())
181 addInspectElementItem();
184 #if USE(CROSS_PLATFORM_CONTEXT_MENUS)
185 m_contextMenu = m_client->customizeMenu(m_contextMenu.release());
187 PlatformMenuDescription customMenu = m_client->getCustomMenuFromDefaultItems(m_contextMenu.get());
188 m_contextMenu->setPlatformDescription(customMenu);
190 event->setDefaultHandled();
193 static void openNewWindow(const KURL& urlToLoad, Frame* frame)
195 if (Page* oldPage = frame->page()) {
196 FrameLoadRequest request(frame->document()->securityOrigin(), ResourceRequest(urlToLoad, frame->loader()->outgoingReferrer()));
197 if (Page* newPage = oldPage->chrome()->createWindow(frame, request, WindowFeatures(), NavigationAction(request.resourceRequest()))) {
198 newPage->mainFrame()->loader()->loadFrameRequest(request, false, false, 0, 0, MaybeSendReferrer);
199 newPage->chrome()->show();
205 static void insertUnicodeCharacter(UChar character, Frame* frame)
207 String text(&character, 1);
208 if (!frame->editor()->shouldInsertText(text, frame->selection()->toNormalizedRange().get(), EditorInsertActionTyped))
211 TypingCommand::insertText(frame->document(), text, 0, TypingCommand::TextCompositionNone);
215 void ContextMenuController::contextMenuItemSelected(ContextMenuItem* item)
217 ASSERT(item->type() == ActionType || item->type() == CheckableActionType);
219 if (item->action() >= ContextMenuItemBaseApplicationTag) {
220 m_client->contextMenuItemSelected(item, m_contextMenu.get());
224 if (item->action() >= ContextMenuItemBaseCustomTag) {
225 ASSERT(m_menuProvider);
226 m_menuProvider->contextMenuItemSelected(item);
230 Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
234 #if ENABLE(TIZEN_WEBKIT_PASTEBOARD)
235 if (Page* page = frame->page()) {
236 if (item->action() == ContextMenuItemTagCopyLinkToClipboard
237 || item->action() == ContextMenuItemTagCopyImageToClipboard
238 || item->action() == ContextMenuItemTagCopyImageUrlToClipboard
239 || item->action() == ContextMenuItemTagCopyMediaLinkToClipboard
240 || item->action() == ContextMenuItemTagCopy
241 || item->action() == ContextMenuItemTagCut)
242 Pasteboard::generalPasteboard()->setPage(page);
246 switch (item->action()) {
247 case ContextMenuItemTagOpenLinkInNewWindow:
248 openNewWindow(m_hitTestResult.absoluteLinkURL(), frame);
250 case ContextMenuItemTagDownloadLinkToDisk:
251 // FIXME: Some day we should be able to do this from within WebCore.
252 m_client->downloadURL(m_hitTestResult.absoluteLinkURL());
254 case ContextMenuItemTagCopyLinkToClipboard:
255 frame->editor()->copyURL(m_hitTestResult.absoluteLinkURL(), m_hitTestResult.textContent());
257 case ContextMenuItemTagOpenImageInNewWindow:
258 openNewWindow(m_hitTestResult.absoluteImageURL(), frame);
260 case ContextMenuItemTagDownloadImageToDisk:
261 // FIXME: Some day we should be able to do this from within WebCore.
262 #if ENABLE(TIZEN_INSTALL_CONTENT)
263 m_client->saveAsImage(m_contextMenu.get(), frame, m_hitTestResult.absoluteImageURL());
265 m_client->downloadURL(m_hitTestResult.absoluteImageURL());
268 #if ENABLE(TIZEN_INSTALL_CONTENT)
269 case ContextMenuItemTagSendImageViaEmail:
270 m_client->sendImageViaEmail(m_contextMenu.get(), frame, m_hitTestResult.absoluteImageURL());
272 case ContextMenuItemTagSendImageViaMessage:
273 m_client->sendImageViaMessage(m_contextMenu.get(), frame, m_hitTestResult.absoluteImageURL());
276 case ContextMenuItemTagCopyImageToClipboard:
277 // FIXME: The Pasteboard class is not written yet
278 // For now, call into the client. This is temporary!
279 frame->editor()->copyImage(m_hitTestResult);
281 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
282 case ContextMenuItemTagCopyImageUrlToClipboard:
283 frame->editor()->copyURL(m_hitTestResult.absoluteImageURL(), m_hitTestResult.textContent());
286 case ContextMenuItemTagOpenMediaInNewWindow:
287 openNewWindow(m_hitTestResult.absoluteMediaURL(), frame);
289 case ContextMenuItemTagCopyMediaLinkToClipboard:
290 frame->editor()->copyURL(m_hitTestResult.absoluteMediaURL(), m_hitTestResult.textContent());
292 case ContextMenuItemTagToggleMediaControls:
293 m_hitTestResult.toggleMediaControlsDisplay();
295 case ContextMenuItemTagToggleMediaLoop:
296 m_hitTestResult.toggleMediaLoopPlayback();
298 case ContextMenuItemTagEnterVideoFullscreen:
299 m_hitTestResult.enterFullscreenForVideo();
301 case ContextMenuItemTagMediaPlayPause:
302 m_hitTestResult.toggleMediaPlayState();
304 case ContextMenuItemTagMediaMute:
305 m_hitTestResult.toggleMediaMuteState();
307 case ContextMenuItemTagOpenFrameInNewWindow: {
308 DocumentLoader* loader = frame->loader()->documentLoader();
309 if (!loader->unreachableURL().isEmpty())
310 openNewWindow(loader->unreachableURL(), frame);
312 openNewWindow(loader->url(), frame);
315 case ContextMenuItemTagCopy:
316 frame->editor()->copy();
318 case ContextMenuItemTagGoBack:
319 if (Page* page = frame->page())
320 page->backForward()->goBackOrForward(-1);
322 case ContextMenuItemTagGoForward:
323 if (Page* page = frame->page())
324 page->backForward()->goBackOrForward(1);
326 case ContextMenuItemTagStop:
327 frame->loader()->stop();
329 case ContextMenuItemTagReload:
330 frame->loader()->reload();
332 case ContextMenuItemTagCut:
333 frame->editor()->command("Cut").execute();
335 case ContextMenuItemTagPaste:
336 frame->editor()->command("Paste").execute();
339 case ContextMenuItemTagDelete:
340 frame->editor()->performDelete();
342 case ContextMenuItemTagUnicodeInsertLRMMark:
343 insertUnicodeCharacter(leftToRightMark, frame);
345 case ContextMenuItemTagUnicodeInsertRLMMark:
346 insertUnicodeCharacter(rightToLeftMark, frame);
348 case ContextMenuItemTagUnicodeInsertLREMark:
349 insertUnicodeCharacter(leftToRightEmbed, frame);
351 case ContextMenuItemTagUnicodeInsertRLEMark:
352 insertUnicodeCharacter(rightToLeftEmbed, frame);
354 case ContextMenuItemTagUnicodeInsertLROMark:
355 insertUnicodeCharacter(leftToRightOverride, frame);
357 case ContextMenuItemTagUnicodeInsertRLOMark:
358 insertUnicodeCharacter(rightToLeftOverride, frame);
360 case ContextMenuItemTagUnicodeInsertPDFMark:
361 insertUnicodeCharacter(popDirectionalFormatting, frame);
363 case ContextMenuItemTagUnicodeInsertZWSMark:
364 insertUnicodeCharacter(zeroWidthSpace, frame);
366 case ContextMenuItemTagUnicodeInsertZWJMark:
367 insertUnicodeCharacter(zeroWidthJoiner, frame);
369 case ContextMenuItemTagUnicodeInsertZWNJMark:
370 insertUnicodeCharacter(zeroWidthNonJoiner, frame);
373 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
374 case ContextMenuItemTagSelectAll:
375 frame->editor()->command("SelectAll").execute();
378 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
379 case ContextMenuItemTagSelectWord:
380 frame->editor()->command("SelectWord").execute();
383 case ContextMenuItemTagSpellingGuess:
384 ASSERT(frame->editor()->selectedText().length());
385 if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(), EditorInsertActionPasted)) {
386 Document* document = frame->document();
387 RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting);
388 applyCommand(command);
389 frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
392 case ContextMenuItemTagIgnoreSpelling:
393 frame->editor()->ignoreSpelling();
395 case ContextMenuItemTagLearnSpelling:
396 frame->editor()->learnSpelling();
398 case ContextMenuItemTagSearchWeb:
399 m_client->searchWithGoogle(frame);
401 case ContextMenuItemTagLookUpInDictionary:
402 // FIXME: Some day we may be able to do this from within WebCore.
403 m_client->lookUpInDictionary(frame);
405 case ContextMenuItemTagOpenLink:
406 if (Frame* targetFrame = m_hitTestResult.targetFrame())
407 targetFrame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(m_hitTestResult.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, false, 0, 0, MaybeSendReferrer);
409 openNewWindow(m_hitTestResult.absoluteLinkURL(), frame);
411 case ContextMenuItemTagBold:
412 frame->editor()->command("ToggleBold").execute();
414 case ContextMenuItemTagItalic:
415 frame->editor()->command("ToggleItalic").execute();
417 case ContextMenuItemTagUnderline:
418 frame->editor()->toggleUnderline();
420 case ContextMenuItemTagOutline:
421 // We actually never enable this because CSS does not have a way to specify an outline font,
422 // which may make this difficult to implement. Maybe a special case of text-shadow?
424 case ContextMenuItemTagStartSpeaking: {
426 RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
427 if (!selectedRange || selectedRange->collapsed(ec)) {
428 Document* document = m_hitTestResult.innerNonSharedNode()->document();
429 selectedRange = document->createRange();
430 selectedRange->selectNode(document->documentElement(), ec);
432 m_client->speak(plainText(selectedRange.get()));
435 case ContextMenuItemTagStopSpeaking:
436 m_client->stopSpeaking();
438 case ContextMenuItemTagDefaultDirection:
439 frame->editor()->setBaseWritingDirection(NaturalWritingDirection);
441 case ContextMenuItemTagLeftToRight:
442 frame->editor()->setBaseWritingDirection(LeftToRightWritingDirection);
444 case ContextMenuItemTagRightToLeft:
445 frame->editor()->setBaseWritingDirection(RightToLeftWritingDirection);
447 case ContextMenuItemTagTextDirectionDefault:
448 frame->editor()->command("MakeTextWritingDirectionNatural").execute();
450 case ContextMenuItemTagTextDirectionLeftToRight:
451 frame->editor()->command("MakeTextWritingDirectionLeftToRight").execute();
453 case ContextMenuItemTagTextDirectionRightToLeft:
454 frame->editor()->command("MakeTextWritingDirectionRightToLeft").execute();
457 case ContextMenuItemTagSearchInSpotlight:
458 m_client->searchWithSpotlight();
461 case ContextMenuItemTagShowSpellingPanel:
462 frame->editor()->showSpellingGuessPanel();
464 case ContextMenuItemTagCheckSpelling:
465 frame->editor()->advanceToNextMisspelling();
467 case ContextMenuItemTagCheckSpellingWhileTyping:
468 frame->editor()->toggleContinuousSpellChecking();
470 case ContextMenuItemTagCheckGrammarWithSpelling:
471 frame->editor()->toggleGrammarChecking();
474 case ContextMenuItemTagShowFonts:
475 frame->editor()->showFontPanel();
477 case ContextMenuItemTagStyles:
478 frame->editor()->showStylesPanel();
480 case ContextMenuItemTagShowColors:
481 frame->editor()->showColorPanel();
484 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
485 case ContextMenuItemTagMakeUpperCase:
486 frame->editor()->uppercaseWord();
488 case ContextMenuItemTagMakeLowerCase:
489 frame->editor()->lowercaseWord();
491 case ContextMenuItemTagCapitalize:
492 frame->editor()->capitalizeWord();
494 case ContextMenuItemTagShowSubstitutions:
495 frame->editor()->showSubstitutionsPanel();
497 case ContextMenuItemTagSmartCopyPaste:
498 frame->editor()->toggleSmartInsertDelete();
500 case ContextMenuItemTagSmartQuotes:
501 frame->editor()->toggleAutomaticQuoteSubstitution();
503 case ContextMenuItemTagSmartDashes:
504 frame->editor()->toggleAutomaticDashSubstitution();
506 case ContextMenuItemTagSmartLinks:
507 frame->editor()->toggleAutomaticLinkDetection();
509 case ContextMenuItemTagTextReplacement:
510 frame->editor()->toggleAutomaticTextReplacement();
512 case ContextMenuItemTagCorrectSpellingAutomatically:
513 frame->editor()->toggleAutomaticSpellingCorrection();
515 case ContextMenuItemTagChangeBack:
516 frame->editor()->changeBackToReplacedString(m_hitTestResult.replacedString());
519 #if ENABLE(INSPECTOR)
520 case ContextMenuItemTagInspectElement:
521 if (Page* page = frame->page())
522 page->inspectorController()->inspect(m_hitTestResult.innerNonSharedNode());
530 void ContextMenuController::appendItem(ContextMenuItem& menuItem, ContextMenu* parentMenu)
532 checkOrEnableIfNeeded(menuItem);
534 parentMenu->appendItem(menuItem);
537 void ContextMenuController::createAndAppendFontSubMenu(ContextMenuItem& fontMenuItem)
539 ContextMenu fontMenu;
542 ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts());
544 ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold());
545 ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic());
546 ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline());
547 ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline());
549 ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles());
550 ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors());
554 appendItem(showFonts, &fontMenu);
556 appendItem(bold, &fontMenu);
557 appendItem(italic, &fontMenu);
558 appendItem(underline, &fontMenu);
559 appendItem(outline, &fontMenu);
561 appendItem(styles, &fontMenu);
562 appendItem(*separatorItem(), &fontMenu);
563 appendItem(showColors, &fontMenu);
566 fontMenuItem.setSubMenu(&fontMenu);
572 void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem)
574 ContextMenu spellingAndGrammarMenu;
576 ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
577 contextMenuItemTagShowSpellingPanel(true));
578 ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
579 contextMenuItemTagCheckSpelling());
580 ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
581 contextMenuItemTagCheckSpellingWhileTyping());
582 ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling,
583 contextMenuItemTagCheckGrammarWithSpelling());
584 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
585 ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically,
586 contextMenuItemTagCorrectSpellingAutomatically());
589 appendItem(showSpellingPanel, &spellingAndGrammarMenu);
590 appendItem(checkSpelling, &spellingAndGrammarMenu);
591 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
592 appendItem(*separatorItem(), &spellingAndGrammarMenu);
594 appendItem(checkAsYouType, &spellingAndGrammarMenu);
595 appendItem(grammarWithSpelling, &spellingAndGrammarMenu);
596 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
597 appendItem(correctSpelling, &spellingAndGrammarMenu);
600 spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
603 #endif // !PLATFORM(GTK)
608 void ContextMenuController::createAndAppendSpeechSubMenu(ContextMenuItem& speechMenuItem)
610 ContextMenu speechMenu;
612 ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking());
613 ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking());
615 appendItem(start, &speechMenu);
616 appendItem(stop, &speechMenu);
618 speechMenuItem.setSubMenu(&speechMenu);
625 void ContextMenuController::createAndAppendUnicodeSubMenu(ContextMenuItem& unicodeMenuItem)
627 ContextMenu unicodeMenu;
629 ContextMenuItem leftToRightMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLRMMark, contextMenuItemTagUnicodeInsertLRMMark());
630 ContextMenuItem rightToLeftMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLMMark, contextMenuItemTagUnicodeInsertRLMMark());
631 ContextMenuItem leftToRightEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLREMark, contextMenuItemTagUnicodeInsertLREMark());
632 ContextMenuItem rightToLeftEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLEMark, contextMenuItemTagUnicodeInsertRLEMark());
633 ContextMenuItem leftToRightOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLROMark, contextMenuItemTagUnicodeInsertLROMark());
634 ContextMenuItem rightToLeftOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLOMark, contextMenuItemTagUnicodeInsertRLOMark());
635 ContextMenuItem popDirectionalFormattingMenuItem(ActionType, ContextMenuItemTagUnicodeInsertPDFMark, contextMenuItemTagUnicodeInsertPDFMark());
636 ContextMenuItem zeroWidthSpaceMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWSMark, contextMenuItemTagUnicodeInsertZWSMark());
637 ContextMenuItem zeroWidthJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWJMark, contextMenuItemTagUnicodeInsertZWJMark());
638 ContextMenuItem zeroWidthNonJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWNJMark, contextMenuItemTagUnicodeInsertZWNJMark());
640 appendItem(leftToRightMarkMenuItem, &unicodeMenu);
641 appendItem(rightToLeftMarkMenuItem, &unicodeMenu);
642 appendItem(leftToRightEmbedMenuItem, &unicodeMenu);
643 appendItem(rightToLeftEmbedMenuItem, &unicodeMenu);
644 appendItem(leftToRightOverrideMenuItem, &unicodeMenu);
645 appendItem(rightToLeftOverrideMenuItem, &unicodeMenu);
646 appendItem(popDirectionalFormattingMenuItem, &unicodeMenu);
647 appendItem(zeroWidthSpaceMenuItem, &unicodeMenu);
648 appendItem(zeroWidthJoinerMenuItem, &unicodeMenu);
649 appendItem(zeroWidthNonJoinerMenuItem, &unicodeMenu);
651 unicodeMenuItem.setSubMenu(&unicodeMenu);
656 void ContextMenuController::createAndAppendWritingDirectionSubMenu(ContextMenuItem& writingDirectionMenuItem)
658 ContextMenu writingDirectionMenu;
660 ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection,
661 contextMenuItemTagDefaultDirection());
662 ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight());
663 ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft());
665 appendItem(defaultItem, &writingDirectionMenu);
666 appendItem(ltr, &writingDirectionMenu);
667 appendItem(rtl, &writingDirectionMenu);
669 writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
672 void ContextMenuController::createAndAppendTextDirectionSubMenu(ContextMenuItem& textDirectionMenuItem)
674 ContextMenu textDirectionMenu;
676 ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
677 ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
678 ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
680 appendItem(defaultItem, &textDirectionMenu);
681 appendItem(ltr, &textDirectionMenu);
682 appendItem(rtl, &textDirectionMenu);
684 textDirectionMenuItem.setSubMenu(&textDirectionMenu);
689 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
691 void ContextMenuController::createAndAppendSubstitutionsSubMenu(ContextMenuItem& substitutionsMenuItem)
693 ContextMenu substitutionsMenu;
695 ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
696 ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
697 ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
698 ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
699 ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
700 ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
702 appendItem(showSubstitutions, &substitutionsMenu);
703 appendItem(*separatorItem(), &substitutionsMenu);
704 appendItem(smartCopyPaste, &substitutionsMenu);
705 appendItem(smartQuotes, &substitutionsMenu);
706 appendItem(smartDashes, &substitutionsMenu);
707 appendItem(smartLinks, &substitutionsMenu);
708 appendItem(textReplacement, &substitutionsMenu);
710 substitutionsMenuItem.setSubMenu(&substitutionsMenu);
713 void ContextMenuController::createAndAppendTransformationsSubMenu(ContextMenuItem& transformationsMenuItem)
715 ContextMenu transformationsMenu;
717 ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
718 ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
719 ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
721 appendItem(makeUpperCase, &transformationsMenu);
722 appendItem(makeLowerCase, &transformationsMenu);
723 appendItem(capitalize, &transformationsMenu);
725 transformationsMenuItem.setSubMenu(&transformationsMenu);
730 static bool selectionContainsPossibleWord(Frame* frame)
732 // Current algorithm: look for a character that's not just a separator.
733 for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) {
734 int length = it.length();
735 const UChar* characters = it.characters();
736 for (int i = 0; i < length; ++i)
737 if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph)))
744 #if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
745 #define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 1
747 #define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 0
751 void ContextMenuController::populate()
753 ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink());
754 ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow,
755 contextMenuItemTagOpenLinkInNewWindow());
756 ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk,
757 contextMenuItemTagDownloadLinkToDisk());
758 ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard,
759 contextMenuItemTagCopyLinkToClipboard());
760 ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow,
761 contextMenuItemTagOpenImageInNewWindow());
762 ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk,
763 contextMenuItemTagDownloadImageToDisk());
764 ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard,
765 contextMenuItemTagCopyImageToClipboard());
766 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
767 ContextMenuItem CopyImageUrlItem(ActionType, ContextMenuItemTagCopyImageUrlToClipboard,
768 contextMenuItemTagCopyImageUrlToClipboard());
770 ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String());
771 ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard,
773 ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause,
774 contextMenuItemTagMediaPlay());
775 ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute,
776 contextMenuItemTagMediaMute());
777 ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls,
778 contextMenuItemTagToggleMediaControls());
779 ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop,
780 contextMenuItemTagToggleMediaLoop());
781 ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen,
782 contextMenuItemTagEnterVideoFullscreen());
784 ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight,
785 contextMenuItemTagSearchInSpotlight());
788 ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb());
790 ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy());
791 ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack());
792 ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward());
793 ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop());
794 ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload());
795 ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow,
796 contextMenuItemTagOpenFrameInNewWindow());
797 ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound,
798 contextMenuItemTagNoGuessesFound());
799 ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling,
800 contextMenuItemTagIgnoreSpelling());
801 ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling,
802 contextMenuItemTagLearnSpelling());
803 ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar,
804 contextMenuItemTagIgnoreGrammar());
805 ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut());
806 ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste());
808 ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete());
810 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
811 ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
813 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
814 ContextMenuItem SelectWordItem(ActionType, ContextMenuItemTagSelectWord, contextMenuItemTagSelectWord());
817 Node* node = m_hitTestResult.innerNonSharedNode();
821 if (!m_hitTestResult.isContentEditable() && (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()))
824 Frame* frame = node->document()->frame();
828 if (!m_hitTestResult.isContentEditable()) {
829 FrameLoader* loader = frame->loader();
830 KURL linkURL = m_hitTestResult.absoluteLinkURL();
831 if (!linkURL.isEmpty()) {
832 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
833 if (m_hitTestResult.isSelected()) {
834 if (selectionContainsPossibleWord(frame)) {
835 appendItem(SearchWebItem, m_contextMenu.get());
837 appendItem(CopyItem, m_contextMenu.get());
841 #if ENABLE(TIZEN_DOWNLOAD_LINK_FILTER)
842 if (loader->client()->canHandleRequest(ResourceRequest(linkURL)) &&
843 (linkURL.protocolIs("http") || linkURL.protocolIs("https") || linkURL.protocolIs("ftp") || linkURL.protocolIs("ftps"))) {
845 if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) {
847 appendItem(OpenLinkItem, m_contextMenu.get());
848 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
849 appendItem(DownloadFileItem, m_contextMenu.get());
852 if (m_hitTestResult.isSelected())
853 appendItem(CopyItem, m_contextMenu.get());
855 appendItem(CopyLinkItem, m_contextMenu.get());
858 KURL imageURL = m_hitTestResult.absoluteImageURL();
859 if (!imageURL.isEmpty()) {
860 if (!linkURL.isEmpty())
861 appendItem(*separatorItem(), m_contextMenu.get());
863 appendItem(OpenImageInNewWindowItem, m_contextMenu.get());
864 appendItem(DownloadImageItem, m_contextMenu.get());
865 if (imageURL.isLocalFile() || m_hitTestResult.image())
866 appendItem(CopyImageItem, m_contextMenu.get());
867 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
868 appendItem(CopyImageUrlItem, m_contextMenu.get());
872 KURL mediaURL = m_hitTestResult.absoluteMediaURL();
873 if (!mediaURL.isEmpty()) {
874 if (!linkURL.isEmpty() || !imageURL.isEmpty())
875 appendItem(*separatorItem(), m_contextMenu.get());
877 appendItem(MediaPlayPause, m_contextMenu.get());
878 appendItem(MediaMute, m_contextMenu.get());
879 appendItem(ToggleMediaControls, m_contextMenu.get());
880 appendItem(ToggleMediaLoop, m_contextMenu.get());
881 appendItem(EnterVideoFullscreen, m_contextMenu.get());
883 appendItem(*separatorItem(), m_contextMenu.get());
884 appendItem(CopyMediaLinkItem, m_contextMenu.get());
885 appendItem(OpenMediaInNewWindowItem, m_contextMenu.get());
888 if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
889 if (m_hitTestResult.isSelected()) {
890 if (selectionContainsPossibleWord(frame)) {
892 String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
893 ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
895 #if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
896 appendItem(SearchSpotlightItem, m_contextMenu.get());
898 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
903 appendItem(SearchWebItem, m_contextMenu.get());
904 appendItem(*separatorItem(), m_contextMenu.get());
907 #if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
908 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
909 appendItem(*separatorItem(), m_contextMenu.get());
913 appendItem(CopyItem, m_contextMenu.get());
915 appendItem(*separatorItem(), m_contextMenu.get());
917 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
918 createAndAppendSpeechSubMenu(SpeechMenuItem);
919 appendItem(SpeechMenuItem, m_contextMenu.get());
922 #if ENABLE(INSPECTOR)
923 if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) {
926 // In GTK+ unavailable items are not hidden but insensitive
928 appendItem(BackItem, m_contextMenu.get());
929 appendItem(ForwardItem, m_contextMenu.get());
930 appendItem(StopItem, m_contextMenu.get());
931 appendItem(ReloadItem, m_contextMenu.get());
933 if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1))
934 appendItem(BackItem, m_contextMenu.get());
936 if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1))
937 appendItem(ForwardItem, m_contextMenu.get());
939 // use isLoadingInAPISense rather than isLoading because Stop/Reload are
940 // intended to match WebKit's API, not WebCore's internal notion of loading status
941 if (loader->documentLoader()->isLoadingInAPISense())
942 appendItem(StopItem, m_contextMenu.get());
944 appendItem(ReloadItem, m_contextMenu.get());
946 #if ENABLE(INSPECTOR)
950 if (frame->page() && frame != frame->page()->mainFrame())
951 appendItem(OpenFrameItem, m_contextMenu.get());
954 } else { // Make an editing context menu
955 FrameSelection* selection = frame->selection();
956 bool inPasswordField = selection->isInPasswordField();
957 bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
959 if (!inPasswordField && spellCheckingEnabled) {
960 // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
961 // is never considered a misspelling and bad grammar at the same time)
964 Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
965 if (misspelling || badGrammar) {
966 size_t size = guesses.size();
968 // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
969 // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
971 appendItem(NoGuessesItem, m_contextMenu.get());
972 appendItem(*separatorItem(), m_contextMenu.get());
975 for (unsigned i = 0; i < size; i++) {
976 const String &guess = guesses[i];
977 if (!guess.isEmpty()) {
978 ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
979 appendItem(item, m_contextMenu.get());
982 appendItem(*separatorItem(), m_contextMenu.get());
986 appendItem(IgnoreSpellingItem, m_contextMenu.get());
987 appendItem(LearnSpellingItem, m_contextMenu.get());
989 appendItem(IgnoreGrammarItem, m_contextMenu.get());
990 appendItem(*separatorItem(), m_contextMenu.get());
991 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
993 // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
994 String replacedString = m_hitTestResult.replacedString();
995 if (!replacedString.isEmpty()) {
996 ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
997 appendItem(item, m_contextMenu.get());
998 appendItem(*separatorItem(), m_contextMenu.get());
1004 FrameLoader* loader = frame->loader();
1005 KURL linkURL = m_hitTestResult.absoluteLinkURL();
1006 if (!linkURL.isEmpty()) {
1007 if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) {
1008 appendItem(OpenLinkItem, m_contextMenu.get());
1009 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
1010 appendItem(DownloadFileItem, m_contextMenu.get());
1012 appendItem(CopyLinkItem, m_contextMenu.get());
1013 appendItem(*separatorItem(), m_contextMenu.get());
1016 if (m_hitTestResult.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) {
1018 String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
1019 ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
1021 #if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
1022 appendItem(SearchSpotlightItem, m_contextMenu.get());
1024 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
1029 appendItem(SearchWebItem, m_contextMenu.get());
1030 appendItem(*separatorItem(), m_contextMenu.get());
1033 #if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
1034 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
1035 appendItem(*separatorItem(), m_contextMenu.get());
1039 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1040 if (m_hitTestResult.isSelected()) {
1041 appendItem(CutItem, m_contextMenu.get());
1042 appendItem(CopyItem, m_contextMenu.get());
1045 appendItem(CutItem, m_contextMenu.get());
1046 appendItem(CopyItem, m_contextMenu.get());
1048 appendItem(PasteItem, m_contextMenu.get());
1050 appendItem(DeleteItem, m_contextMenu.get());
1051 appendItem(*separatorItem(), m_contextMenu.get());
1053 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1054 if (frame->selection()) {
1055 Node* baseNode = frame->selection()->base().containerNode();
1056 if (baseNode && baseNode->isTextNode()) {
1057 if (!(baseNode->textContent().isEmpty())) {
1059 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
1060 appendItem(SelectAllItem, m_contextMenu.get());
1062 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
1063 appendItem(SelectWordItem, m_contextMenu.get());
1065 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1071 if (!inPasswordField) {
1073 #if !ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1074 appendItem(*separatorItem(), m_contextMenu.get());
1075 ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
1076 contextMenuItemTagSpellingMenu());
1077 createAndAppendSpellingAndGrammarSubMenu(SpellingAndGrammarMenuItem);
1078 appendItem(SpellingAndGrammarMenuItem, m_contextMenu.get());
1079 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1081 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
1082 ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu,
1083 contextMenuItemTagSubstitutionsMenu());
1084 createAndAppendSubstitutionsSubMenu(substitutionsMenuItem);
1085 appendItem(substitutionsMenuItem, m_contextMenu.get());
1086 ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu,
1087 contextMenuItemTagTransformationsMenu());
1088 createAndAppendTransformationsSubMenu(transformationsMenuItem);
1089 appendItem(transformationsMenuItem, m_contextMenu.get());
1092 bool shouldShowFontMenu = frame->editor()->canEditRichly();
1094 #if ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1095 bool shouldShowFontMenu = false;
1097 bool shouldShowFontMenu = true;
1098 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1100 if (shouldShowFontMenu) {
1101 ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu,
1102 contextMenuItemTagFontMenu());
1103 createAndAppendFontSubMenu(FontMenuItem);
1104 appendItem(FontMenuItem, m_contextMenu.get());
1107 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
1108 createAndAppendSpeechSubMenu(SpeechMenuItem);
1109 appendItem(SpeechMenuItem, m_contextMenu.get());
1112 EditorClient* client = frame->editor()->client();
1113 if (client && client->shouldShowUnicodeMenu()) {
1114 ContextMenuItem UnicodeMenuItem(SubmenuType, ContextMenuItemTagUnicode, contextMenuItemTagUnicode());
1115 createAndAppendUnicodeSubMenu(UnicodeMenuItem);
1116 appendItem(*separatorItem(), m_contextMenu.get());
1117 appendItem(UnicodeMenuItem, m_contextMenu.get());
1120 ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu,
1121 contextMenuItemTagWritingDirectionMenu());
1122 #if !ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1123 createAndAppendWritingDirectionSubMenu(WritingDirectionMenuItem);
1124 appendItem(WritingDirectionMenuItem, m_contextMenu.get());
1125 if (Page* page = frame->page()) {
1126 if (Settings* settings = page->settings()) {
1127 bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
1128 || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection());
1129 if (includeTextDirectionSubmenu) {
1130 ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu,
1131 contextMenuItemTagTextDirectionMenu());
1132 createAndAppendTextDirectionSubMenu(TextDirectionMenuItem);
1133 appendItem(TextDirectionMenuItem, m_contextMenu.get());
1137 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1143 #if ENABLE(INSPECTOR)
1144 void ContextMenuController::addInspectElementItem()
1146 Node* node = m_hitTestResult.innerNonSharedNode();
1150 Frame* frame = node->document()->frame();
1154 Page* page = frame->page();
1158 if (!page->inspectorController())
1161 ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement());
1162 #if USE(CROSS_PLATFORM_CONTEXT_MENUS)
1163 if (!m_contextMenu->items().isEmpty())
1165 if (m_contextMenu->itemCount())
1167 appendItem(*separatorItem(), m_contextMenu.get());
1168 appendItem(InspectElementItem, m_contextMenu.get());
1170 #endif // ENABLE(INSPECTOR)
1172 void ContextMenuController::checkOrEnableIfNeeded(ContextMenuItem& item) const
1174 if (item.type() == SeparatorType)
1177 Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
1181 // Custom items already have proper checked and enabled values.
1182 if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
1185 bool shouldEnable = true;
1186 bool shouldCheck = false;
1188 switch (item.action()) {
1189 case ContextMenuItemTagCheckSpelling:
1190 shouldEnable = frame->editor()->canEdit();
1192 case ContextMenuItemTagDefaultDirection:
1193 shouldCheck = false;
1194 shouldEnable = false;
1196 case ContextMenuItemTagLeftToRight:
1197 case ContextMenuItemTagRightToLeft: {
1198 String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl";
1199 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyDirection, direction) != FalseTriState;
1200 shouldEnable = true;
1203 case ContextMenuItemTagTextDirectionDefault: {
1204 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural");
1205 shouldCheck = command.state() == TrueTriState;
1206 shouldEnable = command.isEnabled();
1209 case ContextMenuItemTagTextDirectionLeftToRight: {
1210 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight");
1211 shouldCheck = command.state() == TrueTriState;
1212 shouldEnable = command.isEnabled();
1215 case ContextMenuItemTagTextDirectionRightToLeft: {
1216 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft");
1217 shouldCheck = command.state() == TrueTriState;
1218 shouldEnable = command.isEnabled();
1221 case ContextMenuItemTagCopy:
1222 shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy();
1224 case ContextMenuItemTagCut:
1225 shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut();
1227 case ContextMenuItemTagIgnoreSpelling:
1228 case ContextMenuItemTagLearnSpelling:
1229 shouldEnable = frame->selection()->isRange();
1231 case ContextMenuItemTagPaste:
1232 shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste();
1234 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
1235 case ContextMenuItemTagSelectWord:
1236 shouldEnable = frame->editor()->canSelectRange();
1240 case ContextMenuItemTagDelete:
1241 shouldEnable = frame->editor()->canDelete();
1243 case ContextMenuItemTagInputMethods:
1244 case ContextMenuItemTagUnicode:
1245 case ContextMenuItemTagUnicodeInsertLRMMark:
1246 case ContextMenuItemTagUnicodeInsertRLMMark:
1247 case ContextMenuItemTagUnicodeInsertLREMark:
1248 case ContextMenuItemTagUnicodeInsertRLEMark:
1249 case ContextMenuItemTagUnicodeInsertLROMark:
1250 case ContextMenuItemTagUnicodeInsertRLOMark:
1251 case ContextMenuItemTagUnicodeInsertPDFMark:
1252 case ContextMenuItemTagUnicodeInsertZWSMark:
1253 case ContextMenuItemTagUnicodeInsertZWJMark:
1254 case ContextMenuItemTagUnicodeInsertZWNJMark:
1255 shouldEnable = true;
1258 #if PLATFORM(GTK) || PLATFORM(EFL)
1259 case ContextMenuItemTagSelectAll:
1260 shouldEnable = true;
1263 case ContextMenuItemTagUnderline: {
1264 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") != FalseTriState;
1265 shouldEnable = frame->editor()->canEditRichly();
1268 case ContextMenuItemTagLookUpInDictionary:
1269 shouldEnable = frame->selection()->isRange();
1271 case ContextMenuItemTagCheckGrammarWithSpelling:
1272 if (frame->editor()->isGrammarCheckingEnabled())
1274 shouldEnable = true;
1276 case ContextMenuItemTagItalic: {
1277 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic") != FalseTriState;
1278 shouldEnable = frame->editor()->canEditRichly();
1281 case ContextMenuItemTagBold: {
1282 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold") != FalseTriState;
1283 shouldEnable = frame->editor()->canEditRichly();
1286 case ContextMenuItemTagOutline:
1287 shouldEnable = false;
1289 case ContextMenuItemTagShowSpellingPanel:
1290 if (frame->editor()->spellingPanelIsShowing())
1291 item.setTitle(contextMenuItemTagShowSpellingPanel(false));
1293 item.setTitle(contextMenuItemTagShowSpellingPanel(true));
1294 shouldEnable = frame->editor()->canEdit();
1296 case ContextMenuItemTagNoGuessesFound:
1297 shouldEnable = false;
1299 case ContextMenuItemTagCheckSpellingWhileTyping:
1300 shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled();
1303 case ContextMenuItemTagSubstitutionsMenu:
1304 case ContextMenuItemTagTransformationsMenu:
1306 case ContextMenuItemTagShowSubstitutions:
1307 #ifndef BUILDING_ON_LEOPARD
1308 if (frame->editor()->substitutionsPanelIsShowing())
1309 item.setTitle(contextMenuItemTagShowSubstitutions(false));
1311 item.setTitle(contextMenuItemTagShowSubstitutions(true));
1312 shouldEnable = frame->editor()->canEdit();
1315 case ContextMenuItemTagMakeUpperCase:
1316 case ContextMenuItemTagMakeLowerCase:
1317 case ContextMenuItemTagCapitalize:
1318 case ContextMenuItemTagChangeBack:
1319 shouldEnable = frame->editor()->canEdit();
1321 case ContextMenuItemTagCorrectSpellingAutomatically:
1322 #ifndef BUILDING_ON_LEOPARD
1323 shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled();
1326 case ContextMenuItemTagSmartCopyPaste:
1327 #ifndef BUILDING_ON_LEOPARD
1328 shouldCheck = frame->editor()->smartInsertDeleteEnabled();
1331 case ContextMenuItemTagSmartQuotes:
1332 #ifndef BUILDING_ON_LEOPARD
1333 shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled();
1336 case ContextMenuItemTagSmartDashes:
1337 #ifndef BUILDING_ON_LEOPARD
1338 shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled();
1341 case ContextMenuItemTagSmartLinks:
1342 #ifndef BUILDING_ON_LEOPARD
1343 shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled();
1346 case ContextMenuItemTagTextReplacement:
1347 #ifndef BUILDING_ON_LEOPARD
1348 shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled();
1351 case ContextMenuItemTagStopSpeaking:
1352 shouldEnable = client() && client()->isSpeaking();
1354 #else // PLATFORM(MAC) ends here
1355 case ContextMenuItemTagStopSpeaking:
1359 case ContextMenuItemTagGoBack:
1360 shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1);
1362 case ContextMenuItemTagGoForward:
1363 shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1);
1365 case ContextMenuItemTagStop:
1366 shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense();
1368 case ContextMenuItemTagReload:
1369 shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense();
1371 case ContextMenuItemTagFontMenu:
1372 shouldEnable = frame->editor()->canEditRichly();
1375 case ContextMenuItemTagGoBack:
1376 case ContextMenuItemTagGoForward:
1377 case ContextMenuItemTagStop:
1378 case ContextMenuItemTagReload:
1379 case ContextMenuItemTagFontMenu:
1381 case ContextMenuItemTagNoAction:
1382 case ContextMenuItemTagOpenLinkInNewWindow:
1383 case ContextMenuItemTagDownloadLinkToDisk:
1384 case ContextMenuItemTagCopyLinkToClipboard:
1385 case ContextMenuItemTagOpenImageInNewWindow:
1386 case ContextMenuItemTagDownloadImageToDisk:
1387 case ContextMenuItemTagCopyImageToClipboard:
1388 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
1389 case ContextMenuItemTagCopyImageUrlToClipboard:
1392 case ContextMenuItemTagOpenMediaInNewWindow:
1393 if (m_hitTestResult.mediaIsVideo())
1394 item.setTitle(contextMenuItemTagOpenVideoInNewWindow());
1396 item.setTitle(contextMenuItemTagOpenAudioInNewWindow());
1398 case ContextMenuItemTagCopyMediaLinkToClipboard:
1399 if (m_hitTestResult.mediaIsVideo())
1400 item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard());
1402 item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard());
1404 case ContextMenuItemTagToggleMediaControls:
1405 shouldCheck = m_hitTestResult.mediaControlsEnabled();
1407 case ContextMenuItemTagToggleMediaLoop:
1408 shouldCheck = m_hitTestResult.mediaLoopEnabled();
1410 case ContextMenuItemTagEnterVideoFullscreen:
1411 shouldEnable = m_hitTestResult.mediaSupportsFullscreen();
1413 case ContextMenuItemTagOpenFrameInNewWindow:
1414 case ContextMenuItemTagSpellingGuess:
1415 case ContextMenuItemTagOther:
1416 case ContextMenuItemTagSearchInSpotlight:
1417 case ContextMenuItemTagSearchWeb:
1418 case ContextMenuItemTagOpenWithDefaultApplication:
1419 case ContextMenuItemPDFActualSize:
1420 case ContextMenuItemPDFZoomIn:
1421 case ContextMenuItemPDFZoomOut:
1422 case ContextMenuItemPDFAutoSize:
1423 case ContextMenuItemPDFSinglePage:
1424 case ContextMenuItemPDFFacingPages:
1425 case ContextMenuItemPDFContinuous:
1426 case ContextMenuItemPDFNextPage:
1427 case ContextMenuItemPDFPreviousPage:
1428 case ContextMenuItemTagOpenLink:
1429 case ContextMenuItemTagIgnoreGrammar:
1430 case ContextMenuItemTagSpellingMenu:
1431 case ContextMenuItemTagShowFonts:
1432 case ContextMenuItemTagStyles:
1433 case ContextMenuItemTagShowColors:
1434 case ContextMenuItemTagSpeechMenu:
1435 case ContextMenuItemTagStartSpeaking:
1436 case ContextMenuItemTagWritingDirectionMenu:
1437 case ContextMenuItemTagTextDirectionMenu:
1438 case ContextMenuItemTagPDFSinglePageScrolling:
1439 case ContextMenuItemTagPDFFacingPagesScrolling:
1440 #if ENABLE(INSPECTOR)
1441 case ContextMenuItemTagInspectElement:
1443 case ContextMenuItemBaseCustomTag:
1444 case ContextMenuItemCustomTagNoAction:
1445 case ContextMenuItemLastCustomTag:
1446 case ContextMenuItemBaseApplicationTag:
1448 case ContextMenuItemTagMediaPlayPause:
1449 if (m_hitTestResult.mediaPlaying())
1450 item.setTitle(contextMenuItemTagMediaPause());
1452 item.setTitle(contextMenuItemTagMediaPlay());
1454 case ContextMenuItemTagMediaMute:
1455 shouldEnable = m_hitTestResult.mediaHasAudio();
1456 shouldCheck = shouldEnable && m_hitTestResult.mediaMuted();
1460 item.setChecked(shouldCheck);
1461 item.setEnabled(shouldEnable);
1464 #if USE(ACCESSIBILITY_CONTEXT_MENUS)
1465 void ContextMenuController::showContextMenuAt(Frame* frame, const IntPoint& clickPoint)
1467 // Simulate a click in the middle of the accessibility object.
1468 PlatformMouseEvent mouseEvent(clickPoint, clickPoint, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime());
1469 bool handled = frame->eventHandler()->sendContextMenuEvent(mouseEvent);
1470 if (handled && client())
1471 client()->showContextMenu();
1475 } // namespace WebCore
1477 #endif // ENABLE(CONTEXT_MENUS)