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();
317 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
318 if (frame->selection())
319 frame->editor()->command("Unselect").execute();
323 case ContextMenuItemTagGoBack:
324 if (Page* page = frame->page())
325 page->backForward()->goBackOrForward(-1);
327 case ContextMenuItemTagGoForward:
328 if (Page* page = frame->page())
329 page->backForward()->goBackOrForward(1);
331 case ContextMenuItemTagStop:
332 frame->loader()->stop();
334 case ContextMenuItemTagReload:
335 frame->loader()->reload();
337 case ContextMenuItemTagCut:
338 frame->editor()->command("Cut").execute();
340 case ContextMenuItemTagPaste:
341 frame->editor()->command("Paste").execute();
344 case ContextMenuItemTagDelete:
345 frame->editor()->performDelete();
347 case ContextMenuItemTagUnicodeInsertLRMMark:
348 insertUnicodeCharacter(leftToRightMark, frame);
350 case ContextMenuItemTagUnicodeInsertRLMMark:
351 insertUnicodeCharacter(rightToLeftMark, frame);
353 case ContextMenuItemTagUnicodeInsertLREMark:
354 insertUnicodeCharacter(leftToRightEmbed, frame);
356 case ContextMenuItemTagUnicodeInsertRLEMark:
357 insertUnicodeCharacter(rightToLeftEmbed, frame);
359 case ContextMenuItemTagUnicodeInsertLROMark:
360 insertUnicodeCharacter(leftToRightOverride, frame);
362 case ContextMenuItemTagUnicodeInsertRLOMark:
363 insertUnicodeCharacter(rightToLeftOverride, frame);
365 case ContextMenuItemTagUnicodeInsertPDFMark:
366 insertUnicodeCharacter(popDirectionalFormatting, frame);
368 case ContextMenuItemTagUnicodeInsertZWSMark:
369 insertUnicodeCharacter(zeroWidthSpace, frame);
371 case ContextMenuItemTagUnicodeInsertZWJMark:
372 insertUnicodeCharacter(zeroWidthJoiner, frame);
374 case ContextMenuItemTagUnicodeInsertZWNJMark:
375 insertUnicodeCharacter(zeroWidthNonJoiner, frame);
378 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
379 case ContextMenuItemTagSelectAll:
380 frame->editor()->command("SelectAll").execute();
383 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
384 case ContextMenuItemTagSelectWord:
385 frame->editor()->command("SelectWord").execute();
388 case ContextMenuItemTagSpellingGuess:
389 ASSERT(frame->editor()->selectedText().length());
390 if (frame->editor()->shouldInsertText(item->title(), frame->selection()->toNormalizedRange().get(), EditorInsertActionPasted)) {
391 Document* document = frame->document();
392 RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(document, createFragmentFromMarkup(document, item->title(), ""), ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting);
393 applyCommand(command);
394 frame->selection()->revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
397 case ContextMenuItemTagIgnoreSpelling:
398 frame->editor()->ignoreSpelling();
400 case ContextMenuItemTagLearnSpelling:
401 frame->editor()->learnSpelling();
403 case ContextMenuItemTagSearchWeb:
404 m_client->searchWithGoogle(frame);
406 case ContextMenuItemTagLookUpInDictionary:
407 // FIXME: Some day we may be able to do this from within WebCore.
408 m_client->lookUpInDictionary(frame);
410 case ContextMenuItemTagOpenLink:
411 if (Frame* targetFrame = m_hitTestResult.targetFrame())
412 targetFrame->loader()->loadFrameRequest(FrameLoadRequest(frame->document()->securityOrigin(), ResourceRequest(m_hitTestResult.absoluteLinkURL(), frame->loader()->outgoingReferrer())), false, false, 0, 0, MaybeSendReferrer);
414 openNewWindow(m_hitTestResult.absoluteLinkURL(), frame);
416 case ContextMenuItemTagBold:
417 frame->editor()->command("ToggleBold").execute();
419 case ContextMenuItemTagItalic:
420 frame->editor()->command("ToggleItalic").execute();
422 case ContextMenuItemTagUnderline:
423 frame->editor()->toggleUnderline();
425 case ContextMenuItemTagOutline:
426 // We actually never enable this because CSS does not have a way to specify an outline font,
427 // which may make this difficult to implement. Maybe a special case of text-shadow?
429 case ContextMenuItemTagStartSpeaking: {
431 RefPtr<Range> selectedRange = frame->selection()->toNormalizedRange();
432 if (!selectedRange || selectedRange->collapsed(ec)) {
433 Document* document = m_hitTestResult.innerNonSharedNode()->document();
434 selectedRange = document->createRange();
435 selectedRange->selectNode(document->documentElement(), ec);
437 m_client->speak(plainText(selectedRange.get()));
440 case ContextMenuItemTagStopSpeaking:
441 m_client->stopSpeaking();
443 case ContextMenuItemTagDefaultDirection:
444 frame->editor()->setBaseWritingDirection(NaturalWritingDirection);
446 case ContextMenuItemTagLeftToRight:
447 frame->editor()->setBaseWritingDirection(LeftToRightWritingDirection);
449 case ContextMenuItemTagRightToLeft:
450 frame->editor()->setBaseWritingDirection(RightToLeftWritingDirection);
452 case ContextMenuItemTagTextDirectionDefault:
453 frame->editor()->command("MakeTextWritingDirectionNatural").execute();
455 case ContextMenuItemTagTextDirectionLeftToRight:
456 frame->editor()->command("MakeTextWritingDirectionLeftToRight").execute();
458 case ContextMenuItemTagTextDirectionRightToLeft:
459 frame->editor()->command("MakeTextWritingDirectionRightToLeft").execute();
462 case ContextMenuItemTagSearchInSpotlight:
463 m_client->searchWithSpotlight();
466 case ContextMenuItemTagShowSpellingPanel:
467 frame->editor()->showSpellingGuessPanel();
469 case ContextMenuItemTagCheckSpelling:
470 frame->editor()->advanceToNextMisspelling();
472 case ContextMenuItemTagCheckSpellingWhileTyping:
473 frame->editor()->toggleContinuousSpellChecking();
475 case ContextMenuItemTagCheckGrammarWithSpelling:
476 frame->editor()->toggleGrammarChecking();
479 case ContextMenuItemTagShowFonts:
480 frame->editor()->showFontPanel();
482 case ContextMenuItemTagStyles:
483 frame->editor()->showStylesPanel();
485 case ContextMenuItemTagShowColors:
486 frame->editor()->showColorPanel();
489 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
490 case ContextMenuItemTagMakeUpperCase:
491 frame->editor()->uppercaseWord();
493 case ContextMenuItemTagMakeLowerCase:
494 frame->editor()->lowercaseWord();
496 case ContextMenuItemTagCapitalize:
497 frame->editor()->capitalizeWord();
499 case ContextMenuItemTagShowSubstitutions:
500 frame->editor()->showSubstitutionsPanel();
502 case ContextMenuItemTagSmartCopyPaste:
503 frame->editor()->toggleSmartInsertDelete();
505 case ContextMenuItemTagSmartQuotes:
506 frame->editor()->toggleAutomaticQuoteSubstitution();
508 case ContextMenuItemTagSmartDashes:
509 frame->editor()->toggleAutomaticDashSubstitution();
511 case ContextMenuItemTagSmartLinks:
512 frame->editor()->toggleAutomaticLinkDetection();
514 case ContextMenuItemTagTextReplacement:
515 frame->editor()->toggleAutomaticTextReplacement();
517 case ContextMenuItemTagCorrectSpellingAutomatically:
518 frame->editor()->toggleAutomaticSpellingCorrection();
520 case ContextMenuItemTagChangeBack:
521 frame->editor()->changeBackToReplacedString(m_hitTestResult.replacedString());
524 #if ENABLE(INSPECTOR)
525 case ContextMenuItemTagInspectElement:
526 if (Page* page = frame->page())
527 page->inspectorController()->inspect(m_hitTestResult.innerNonSharedNode());
535 void ContextMenuController::appendItem(ContextMenuItem& menuItem, ContextMenu* parentMenu)
537 checkOrEnableIfNeeded(menuItem);
539 parentMenu->appendItem(menuItem);
542 void ContextMenuController::createAndAppendFontSubMenu(ContextMenuItem& fontMenuItem)
544 ContextMenu fontMenu;
547 ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts());
549 ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold());
550 ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic());
551 ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline());
552 ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline());
554 ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles());
555 ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors());
559 appendItem(showFonts, &fontMenu);
561 appendItem(bold, &fontMenu);
562 appendItem(italic, &fontMenu);
563 appendItem(underline, &fontMenu);
564 appendItem(outline, &fontMenu);
566 appendItem(styles, &fontMenu);
567 appendItem(*separatorItem(), &fontMenu);
568 appendItem(showColors, &fontMenu);
571 fontMenuItem.setSubMenu(&fontMenu);
577 void ContextMenuController::createAndAppendSpellingAndGrammarSubMenu(ContextMenuItem& spellingAndGrammarMenuItem)
579 ContextMenu spellingAndGrammarMenu;
581 ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
582 contextMenuItemTagShowSpellingPanel(true));
583 ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
584 contextMenuItemTagCheckSpelling());
585 ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
586 contextMenuItemTagCheckSpellingWhileTyping());
587 ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling,
588 contextMenuItemTagCheckGrammarWithSpelling());
589 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
590 ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically,
591 contextMenuItemTagCorrectSpellingAutomatically());
594 appendItem(showSpellingPanel, &spellingAndGrammarMenu);
595 appendItem(checkSpelling, &spellingAndGrammarMenu);
596 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
597 appendItem(*separatorItem(), &spellingAndGrammarMenu);
599 appendItem(checkAsYouType, &spellingAndGrammarMenu);
600 appendItem(grammarWithSpelling, &spellingAndGrammarMenu);
601 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
602 appendItem(correctSpelling, &spellingAndGrammarMenu);
605 spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
608 #endif // !PLATFORM(GTK)
613 void ContextMenuController::createAndAppendSpeechSubMenu(ContextMenuItem& speechMenuItem)
615 ContextMenu speechMenu;
617 ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking());
618 ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking());
620 appendItem(start, &speechMenu);
621 appendItem(stop, &speechMenu);
623 speechMenuItem.setSubMenu(&speechMenu);
630 void ContextMenuController::createAndAppendUnicodeSubMenu(ContextMenuItem& unicodeMenuItem)
632 ContextMenu unicodeMenu;
634 ContextMenuItem leftToRightMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLRMMark, contextMenuItemTagUnicodeInsertLRMMark());
635 ContextMenuItem rightToLeftMarkMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLMMark, contextMenuItemTagUnicodeInsertRLMMark());
636 ContextMenuItem leftToRightEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLREMark, contextMenuItemTagUnicodeInsertLREMark());
637 ContextMenuItem rightToLeftEmbedMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLEMark, contextMenuItemTagUnicodeInsertRLEMark());
638 ContextMenuItem leftToRightOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertLROMark, contextMenuItemTagUnicodeInsertLROMark());
639 ContextMenuItem rightToLeftOverrideMenuItem(ActionType, ContextMenuItemTagUnicodeInsertRLOMark, contextMenuItemTagUnicodeInsertRLOMark());
640 ContextMenuItem popDirectionalFormattingMenuItem(ActionType, ContextMenuItemTagUnicodeInsertPDFMark, contextMenuItemTagUnicodeInsertPDFMark());
641 ContextMenuItem zeroWidthSpaceMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWSMark, contextMenuItemTagUnicodeInsertZWSMark());
642 ContextMenuItem zeroWidthJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWJMark, contextMenuItemTagUnicodeInsertZWJMark());
643 ContextMenuItem zeroWidthNonJoinerMenuItem(ActionType, ContextMenuItemTagUnicodeInsertZWNJMark, contextMenuItemTagUnicodeInsertZWNJMark());
645 appendItem(leftToRightMarkMenuItem, &unicodeMenu);
646 appendItem(rightToLeftMarkMenuItem, &unicodeMenu);
647 appendItem(leftToRightEmbedMenuItem, &unicodeMenu);
648 appendItem(rightToLeftEmbedMenuItem, &unicodeMenu);
649 appendItem(leftToRightOverrideMenuItem, &unicodeMenu);
650 appendItem(rightToLeftOverrideMenuItem, &unicodeMenu);
651 appendItem(popDirectionalFormattingMenuItem, &unicodeMenu);
652 appendItem(zeroWidthSpaceMenuItem, &unicodeMenu);
653 appendItem(zeroWidthJoinerMenuItem, &unicodeMenu);
654 appendItem(zeroWidthNonJoinerMenuItem, &unicodeMenu);
656 unicodeMenuItem.setSubMenu(&unicodeMenu);
661 void ContextMenuController::createAndAppendWritingDirectionSubMenu(ContextMenuItem& writingDirectionMenuItem)
663 ContextMenu writingDirectionMenu;
665 ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection,
666 contextMenuItemTagDefaultDirection());
667 ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight());
668 ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft());
670 appendItem(defaultItem, &writingDirectionMenu);
671 appendItem(ltr, &writingDirectionMenu);
672 appendItem(rtl, &writingDirectionMenu);
674 writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
677 void ContextMenuController::createAndAppendTextDirectionSubMenu(ContextMenuItem& textDirectionMenuItem)
679 ContextMenu textDirectionMenu;
681 ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
682 ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
683 ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
685 appendItem(defaultItem, &textDirectionMenu);
686 appendItem(ltr, &textDirectionMenu);
687 appendItem(rtl, &textDirectionMenu);
689 textDirectionMenuItem.setSubMenu(&textDirectionMenu);
694 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
696 void ContextMenuController::createAndAppendSubstitutionsSubMenu(ContextMenuItem& substitutionsMenuItem)
698 ContextMenu substitutionsMenu;
700 ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
701 ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
702 ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
703 ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
704 ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
705 ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
707 appendItem(showSubstitutions, &substitutionsMenu);
708 appendItem(*separatorItem(), &substitutionsMenu);
709 appendItem(smartCopyPaste, &substitutionsMenu);
710 appendItem(smartQuotes, &substitutionsMenu);
711 appendItem(smartDashes, &substitutionsMenu);
712 appendItem(smartLinks, &substitutionsMenu);
713 appendItem(textReplacement, &substitutionsMenu);
715 substitutionsMenuItem.setSubMenu(&substitutionsMenu);
718 void ContextMenuController::createAndAppendTransformationsSubMenu(ContextMenuItem& transformationsMenuItem)
720 ContextMenu transformationsMenu;
722 ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
723 ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
724 ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
726 appendItem(makeUpperCase, &transformationsMenu);
727 appendItem(makeLowerCase, &transformationsMenu);
728 appendItem(capitalize, &transformationsMenu);
730 transformationsMenuItem.setSubMenu(&transformationsMenu);
735 static bool selectionContainsPossibleWord(Frame* frame)
737 // Current algorithm: look for a character that's not just a separator.
738 for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) {
739 int length = it.length();
740 const UChar* characters = it.characters();
741 for (int i = 0; i < length; ++i)
742 if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph)))
749 #if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
750 #define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 1
752 #define INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM 0
756 void ContextMenuController::populate()
758 ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink());
759 ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow,
760 contextMenuItemTagOpenLinkInNewWindow());
761 ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk,
762 contextMenuItemTagDownloadLinkToDisk());
763 ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard,
764 contextMenuItemTagCopyLinkToClipboard());
765 ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow,
766 contextMenuItemTagOpenImageInNewWindow());
767 ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk,
768 contextMenuItemTagDownloadImageToDisk());
769 ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard,
770 contextMenuItemTagCopyImageToClipboard());
771 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
772 ContextMenuItem CopyImageUrlItem(ActionType, ContextMenuItemTagCopyImageUrlToClipboard,
773 contextMenuItemTagCopyImageUrlToClipboard());
775 ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String());
776 ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard,
778 ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause,
779 contextMenuItemTagMediaPlay());
780 ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute,
781 contextMenuItemTagMediaMute());
782 ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls,
783 contextMenuItemTagToggleMediaControls());
784 ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop,
785 contextMenuItemTagToggleMediaLoop());
786 ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen,
787 contextMenuItemTagEnterVideoFullscreen());
789 ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight,
790 contextMenuItemTagSearchInSpotlight());
793 ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb());
795 ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy());
796 ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack());
797 ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward());
798 ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop());
799 ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload());
800 ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow,
801 contextMenuItemTagOpenFrameInNewWindow());
802 ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound,
803 contextMenuItemTagNoGuessesFound());
804 ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling,
805 contextMenuItemTagIgnoreSpelling());
806 ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling,
807 contextMenuItemTagLearnSpelling());
808 ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar,
809 contextMenuItemTagIgnoreGrammar());
810 ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut());
811 ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste());
813 ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete());
815 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
816 ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
818 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
819 ContextMenuItem SelectWordItem(ActionType, ContextMenuItemTagSelectWord, contextMenuItemTagSelectWord());
822 Node* node = m_hitTestResult.innerNonSharedNode();
826 if (!m_hitTestResult.isContentEditable() && (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()))
829 Frame* frame = node->document()->frame();
833 if (!m_hitTestResult.isContentEditable()) {
834 FrameLoader* loader = frame->loader();
835 KURL linkURL = m_hitTestResult.absoluteLinkURL();
836 if (!linkURL.isEmpty()) {
837 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
838 if (m_hitTestResult.isSelected()) {
839 if (selectionContainsPossibleWord(frame)) {
840 appendItem(SearchWebItem, m_contextMenu.get());
842 appendItem(CopyItem, m_contextMenu.get());
846 #if ENABLE(TIZEN_DOWNLOAD_LINK_FILTER)
847 if (loader->client()->canHandleRequest(ResourceRequest(linkURL)) &&
848 (linkURL.protocolIs("http") || linkURL.protocolIs("https") || linkURL.protocolIs("ftp") || linkURL.protocolIs("ftps"))) {
850 if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) {
852 appendItem(OpenLinkItem, m_contextMenu.get());
853 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
854 appendItem(DownloadFileItem, m_contextMenu.get());
857 if (m_hitTestResult.isSelected())
858 appendItem(CopyItem, m_contextMenu.get());
860 appendItem(CopyLinkItem, m_contextMenu.get());
863 KURL imageURL = m_hitTestResult.absoluteImageURL();
864 if (!imageURL.isEmpty()) {
865 if (!linkURL.isEmpty())
866 appendItem(*separatorItem(), m_contextMenu.get());
868 appendItem(OpenImageInNewWindowItem, m_contextMenu.get());
869 appendItem(DownloadImageItem, m_contextMenu.get());
870 if (imageURL.isLocalFile() || m_hitTestResult.image())
871 appendItem(CopyImageItem, m_contextMenu.get());
872 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
873 appendItem(CopyImageUrlItem, m_contextMenu.get());
877 KURL mediaURL = m_hitTestResult.absoluteMediaURL();
878 if (!mediaURL.isEmpty()) {
879 if (!linkURL.isEmpty() || !imageURL.isEmpty())
880 appendItem(*separatorItem(), m_contextMenu.get());
882 appendItem(MediaPlayPause, m_contextMenu.get());
883 appendItem(MediaMute, m_contextMenu.get());
884 appendItem(ToggleMediaControls, m_contextMenu.get());
885 appendItem(ToggleMediaLoop, m_contextMenu.get());
886 appendItem(EnterVideoFullscreen, m_contextMenu.get());
888 appendItem(*separatorItem(), m_contextMenu.get());
889 appendItem(CopyMediaLinkItem, m_contextMenu.get());
890 appendItem(OpenMediaInNewWindowItem, m_contextMenu.get());
893 if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
894 if (m_hitTestResult.isSelected()) {
895 if (selectionContainsPossibleWord(frame)) {
897 String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
898 ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
900 #if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
901 appendItem(SearchSpotlightItem, m_contextMenu.get());
903 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
908 appendItem(SearchWebItem, m_contextMenu.get());
909 appendItem(*separatorItem(), m_contextMenu.get());
912 #if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
913 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
914 appendItem(*separatorItem(), m_contextMenu.get());
918 appendItem(CopyItem, m_contextMenu.get());
920 appendItem(*separatorItem(), m_contextMenu.get());
922 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
923 createAndAppendSpeechSubMenu(SpeechMenuItem);
924 appendItem(SpeechMenuItem, m_contextMenu.get());
927 #if ENABLE(INSPECTOR)
928 if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) {
931 // In GTK+ unavailable items are not hidden but insensitive
933 appendItem(BackItem, m_contextMenu.get());
934 appendItem(ForwardItem, m_contextMenu.get());
935 appendItem(StopItem, m_contextMenu.get());
936 appendItem(ReloadItem, m_contextMenu.get());
938 if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1))
939 appendItem(BackItem, m_contextMenu.get());
941 if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1))
942 appendItem(ForwardItem, m_contextMenu.get());
944 // use isLoadingInAPISense rather than isLoading because Stop/Reload are
945 // intended to match WebKit's API, not WebCore's internal notion of loading status
946 if (loader->documentLoader()->isLoadingInAPISense())
947 appendItem(StopItem, m_contextMenu.get());
949 appendItem(ReloadItem, m_contextMenu.get());
951 #if ENABLE(INSPECTOR)
955 if (frame->page() && frame != frame->page()->mainFrame())
956 appendItem(OpenFrameItem, m_contextMenu.get());
959 } else { // Make an editing context menu
960 FrameSelection* selection = frame->selection();
961 bool inPasswordField = selection->isInPasswordField();
962 bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
964 if (!inPasswordField && spellCheckingEnabled) {
965 // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
966 // is never considered a misspelling and bad grammar at the same time)
969 Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
970 if (misspelling || badGrammar) {
971 size_t size = guesses.size();
973 // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
974 // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
976 appendItem(NoGuessesItem, m_contextMenu.get());
977 appendItem(*separatorItem(), m_contextMenu.get());
980 for (unsigned i = 0; i < size; i++) {
981 const String &guess = guesses[i];
982 if (!guess.isEmpty()) {
983 ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
984 appendItem(item, m_contextMenu.get());
987 appendItem(*separatorItem(), m_contextMenu.get());
991 appendItem(IgnoreSpellingItem, m_contextMenu.get());
992 appendItem(LearnSpellingItem, m_contextMenu.get());
994 appendItem(IgnoreGrammarItem, m_contextMenu.get());
995 appendItem(*separatorItem(), m_contextMenu.get());
996 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
998 // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
999 String replacedString = m_hitTestResult.replacedString();
1000 if (!replacedString.isEmpty()) {
1001 ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
1002 appendItem(item, m_contextMenu.get());
1003 appendItem(*separatorItem(), m_contextMenu.get());
1009 FrameLoader* loader = frame->loader();
1010 KURL linkURL = m_hitTestResult.absoluteLinkURL();
1011 if (!linkURL.isEmpty()) {
1012 if (loader->client()->canHandleRequest(ResourceRequest(linkURL))) {
1013 appendItem(OpenLinkItem, m_contextMenu.get());
1014 appendItem(OpenLinkInNewWindowItem, m_contextMenu.get());
1015 appendItem(DownloadFileItem, m_contextMenu.get());
1017 appendItem(CopyLinkItem, m_contextMenu.get());
1018 appendItem(*separatorItem(), m_contextMenu.get());
1021 if (m_hitTestResult.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) {
1023 String selectedString = frame->displayStringModifiedByEncoding(frame->editor()->selectedText());
1024 ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
1026 #if INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
1027 appendItem(SearchSpotlightItem, m_contextMenu.get());
1029 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
1034 appendItem(SearchWebItem, m_contextMenu.get());
1035 appendItem(*separatorItem(), m_contextMenu.get());
1038 #if PLATFORM(MAC) && INCLUDE_SPOTLIGHT_CONTEXT_MENU_ITEM
1039 appendItem(LookUpInDictionaryItem, m_contextMenu.get());
1040 appendItem(*separatorItem(), m_contextMenu.get());
1044 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1045 if (m_hitTestResult.isSelected()) {
1046 appendItem(CutItem, m_contextMenu.get());
1047 appendItem(CopyItem, m_contextMenu.get());
1050 appendItem(CutItem, m_contextMenu.get());
1051 appendItem(CopyItem, m_contextMenu.get());
1053 appendItem(PasteItem, m_contextMenu.get());
1055 appendItem(DeleteItem, m_contextMenu.get());
1056 appendItem(*separatorItem(), m_contextMenu.get());
1058 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1059 if (frame->selection()) {
1060 Node* baseNode = frame->selection()->base().containerNode();
1061 if (baseNode && baseNode->isTextNode()) {
1062 if (!(baseNode->textContent().isEmpty())) {
1064 #if PLATFORM(GTK) || PLATFORM(QT) || PLATFORM(EFL)
1065 appendItem(SelectAllItem, m_contextMenu.get());
1067 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
1068 appendItem(SelectWordItem, m_contextMenu.get());
1070 #if ENABLE(TIZEN_CONTEXT_MENU_WEBKIT_2)
1076 if (!inPasswordField) {
1078 #if !ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1079 appendItem(*separatorItem(), m_contextMenu.get());
1080 ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
1081 contextMenuItemTagSpellingMenu());
1082 createAndAppendSpellingAndGrammarSubMenu(SpellingAndGrammarMenuItem);
1083 appendItem(SpellingAndGrammarMenuItem, m_contextMenu.get());
1084 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1086 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
1087 ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu,
1088 contextMenuItemTagSubstitutionsMenu());
1089 createAndAppendSubstitutionsSubMenu(substitutionsMenuItem);
1090 appendItem(substitutionsMenuItem, m_contextMenu.get());
1091 ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu,
1092 contextMenuItemTagTransformationsMenu());
1093 createAndAppendTransformationsSubMenu(transformationsMenuItem);
1094 appendItem(transformationsMenuItem, m_contextMenu.get());
1097 bool shouldShowFontMenu = frame->editor()->canEditRichly();
1099 #if ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1100 bool shouldShowFontMenu = false;
1102 bool shouldShowFontMenu = true;
1103 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1105 if (shouldShowFontMenu) {
1106 ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu,
1107 contextMenuItemTagFontMenu());
1108 createAndAppendFontSubMenu(FontMenuItem);
1109 appendItem(FontMenuItem, m_contextMenu.get());
1112 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
1113 createAndAppendSpeechSubMenu(SpeechMenuItem);
1114 appendItem(SpeechMenuItem, m_contextMenu.get());
1117 EditorClient* client = frame->editor()->client();
1118 if (client && client->shouldShowUnicodeMenu()) {
1119 ContextMenuItem UnicodeMenuItem(SubmenuType, ContextMenuItemTagUnicode, contextMenuItemTagUnicode());
1120 createAndAppendUnicodeSubMenu(UnicodeMenuItem);
1121 appendItem(*separatorItem(), m_contextMenu.get());
1122 appendItem(UnicodeMenuItem, m_contextMenu.get());
1125 ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu,
1126 contextMenuItemTagWritingDirectionMenu());
1127 #if !ENABLE(TIZEN_CONTEXT_MENU_TEMPORARY_FIX)
1128 createAndAppendWritingDirectionSubMenu(WritingDirectionMenuItem);
1129 appendItem(WritingDirectionMenuItem, m_contextMenu.get());
1130 if (Page* page = frame->page()) {
1131 if (Settings* settings = page->settings()) {
1132 bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
1133 || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection());
1134 if (includeTextDirectionSubmenu) {
1135 ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu,
1136 contextMenuItemTagTextDirectionMenu());
1137 createAndAppendTextDirectionSubMenu(TextDirectionMenuItem);
1138 appendItem(TextDirectionMenuItem, m_contextMenu.get());
1142 #endif //TIZEN_CONTEXT_MENU_TEMPORARY_FIX
1148 #if ENABLE(INSPECTOR)
1149 void ContextMenuController::addInspectElementItem()
1151 Node* node = m_hitTestResult.innerNonSharedNode();
1155 Frame* frame = node->document()->frame();
1159 Page* page = frame->page();
1163 if (!page->inspectorController())
1166 ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement());
1167 #if USE(CROSS_PLATFORM_CONTEXT_MENUS)
1168 if (!m_contextMenu->items().isEmpty())
1170 if (m_contextMenu->itemCount())
1172 appendItem(*separatorItem(), m_contextMenu.get());
1173 appendItem(InspectElementItem, m_contextMenu.get());
1175 #endif // ENABLE(INSPECTOR)
1177 void ContextMenuController::checkOrEnableIfNeeded(ContextMenuItem& item) const
1179 if (item.type() == SeparatorType)
1182 Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
1186 // Custom items already have proper checked and enabled values.
1187 if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
1190 bool shouldEnable = true;
1191 bool shouldCheck = false;
1193 switch (item.action()) {
1194 case ContextMenuItemTagCheckSpelling:
1195 shouldEnable = frame->editor()->canEdit();
1197 case ContextMenuItemTagDefaultDirection:
1198 shouldCheck = false;
1199 shouldEnable = false;
1201 case ContextMenuItemTagLeftToRight:
1202 case ContextMenuItemTagRightToLeft: {
1203 String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl";
1204 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyDirection, direction) != FalseTriState;
1205 shouldEnable = true;
1208 case ContextMenuItemTagTextDirectionDefault: {
1209 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural");
1210 shouldCheck = command.state() == TrueTriState;
1211 shouldEnable = command.isEnabled();
1214 case ContextMenuItemTagTextDirectionLeftToRight: {
1215 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight");
1216 shouldCheck = command.state() == TrueTriState;
1217 shouldEnable = command.isEnabled();
1220 case ContextMenuItemTagTextDirectionRightToLeft: {
1221 Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft");
1222 shouldCheck = command.state() == TrueTriState;
1223 shouldEnable = command.isEnabled();
1226 case ContextMenuItemTagCopy:
1227 shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy();
1229 case ContextMenuItemTagCut:
1230 shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut();
1232 case ContextMenuItemTagIgnoreSpelling:
1233 case ContextMenuItemTagLearnSpelling:
1234 shouldEnable = frame->selection()->isRange();
1236 case ContextMenuItemTagPaste:
1237 shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste();
1239 #if ENABLE(TIZEN_CONTEXT_MENU_SELECT)
1240 case ContextMenuItemTagSelectWord:
1241 shouldEnable = frame->editor()->canSelectRange();
1245 case ContextMenuItemTagDelete:
1246 shouldEnable = frame->editor()->canDelete();
1248 case ContextMenuItemTagInputMethods:
1249 case ContextMenuItemTagUnicode:
1250 case ContextMenuItemTagUnicodeInsertLRMMark:
1251 case ContextMenuItemTagUnicodeInsertRLMMark:
1252 case ContextMenuItemTagUnicodeInsertLREMark:
1253 case ContextMenuItemTagUnicodeInsertRLEMark:
1254 case ContextMenuItemTagUnicodeInsertLROMark:
1255 case ContextMenuItemTagUnicodeInsertRLOMark:
1256 case ContextMenuItemTagUnicodeInsertPDFMark:
1257 case ContextMenuItemTagUnicodeInsertZWSMark:
1258 case ContextMenuItemTagUnicodeInsertZWJMark:
1259 case ContextMenuItemTagUnicodeInsertZWNJMark:
1260 shouldEnable = true;
1263 #if PLATFORM(GTK) || PLATFORM(EFL)
1264 case ContextMenuItemTagSelectAll:
1265 shouldEnable = true;
1268 case ContextMenuItemTagUnderline: {
1269 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyWebkitTextDecorationsInEffect, "underline") != FalseTriState;
1270 shouldEnable = frame->editor()->canEditRichly();
1273 case ContextMenuItemTagLookUpInDictionary:
1274 shouldEnable = frame->selection()->isRange();
1276 case ContextMenuItemTagCheckGrammarWithSpelling:
1277 if (frame->editor()->isGrammarCheckingEnabled())
1279 shouldEnable = true;
1281 case ContextMenuItemTagItalic: {
1282 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontStyle, "italic") != FalseTriState;
1283 shouldEnable = frame->editor()->canEditRichly();
1286 case ContextMenuItemTagBold: {
1287 shouldCheck = frame->editor()->selectionHasStyle(CSSPropertyFontWeight, "bold") != FalseTriState;
1288 shouldEnable = frame->editor()->canEditRichly();
1291 case ContextMenuItemTagOutline:
1292 shouldEnable = false;
1294 case ContextMenuItemTagShowSpellingPanel:
1295 if (frame->editor()->spellingPanelIsShowing())
1296 item.setTitle(contextMenuItemTagShowSpellingPanel(false));
1298 item.setTitle(contextMenuItemTagShowSpellingPanel(true));
1299 shouldEnable = frame->editor()->canEdit();
1301 case ContextMenuItemTagNoGuessesFound:
1302 shouldEnable = false;
1304 case ContextMenuItemTagCheckSpellingWhileTyping:
1305 shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled();
1308 case ContextMenuItemTagSubstitutionsMenu:
1309 case ContextMenuItemTagTransformationsMenu:
1311 case ContextMenuItemTagShowSubstitutions:
1312 #ifndef BUILDING_ON_LEOPARD
1313 if (frame->editor()->substitutionsPanelIsShowing())
1314 item.setTitle(contextMenuItemTagShowSubstitutions(false));
1316 item.setTitle(contextMenuItemTagShowSubstitutions(true));
1317 shouldEnable = frame->editor()->canEdit();
1320 case ContextMenuItemTagMakeUpperCase:
1321 case ContextMenuItemTagMakeLowerCase:
1322 case ContextMenuItemTagCapitalize:
1323 case ContextMenuItemTagChangeBack:
1324 shouldEnable = frame->editor()->canEdit();
1326 case ContextMenuItemTagCorrectSpellingAutomatically:
1327 #ifndef BUILDING_ON_LEOPARD
1328 shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled();
1331 case ContextMenuItemTagSmartCopyPaste:
1332 #ifndef BUILDING_ON_LEOPARD
1333 shouldCheck = frame->editor()->smartInsertDeleteEnabled();
1336 case ContextMenuItemTagSmartQuotes:
1337 #ifndef BUILDING_ON_LEOPARD
1338 shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled();
1341 case ContextMenuItemTagSmartDashes:
1342 #ifndef BUILDING_ON_LEOPARD
1343 shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled();
1346 case ContextMenuItemTagSmartLinks:
1347 #ifndef BUILDING_ON_LEOPARD
1348 shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled();
1351 case ContextMenuItemTagTextReplacement:
1352 #ifndef BUILDING_ON_LEOPARD
1353 shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled();
1356 case ContextMenuItemTagStopSpeaking:
1357 shouldEnable = client() && client()->isSpeaking();
1359 #else // PLATFORM(MAC) ends here
1360 case ContextMenuItemTagStopSpeaking:
1364 case ContextMenuItemTagGoBack:
1365 shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1);
1367 case ContextMenuItemTagGoForward:
1368 shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1);
1370 case ContextMenuItemTagStop:
1371 shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense();
1373 case ContextMenuItemTagReload:
1374 shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense();
1376 case ContextMenuItemTagFontMenu:
1377 shouldEnable = frame->editor()->canEditRichly();
1380 case ContextMenuItemTagGoBack:
1381 case ContextMenuItemTagGoForward:
1382 case ContextMenuItemTagStop:
1383 case ContextMenuItemTagReload:
1384 case ContextMenuItemTagFontMenu:
1386 case ContextMenuItemTagNoAction:
1387 case ContextMenuItemTagOpenLinkInNewWindow:
1388 case ContextMenuItemTagDownloadLinkToDisk:
1389 case ContextMenuItemTagCopyLinkToClipboard:
1390 case ContextMenuItemTagOpenImageInNewWindow:
1391 case ContextMenuItemTagDownloadImageToDisk:
1392 case ContextMenuItemTagCopyImageToClipboard:
1393 #if PLATFORM(QT) || PLATFORM(GTK) || PLATFORM(EFL)
1394 case ContextMenuItemTagCopyImageUrlToClipboard:
1397 case ContextMenuItemTagOpenMediaInNewWindow:
1398 if (m_hitTestResult.mediaIsVideo())
1399 item.setTitle(contextMenuItemTagOpenVideoInNewWindow());
1401 item.setTitle(contextMenuItemTagOpenAudioInNewWindow());
1403 case ContextMenuItemTagCopyMediaLinkToClipboard:
1404 if (m_hitTestResult.mediaIsVideo())
1405 item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard());
1407 item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard());
1409 case ContextMenuItemTagToggleMediaControls:
1410 shouldCheck = m_hitTestResult.mediaControlsEnabled();
1412 case ContextMenuItemTagToggleMediaLoop:
1413 shouldCheck = m_hitTestResult.mediaLoopEnabled();
1415 case ContextMenuItemTagEnterVideoFullscreen:
1416 shouldEnable = m_hitTestResult.mediaSupportsFullscreen();
1418 case ContextMenuItemTagOpenFrameInNewWindow:
1419 case ContextMenuItemTagSpellingGuess:
1420 case ContextMenuItemTagOther:
1421 case ContextMenuItemTagSearchInSpotlight:
1422 case ContextMenuItemTagSearchWeb:
1423 case ContextMenuItemTagOpenWithDefaultApplication:
1424 case ContextMenuItemPDFActualSize:
1425 case ContextMenuItemPDFZoomIn:
1426 case ContextMenuItemPDFZoomOut:
1427 case ContextMenuItemPDFAutoSize:
1428 case ContextMenuItemPDFSinglePage:
1429 case ContextMenuItemPDFFacingPages:
1430 case ContextMenuItemPDFContinuous:
1431 case ContextMenuItemPDFNextPage:
1432 case ContextMenuItemPDFPreviousPage:
1433 case ContextMenuItemTagOpenLink:
1434 case ContextMenuItemTagIgnoreGrammar:
1435 case ContextMenuItemTagSpellingMenu:
1436 case ContextMenuItemTagShowFonts:
1437 case ContextMenuItemTagStyles:
1438 case ContextMenuItemTagShowColors:
1439 case ContextMenuItemTagSpeechMenu:
1440 case ContextMenuItemTagStartSpeaking:
1441 case ContextMenuItemTagWritingDirectionMenu:
1442 case ContextMenuItemTagTextDirectionMenu:
1443 case ContextMenuItemTagPDFSinglePageScrolling:
1444 case ContextMenuItemTagPDFFacingPagesScrolling:
1445 #if ENABLE(INSPECTOR)
1446 case ContextMenuItemTagInspectElement:
1448 case ContextMenuItemBaseCustomTag:
1449 case ContextMenuItemCustomTagNoAction:
1450 case ContextMenuItemLastCustomTag:
1451 case ContextMenuItemBaseApplicationTag:
1453 case ContextMenuItemTagMediaPlayPause:
1454 if (m_hitTestResult.mediaPlaying())
1455 item.setTitle(contextMenuItemTagMediaPause());
1457 item.setTitle(contextMenuItemTagMediaPlay());
1459 case ContextMenuItemTagMediaMute:
1460 shouldEnable = m_hitTestResult.mediaHasAudio();
1461 shouldCheck = shouldEnable && m_hitTestResult.mediaMuted();
1465 item.setChecked(shouldCheck);
1466 item.setEnabled(shouldEnable);
1469 #if USE(ACCESSIBILITY_CONTEXT_MENUS)
1470 void ContextMenuController::showContextMenuAt(Frame* frame, const IntPoint& clickPoint)
1472 // Simulate a click in the middle of the accessibility object.
1473 PlatformMouseEvent mouseEvent(clickPoint, clickPoint, RightButton, PlatformEvent::MousePressed, 1, false, false, false, false, currentTime());
1474 bool handled = frame->eventHandler()->sendContextMenuEvent(mouseEvent);
1475 if (handled && client())
1476 client()->showContextMenu();
1480 } // namespace WebCore
1482 #endif // ENABLE(CONTEXT_MENUS)