Changeset 120357 in webkit


Ignore:
Timestamp:
Jun 14, 2012 1:22:56 PM (12 years ago)
Author:
jpu@apple.com
Message:

Mark text with text alternative with blue underline.
https://bugs.webkit.org/show_bug.cgi?id=83047

Reviewed by Enrica Casucci.

Tests: platform/mac/editing/input/edit-dictated-text-with-alternative.html

platform/mac/editing/input/insert-dictated-text.html

This patch implements visual indication on dictated text with alternatives, and provides UI
to show alternative text on OS X. Majority of the changes is for generalizing existing AlternativeTextController
class to handle dictation alternatives. The two new classes, AlternativeTextUIController and
TextAlternativeWithRange, are used by both WebKit and WK2. So WebCore seems to be the natural place
for them.

  • WebCore.exp.in:
  • WebCore.xcodeproj/project.pbxproj:
  • editing/AlternativeTextController.cpp: Expanded exising class interface to support dictation alternatives.

(DictationAlternativeDetails): Marker detail class for dictation alternative mark.
(WebCore::DictationAlternativeDetails::create):
(WebCore::DictationAlternativeDetails::dictationContext):
(WebCore::DictationAlternativeDetails::DictationAlternativeDetails):
(WebCore::markerTypesForAppliedDictationAlternative):
(WebCore::AlternativeTextController::applyAlternativeTextToRange): Generalized existing applyAlternativeTextToRange() to handle dictation alternatives.
(WebCore::AlternativeTextController::timerFired): Expanded existing code to handle dictation alternatives.
(WebCore::AlternativeTextController::handleAlternativeTextUIResult): Expanded existing code to handle dictation alternatives.
(WebCore::AlternativeTextController::respondToChangedSelection): Moved part of the function into respondToMarkerAtEndOfWord() to improve readability.
(WebCore::AlternativeTextController::shouldStartTimerFor):
(WebCore::AlternativeTextController::respondToMarkerAtEndOfWord):
(WebCore::AlternativeTextController::markerDescriptionForAppliedAlternativeText):
(WebCore::AlternativeTextController::removeDictationAlternativesForMarker):
(WebCore::AlternativeTextController::dictationAlternativesForMarker):
(WebCore::AlternativeTextController::applyDictationAlternative):

  • editing/AlternativeTextController.h:
  • editing/Editor.cpp:

(WebCore::Editor::notifyComponentsOnChangedSelection): Renamed existing respondToChangedSelection() function to avoid naming collision.
(WebCore::Editor::appliedEditing):
(WebCore::Editor::unappliedEditing):
(WebCore::Editor::reappliedEditing):
(WebCore::Editor::updateMarkersForWordsAffectedByEditing):
(WebCore::Editor::changeSelectionAfterCommand):
(WebCore::Editor::respondToChangedSelection):
(WebCore::Editor::dictationAlternativesForMarker):
(WebCore::Editor::applyDictationAlternativelternative):

  • editing/Editor.h:
  • editing/FrameSelection.h:
  • editing/mac/AlternativeTextUIController.h: Added. WK1 and WK2 use this class to keep track of text alternatives objects.

(AlternativeTextUIController):
(WebCore::AlternativeTextUIController::AlternativeTextUIController):
(AlernativeTextContextController):
(WebCore::AlternativeTextUIController::AlernativeTextContextController::AlernativeTextContextController):

  • editing/mac/AlternativeTextUIController.mm: Added.

(WebCore::AlternativeTextUIController::AlernativeTextContextController::addAlternatives):
(WebCore::AlternativeTextUIController::AlernativeTextContextController::alternativesForContext):
(WebCore::AlternativeTextUIController::AlernativeTextContextController::removeAlternativesForContext):
(WebCore::AlternativeTextUIController::AlernativeTextContextController::clear):
(WebCore::AlternativeTextUIController::addAlternatives):
(WebCore::AlternativeTextUIController::alternativesForContext):
(WebCore::AlternativeTextUIController::clear):
(WebCore::AlternativeTextUIController::showAlternatives):
(WebCore::AlternativeTextUIController::handleAcceptedAlternative):
(WebCore::AlternativeTextUIController::dismissAlternatives):
(WebCore::AlternativeTextUIController::removeAlternatives):

  • editing/mac/TextAlternativeWithRange.h: Added. A simple struct to make it easier to pass around a pair of text alternatives object and range.
  • editing/mac/TextAlternativeWithRange.mm: Added.

(WebCore::TextAlternativeWithRange::TextAlternativeWithRange):
(WebCore::collectDictationTextAlternatives):

  • page/AlternativeTextClient.h:
  • page/ContextMenuController.cpp: Added code to show alternative dictated text in context menu.

(WebCore::ContextMenuController::contextMenuItemSelected):
(WebCore::ContextMenuController::populate):
(WebCore::ContextMenuController::checkOrEnableIfNeeded):

  • platform/ContextMenuItem.h:
  • rendering/HitTestResult.cpp:

(WebCore::HitTestResult::dictationAlternatives):

  • rendering/HitTestResult.h:
  • rendering/InlineTextBox.cpp:

(WebCore::InlineTextBox::paintDocumentMarker):

Changes in WebKit include implementation of new functions declared in AlternativeTextClient,
and logic for calling Editor::insertDictatedText() instead of Editor::insertText() when there's
alternatives attached to the input string.

  • WebCoreSupport/CorrectionPanel.mm:

(correctionIndicatorType):
(CorrectionPanel::handleAcceptedReplacement):

  • WebCoreSupport/WebAlternativeTextClient.h:

(WebAlternativeTextClient):

  • WebCoreSupport/WebAlternativeTextClient.mm:

(WebAlternativeTextClient::showCorrectionAlternative):
(WebAlternativeTextClient::dismissAlternative):
(WebAlternativeTextClient::dismissAlternativeSoon):
(WebAlternativeTextClient::recordAutocorrectionResponse):
(WebAlternativeTextClient::removeDictationAlternatives):
(WebAlternativeTextClient::showDictationAlternativeUI):
(WebAlternativeTextClient::dismissDictationAlternativeUI):
(WebAlternativeTextClient::dictationAlternatives):

  • WebView/WebHTMLView.mm:

(-[WebHTMLView validAttributesForMarkedText]):
(-[WebHTMLView insertText:]):

  • WebView/WebView.mm:

(-[WebView handleAcceptedAlternativeText:]):
(-[WebView _getWebCoreDictationAlternatives:fromTextAlternatives:]):
(-[WebView _showDictationAlternativeUI:WebCore::forDictationContext:]):
(-[WebView _dismissDictationAlternativeUI]):
(-[WebView _removeDictationAlternatives:]):
(-[WebView _dictationAlternatives:]):

  • WebView/WebViewData.h:
  • WebView/WebViewData.mm:

(-[WebViewPrivate init]):

  • WebView/WebViewInternal.h:
  • WebView/WebViewPrivate.h:

Changes in WebKit2 include implementation of new functions declared in AlternativeTextClient,
and logic for calling Editor::insertDictatedText() instead of Editor::insertText() when there's
alternatives attached to the input string.

  • Shared/API/c/WKContextMenuItemTypes.h:
  • Shared/API/c/WKSharedAPICast.h:
  • Shared/WebCoreArgumentCoders.cpp:
  • Shared/WebCoreArgumentCoders.h:
  • UIProcess/API/mac/PageClientImpl.h:
  • UIProcess/API/mac/PageClientImpl.mm:

(WebKit::PageClientImpl::PageClientImpl):
(WebKit::PageClientImpl::pageClosed):
(WebKit::PageClientImpl::addDictationAlternatives):
(WebKit::PageClientImpl::removeDictationAlternatives):
(WebKit::PageClientImpl::showDictationAlternativeUI):
(WebKit::PageClientImpl::dictationAlternatives):
(WebKit::PageClientImpl::dismissDictationAlternativeUI):

  • UIProcess/API/mac/WKView.mm:

(-[WKView insertText:replacementRange:]):
(-[WKView validAttributesForMarkedText]):
(-[WKView handleAcceptedAlternativeText:]):

  • UIProcess/API/mac/WKViewInternal.h:
  • UIProcess/PageClient.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::showDictationAlternativeUI):
(WebKit::WebPageProxy::dismissDictationAlternativeUI):
(WebKit::WebPageProxy::removeDictationAlternatives):
(WebKit::WebPageProxy::dictationAlternatives):

  • UIProcess/WebPageProxy.h:
  • UIProcess/WebPageProxy.messages.in:
  • UIProcess/mac/CorrectionPanel.mm:

(correctionIndicatorType):
(WebKit::CorrectionPanel::handleAcceptedReplacement):

  • UIProcess/mac/WebPageProxyMac.mm:

(WebKit::WebPageProxy::insertDictatedText):

  • WebProcess/WebCoreSupport/WebAlternativeTextClient.h:

(WebAlternativeTextClient):

  • WebProcess/WebCoreSupport/mac/WebAlternativeTextClient.cpp:

(WebKit::WebAlternativeTextClient::showCorrectionAlternative):
(WebKit::WebAlternativeTextClient::dismissAlternative):
(WebKit::WebAlternativeTextClient::dismissAlternativeSoon):
(WebKit::WebAlternativeTextClient::recordAutocorrectionResponse):
(WebKit::WebAlternativeTextClient::removeDictationAlternatives):
(WebKit::WebAlternativeTextClient::showDictationAlternativeUI):
(WebKit::WebAlternativeTextClient::dismissDictationAlternativeUI):
(WebKit::WebAlternativeTextClient::dictationAlternatives):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:
  • WebProcess/WebPage/mac/WebPageMac.mm:

(WebKit::WebPage::insertDictatedText):

  • platform/mac-lion/Skipped:
  • platform/mac-snowleopard/Skipped:
  • platform/mac/editing/input/edit-dictated-text-with-alternative-expected.txt: Added.
  • platform/mac/editing/input/edit-dictated-text-with-alternative.html: Added.
  • platform/mac/editing/input/insert-dictated-text-expected.txt: Added.
  • platform/mac/editing/input/insert-dictated-text.html: Added.
  • DumpRenderTree/mac/TextInputController.m:

(+[TextInputController isSelectorExcludedFromWebScript:]):
(+[TextInputController webScriptNameForSelector:]):
(-[TextInputController dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:]):

Location:
trunk
Files:
8 added
49 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r120354 r120357  
     12012-06-14  Jia Pu  <jpu@apple.com>
     2
     3        Mark text with text alternative with blue underline.
     4        https://bugs.webkit.org/show_bug.cgi?id=83047
     5
     6        Reviewed by Enrica Casucci.
     7
     8        * platform/mac-lion/Skipped:
     9        * platform/mac-snowleopard/Skipped:
     10        * platform/mac/editing/input/edit-dictated-text-with-alternative-expected.txt: Added.
     11        * platform/mac/editing/input/edit-dictated-text-with-alternative.html: Added.
     12        * platform/mac/editing/input/insert-dictated-text-expected.txt: Added.
     13        * platform/mac/editing/input/insert-dictated-text.html: Added.
     14
    1152012-06-14  Emil A Eklund  <eae@chromium.org>
    216
  • trunk/LayoutTests/platform/mac-lion/Skipped

    r119659 r120357  
    3535# Pasting replaces the three periods with an ellipsis on Lion
    3636editing/pasteboard/5478250.html
     37
     38# Mountain Lion functionalities
     39platform/mac/editing/input/edit-dictated-text-with-alternative.html
     40platform/mac/editing/input/insert-dictated-text.html
    3741
    3842# --- Media ---
  • trunk/LayoutTests/platform/mac-snowleopard/Skipped

    r119659 r120357  
    212212# https://bugs.webkit.org/show_bug.cgi?id=40361
    213213editing/text-iterator/findString-selection-disabled.html
     214
     215# Dictated text input is not supported on this platform
     216platform/mac/editing/input/edit-dictated-text-with-alternative.html
     217platform/mac/editing/input/insert-dictated-text.html
  • trunk/Source/WebCore/ChangeLog

    r120354 r120357  
     12012-06-14  Jia Pu  <jpu@apple.com>
     2
     3        Mark text with text alternative with blue underline.
     4        https://bugs.webkit.org/show_bug.cgi?id=83047
     5
     6        Reviewed by Enrica Casucci.
     7
     8        Tests: platform/mac/editing/input/edit-dictated-text-with-alternative.html
     9               platform/mac/editing/input/insert-dictated-text.html
     10
     11        This patch implements visual indication on dictated text with alternatives, and provides UI
     12        to show alternative text on OS X. Majority of the changes is for generalizing existing AlternativeTextController
     13        class to handle dictation alternatives. The two new classes, AlternativeTextUIController and
     14        TextAlternativeWithRange, are used by both WebKit and WK2. So WebCore seems to be the natural place
     15        for them.
     16
     17        * WebCore.exp.in:
     18        * WebCore.xcodeproj/project.pbxproj:
     19        * editing/AlternativeTextController.cpp: Expanded exising class interface to support dictation alternatives.
     20        (DictationAlternativeDetails): Marker detail class for dictation alternative mark.
     21        (WebCore::DictationAlternativeDetails::create):
     22        (WebCore::DictationAlternativeDetails::dictationContext):
     23        (WebCore::DictationAlternativeDetails::DictationAlternativeDetails):
     24        (WebCore::markerTypesForAppliedDictationAlternative):
     25        (WebCore::AlternativeTextController::applyAlternativeTextToRange): Generalized existing applyAlternativeTextToRange() to handle dictation alternatives.
     26        (WebCore::AlternativeTextController::timerFired): Expanded existing code to handle dictation alternatives.
     27        (WebCore::AlternativeTextController::handleAlternativeTextUIResult): Expanded existing code to handle dictation alternatives.
     28        (WebCore::AlternativeTextController::respondToChangedSelection): Moved part of the function into respondToMarkerAtEndOfWord() to improve readability.
     29        (WebCore::AlternativeTextController::shouldStartTimerFor):
     30        (WebCore::AlternativeTextController::respondToMarkerAtEndOfWord):
     31        (WebCore::AlternativeTextController::markerDescriptionForAppliedAlternativeText):
     32        (WebCore::AlternativeTextController::removeDictationAlternativesForMarker):
     33        (WebCore::AlternativeTextController::dictationAlternativesForMarker):
     34        (WebCore::AlternativeTextController::applyDictationAlternative):
     35        * editing/AlternativeTextController.h:
     36        * editing/Editor.cpp:
     37        (WebCore::Editor::notifyComponentsOnChangedSelection): Renamed existing respondToChangedSelection() function to avoid naming collision.
     38        (WebCore::Editor::appliedEditing):
     39        (WebCore::Editor::unappliedEditing):
     40        (WebCore::Editor::reappliedEditing):
     41        (WebCore::Editor::updateMarkersForWordsAffectedByEditing):
     42        (WebCore::Editor::changeSelectionAfterCommand):
     43        (WebCore::Editor::respondToChangedSelection):
     44        (WebCore::Editor::dictationAlternativesForMarker):
     45        (WebCore::Editor::applyDictationAlternativelternative):
     46        * editing/Editor.h:
     47        * editing/FrameSelection.h:
     48        * editing/mac/AlternativeTextUIController.h: Added. WK1 and WK2 use this class to keep track of text alternatives objects.
     49        (AlternativeTextUIController):
     50        (WebCore::AlternativeTextUIController::AlternativeTextUIController):
     51        (AlernativeTextContextController):
     52        (WebCore::AlternativeTextUIController::AlernativeTextContextController::AlernativeTextContextController):
     53        * editing/mac/AlternativeTextUIController.mm: Added.
     54        (WebCore::AlternativeTextUIController::AlernativeTextContextController::addAlternatives):
     55        (WebCore::AlternativeTextUIController::AlernativeTextContextController::alternativesForContext):
     56        (WebCore::AlternativeTextUIController::AlernativeTextContextController::removeAlternativesForContext):
     57        (WebCore::AlternativeTextUIController::AlernativeTextContextController::clear):
     58        (WebCore::AlternativeTextUIController::addAlternatives):
     59        (WebCore::AlternativeTextUIController::alternativesForContext):
     60        (WebCore::AlternativeTextUIController::clear):
     61        (WebCore::AlternativeTextUIController::showAlternatives):
     62        (WebCore::AlternativeTextUIController::handleAcceptedAlternative):
     63        (WebCore::AlternativeTextUIController::dismissAlternatives):
     64        (WebCore::AlternativeTextUIController::removeAlternatives):
     65        * editing/mac/TextAlternativeWithRange.h: Added.  A simple struct to make it easier to pass around a pair of text alternatives object and range.
     66        * editing/mac/TextAlternativeWithRange.mm: Added.
     67        (WebCore::TextAlternativeWithRange::TextAlternativeWithRange):
     68        (WebCore::collectDictationTextAlternatives):
     69        * page/AlternativeTextClient.h:
     70        * page/ContextMenuController.cpp: Added code to show alternative dictated text in context menu.
     71        (WebCore::ContextMenuController::contextMenuItemSelected):
     72        (WebCore::ContextMenuController::populate):
     73        (WebCore::ContextMenuController::checkOrEnableIfNeeded):
     74        * platform/ContextMenuItem.h:
     75        * rendering/HitTestResult.cpp:
     76        (WebCore::HitTestResult::dictationAlternatives):
     77        * rendering/HitTestResult.h:
     78        * rendering/InlineTextBox.cpp:
     79        (WebCore::InlineTextBox::paintDocumentMarker):
     80
    1812012-06-14  Emil A Eklund  <eae@chromium.org>
    282
  • trunk/Source/WebCore/WebCore.exp.in

    r120147 r120357  
    25272527__ZNK7WebCore4KURL22protocolIsInHTTPFamilyEv
    25282528#endif
     2529
     2530#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
     2531__ZN7WebCore27AlternativeTextUIController15addAlternativesERKN3WTF9RetainPtrI18NSTextAlternativesEE
     2532__ZN7WebCore27AlternativeTextUIController22alternativesForContextEy
     2533__ZN7WebCore27AlternativeTextUIController5clearEv
     2534__ZN7WebCore27AlternativeTextUIController19dismissAlternativesEv
     2535__ZN7WebCore27AlternativeTextUIController18removeAlternativesEy
     2536__ZN7WebCore27AlternativeTextUIController16showAlternativesEP6NSViewRKNS_9FloatRectEyU13block_pointerFvP8NSStringE
     2537__ZN7WebCore24TextAlternativeWithRangeC1EP18NSTextAlternatives8_NSRange
     2538__ZN7WebCore32collectDictationTextAlternativesEP18NSAttributedStringRN3WTF6VectorINS_24TextAlternativeWithRangeELm0EEE
     2539#endif
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r120260 r120357  
    57925792                CE08C3D2152B599A0021B8C2 /* AlternativeTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE08C3D0152B599A0021B8C2 /* AlternativeTextController.h */; settings = {ATTRIBUTES = (); }; };
    57935793                CE54FD381016D9A6008B44C8 /* ScriptSourceProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = CE54FD371016D9A6008B44C8 /* ScriptSourceProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5794                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5795                CE7B2DB41586ABAD0098B3FA /* AlternativeTextUIController.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */; };
     5796                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5797                CE7B2DB61586ABAD0098B3FA /* TextAlternativeWithRange.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */; };
    57945798                CEA3949C11D45CDA003094CF /* StaticHashSetNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CEA3949A11D45CDA003094CF /* StaticHashSetNodeList.cpp */; };
    57955799                CEA3949D11D45CDA003094CF /* StaticHashSetNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = CEA3949B11D45CDA003094CF /* StaticHashSetNodeList.h */; };
     
    1298812992                CE54FD371016D9A6008B44C8 /* ScriptSourceProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptSourceProvider.h; sourceTree = "<group>"; };
    1298912993                CE5CB1B314EDAB6F00BB2795 /* EventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSender.h; sourceTree = "<group>"; };
     12994                CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AlternativeTextUIController.h; path = mac/AlternativeTextUIController.h; sourceTree = "<group>"; };
     12995                CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AlternativeTextUIController.mm; path = mac/AlternativeTextUIController.mm; sourceTree = "<group>"; };
     12996                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextAlternativeWithRange.h; path = mac/TextAlternativeWithRange.h; sourceTree = "<group>"; };
     12997                CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TextAlternativeWithRange.mm; path = mac/TextAlternativeWithRange.mm; sourceTree = "<group>"; };
    1299012998                CEA3949A11D45CDA003094CF /* StaticHashSetNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StaticHashSetNodeList.cpp; sourceTree = "<group>"; };
    1299112999                CEA3949B11D45CDA003094CF /* StaticHashSetNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticHashSetNodeList.h; sourceTree = "<group>"; };
     
    2069420702                        isa = PBXGroup;
    2069520703                        children = (
     20704                                CE7B2DB01586ABAD0098B3FA /* AlternativeTextUIController.mm */,
     20705                                CE7B2DAF1586ABAD0098B3FA /* AlternativeTextUIController.h */,
    2069620706                                ED501DC50B249F2900AE18D9 /* EditorMac.mm */,
    2069720707                                4A8C96EA0BE69032004EEFF0 /* FrameSelectionMac.mm */,
     20708                                CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */,
     20709                                CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */,
    2069820710                        );
    2069920711                        name = mac;
     
    2506225074                                977E2E0F12F0FC9C00C13379 /* XSSAuditor.h in Headers */,
    2506325075                                FD537353137B651800008DCE /* ZeroPole.h in Headers */,
     25076                                CE7B2DB31586ABAD0098B3FA /* AlternativeTextUIController.h in Headers */,
     25077                                CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */,
    2506425078                        );
    2506525079                        runOnlyForDeploymentPostprocessing = 0;
     
    2810328117                                FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
    2810428118                                9A1B6F97158869C80011A8C4 /* JSDOMStringListCustom.cpp in Sources */,
     28119                                CE7B2DB41586ABAD0098B3FA /* AlternativeTextUIController.mm in Sources */,
     28120                                CE7B2DB61586ABAD0098B3FA /* TextAlternativeWithRange.mm in Sources */,
    2810528121                        );
    2810628122                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/WebCore/editing/AlternativeTextController.cpp

    r114220 r120357  
    6969};
    7070
     71class DictationAlternativeDetails : public AlternativeTextDetails {
     72public:
     73    static PassRefPtr<DictationAlternativeDetails> create(uint64_t dictationContext)
     74    {
     75        return adoptRef(new DictationAlternativeDetails(dictationContext));
     76    }
     77
     78    uint64_t dictationContext() const { return m_dictationContext; }
     79
     80private:
     81    DictationAlternativeDetails(uint64_t dictationContext)
     82    : m_dictationContext(dictationContext)
     83    { }
     84
     85    uint64_t m_dictationContext;
     86};
     87
    7188#if USE(AUTOCORRECTION_PANEL)
    7289
     
    91108    }
    92109    return markerTypesForReplacement;
     110}
     111
     112static const Vector<DocumentMarker::MarkerType>& markerTypesForAppliedDictationAlternative()
     113{
     114    DEFINE_STATIC_LOCAL(Vector<DocumentMarker::MarkerType>, markerTypesForAppliedDictationAlternative, ());
     115    if (markerTypesForAppliedDictationAlternative.isEmpty())
     116        markerTypesForAppliedDictationAlternative.append(DocumentMarker::SpellCheckingExemption);
     117    return markerTypesForAppliedDictationAlternative;
    93118}
    94119
     
    216241}
    217242
    218 void AlternativeTextController::applyAlternativeText(const String& alternative, const Vector<DocumentMarker::MarkerType>& markerTypesToAdd)
    219 {
    220     if (!m_alternativeTextInfo.rangeWithAlternative)
     243void AlternativeTextController::applyAlternativeTextToRange(const Range* range, const String& alternative, AlternativeTextType alternativeType, const Vector<DocumentMarker::MarkerType>& markerTypesToAdd)
     244{
     245    if (!range)
    221246        return;
    222247
    223248    ExceptionCode ec = 0;
    224     RefPtr<Range> paragraphRangeContainingCorrection = m_alternativeTextInfo.rangeWithAlternative->cloneRange(ec);
     249    RefPtr<Range> paragraphRangeContainingCorrection = range->cloneRange(ec);
    225250    if (ec)
    226251        return;
    227252
    228     setStart(paragraphRangeContainingCorrection.get(), startOfParagraph(m_alternativeTextInfo.rangeWithAlternative->startPosition()));
    229     setEnd(paragraphRangeContainingCorrection.get(), endOfParagraph(m_alternativeTextInfo.rangeWithAlternative->endPosition()));
     253    setStart(paragraphRangeContainingCorrection.get(), startOfParagraph(range->startPosition()));
     254    setEnd(paragraphRangeContainingCorrection.get(), endOfParagraph(range->endPosition()));
    230255
    231256    // After we replace the word at range rangeWithAlternative, we need to add markers to that range.
     
    239264        return;
    240265
    241     Position startPositionOfrangeWithAlternative = m_alternativeTextInfo.rangeWithAlternative->startPosition();
     266    Position startPositionOfrangeWithAlternative = range->startPosition();
    242267    correctionStartOffsetInParagraphAsRange->setEnd(startPositionOfrangeWithAlternative.containerNode(), startPositionOfrangeWithAlternative.computeOffsetInContainerNode(), ec);
    243268    if (ec)
     
    248273
    249274    // Clone the range, since the caller of this method may want to keep the original range around.
    250     RefPtr<Range> rangeWithAlternative = m_alternativeTextInfo.rangeWithAlternative->cloneRange(ec);
     275    RefPtr<Range> rangeWithAlternative = range->cloneRange(ec);
    251276    applyCommand(SpellingCorrectionCommand::create(rangeWithAlternative, alternative));
    252277    setEnd(paragraphRangeContainingCorrection.get(), m_frame->selection()->selection().start());
     
    260285    DocumentMarkerController* markers = replacementRange->startContainer()->document()->markers();
    261286    size_t size = markerTypesToAdd.size();
    262     for (size_t i = 0; i < size; ++i) {
    263         DocumentMarker::MarkerType markerType = markerTypesToAdd[i];
    264         String description;
    265         if (m_alternativeTextInfo.type != AlternativeTextTypeReversion && (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected))
    266             description = m_alternativeTextInfo.originalText;
    267         markers->addMarker(replacementRange.get(), markerType, description);
    268     }
     287    for (size_t i = 0; i < size; ++i)
     288        markers->addMarker(replacementRange.get(), markerTypesToAdd[i], markerDescriptionForAppliedAlternativeText(alternativeType, markerTypesToAdd[i]));
    269289}
    270290
     
    349369    }
    350370        break;
     371    case AlternativeTextTypeDictationAlternatives:
     372    {
     373#if USE(DICTATION_ALTERNATIVES)
     374        const Range* rangeWithAlternative = m_alternativeTextInfo.rangeWithAlternative.get();
     375        const DictationAlternativeDetails* details = static_cast<const DictationAlternativeDetails*>(m_alternativeTextInfo.details.get());
     376        if (!rangeWithAlternative || !details || !details->dictationContext())
     377            return;
     378        FloatRect boundingBox = rootViewRectForRange(rangeWithAlternative);
     379        m_alternativeTextInfo.isActive = true;
     380        if (!boundingBox.isEmpty()) {
     381            if (AlternativeTextClient* client = alternativeTextClient())
     382                client->showDictationAlternativeUI(boundingBox, details->dictationContext());
     383        }
     384#endif
     385    }
     386        break;
    351387    }
    352388}
     
    354390void AlternativeTextController::handleAlternativeTextUIResult(const String& result)
    355391{
    356     Range* replacedRange = m_alternativeTextInfo.rangeWithAlternative.get();
    357     if (!replacedRange || m_frame->document() != replacedRange->ownerDocument())
    358         return;
    359 
    360     String currentWord = plainText(m_alternativeTextInfo.rangeWithAlternative.get());
     392    Range* rangeWithAlternative = m_alternativeTextInfo.rangeWithAlternative.get();
     393    if (!rangeWithAlternative || m_frame->document() != rangeWithAlternative->ownerDocument())
     394        return;
     395
     396    String currentWord = plainText(rangeWithAlternative);
    361397    // Check to see if the word we are about to correct has been changed between timer firing and callback being triggered.
    362398    if (currentWord != m_alternativeTextInfo.originalText)
     
    368404    case AlternativeTextTypeCorrection:
    369405        if (result.length())
    370             applyAlternativeText(result, markerTypesForAutocorrection());
     406            applyAlternativeTextToRange(rangeWithAlternative, result, m_alternativeTextInfo.type, markerTypesForAutocorrection());
    371407        else if (!m_isDismissedByEditing)
    372             replacedRange->startContainer()->document()->markers()->addMarker(replacedRange, DocumentMarker::RejectedCorrection, m_alternativeTextInfo.originalText);
     408            rangeWithAlternative->startContainer()->document()->markers()->addMarker(rangeWithAlternative, DocumentMarker::RejectedCorrection, m_alternativeTextInfo.originalText);
    373409        break;
    374410    case AlternativeTextTypeReversion:
    375411    case AlternativeTextTypeSpellingSuggestions:
    376412        if (result.length())
    377             applyAlternativeText(result, markerTypesForReplacement());
     413            applyAlternativeTextToRange(rangeWithAlternative, result, m_alternativeTextInfo.type, markerTypesForReplacement());
     414        break;
     415    case AlternativeTextTypeDictationAlternatives:
     416        if (result.length())
     417            applyAlternativeTextToRange(rangeWithAlternative, result, m_alternativeTextInfo.type, markerTypesForAppliedDictationAlternative());
    378418        break;
    379419    }
     
    401441}       
    402442
    403 void AlternativeTextController::respondToChangedSelection(const VisibleSelection& oldSelection)
     443void AlternativeTextController::respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
    404444{
    405445    VisibleSelection currentSelection(m_frame->selection()->selection());
     
    427467
    428468    Node* node = position.containerNode();
    429     int endOffset = position.offsetInContainerNode();
    430469    Vector<DocumentMarker*> markers = node->document()->markers()->markersFor(node);
    431470    size_t markerCount = markers.size();
    432471    for (size_t i = 0; i < markerCount; ++i) {
    433472        const DocumentMarker* marker = markers[i];
    434         if (!shouldStartTimerFor(marker, endOffset))
     473        if (!marker)
    435474            continue;
    436         RefPtr<Range> wordRange = Range::create(m_frame->document(), node, marker->startOffset(), node, marker->endOffset());
    437         String currentWord = plainText(wordRange.get());
    438         if (!currentWord.length())
    439             continue;
    440 
    441         m_alternativeTextInfo.rangeWithAlternative = wordRange;
    442         m_alternativeTextInfo.originalText = currentWord;
    443         if (marker->type() == DocumentMarker::Spelling)
    444             startAlternativeTextUITimer(AlternativeTextTypeSpellingSuggestions);
    445         else {
    446             m_alternativeTextInfo.details = AutocorrectionAlternativeDetails::create(marker->description());
    447             startAlternativeTextUITimer(AlternativeTextTypeReversion);
    448         }
    449 
    450         break;
     475
     476        if (respondToMarkerAtEndOfWord(*marker, position, options))
     477            break;
    451478    }
    452479}
     
    599626    return true;
    600627}
    601    
     628
     629bool AlternativeTextController::shouldStartTimerFor(const WebCore::DocumentMarker &marker, int endOffset) const
     630{
     631    return (((marker.type() == DocumentMarker::Replacement && !marker.description().isNull()) || marker.type() == DocumentMarker::Spelling || marker.type() == DocumentMarker::DictationAlternatives) && static_cast<int>(marker.endOffset()) == endOffset);
     632}
     633
     634bool AlternativeTextController::respondToMarkerAtEndOfWord(const DocumentMarker& marker, const Position& endOfWordPosition, FrameSelection::SetSelectionOptions options)
     635{
     636    if (options & FrameSelection::DictationTriggered)
     637        return false;
     638    if (!shouldStartTimerFor(marker, endOfWordPosition.offsetInContainerNode()))
     639        return false;
     640    Node* node = endOfWordPosition.containerNode();
     641    RefPtr<Range> wordRange = Range::create(m_frame->document(), node, marker.startOffset(), node, marker.endOffset());
     642    if (!wordRange)
     643        return false;
     644    String currentWord = plainText(wordRange.get());
     645    if (!currentWord.length())
     646        return false;
     647    m_alternativeTextInfo.originalText = currentWord;
     648    switch (marker.type()) {
     649    case DocumentMarker::Spelling:
     650        m_alternativeTextInfo.rangeWithAlternative = wordRange;
     651        m_alternativeTextInfo.details = AutocorrectionAlternativeDetails::create("");
     652        startAlternativeTextUITimer(AlternativeTextTypeSpellingSuggestions);
     653        break;
     654    case DocumentMarker::Replacement:
     655        m_alternativeTextInfo.rangeWithAlternative = wordRange;
     656        m_alternativeTextInfo.details = AutocorrectionAlternativeDetails::create(marker.description());
     657        startAlternativeTextUITimer(AlternativeTextTypeReversion);
     658        break;
     659    case DocumentMarker::DictationAlternatives: {
     660        const DictationMarkerDetails* markerDetails = static_cast<const DictationMarkerDetails*>(marker.details());
     661        if (!markerDetails)
     662            return false;
     663        if (currentWord != markerDetails->originalText())
     664            return false;
     665        m_alternativeTextInfo.rangeWithAlternative = wordRange;
     666        m_alternativeTextInfo.details = DictationAlternativeDetails::create(markerDetails->dictationContext());
     667        startAlternativeTextUITimer(AlternativeTextTypeDictationAlternatives);
     668    }
     669        break;
     670    default:
     671        ASSERT_NOT_REACHED();
     672        break;
     673    }
     674    return true;
     675}
     676
     677String AlternativeTextController::markerDescriptionForAppliedAlternativeText(AlternativeTextType alternativeTextType, DocumentMarker::MarkerType markerType)
     678{
     679
     680    if (alternativeTextType != AlternativeTextTypeReversion && alternativeTextType != AlternativeTextTypeDictationAlternatives && (markerType == DocumentMarker::Replacement || markerType == DocumentMarker::Autocorrected))
     681        return m_alternativeTextInfo.originalText;
     682    return "";
     683}
     684
    602685#endif
    603686
     
    625708}
    626709
     710void AlternativeTextController::removeDictationAlternativesForMarker(const DocumentMarker* marker)
     711{
     712#if USE(DICTATION_ALTERNATIVES)
     713    DictationMarkerDetails* details = static_cast<DictationMarkerDetails*>(marker->details());
     714    if (AlternativeTextClient* client = alternativeTextClient())
     715        client->removeDictationAlternatives(details->dictationContext());
     716#else
     717    UNUSED_PARAM(marker);
     718#endif
     719}
     720
     721Vector<String> AlternativeTextController::dictationAlternativesForMarker(const DocumentMarker* marker)
     722{
     723#if USE(DICTATION_ALTERNATIVES)
     724    ASSERT(marker->type() == DocumentMarker::DictationAlternatives);
     725    if (AlternativeTextClient* client = alternativeTextClient()) {
     726        DictationMarkerDetails* details = static_cast<DictationMarkerDetails*>(marker->details());
     727        return client->dictationAlternatives(details->dictationContext());
     728    }
     729    return Vector<String>();
     730#else
     731    UNUSED_PARAM(marker);
     732    return Vector<String>();
     733#endif
     734}
     735
     736void AlternativeTextController::applyDictationAlternative(const String& alternativeString)
     737{
     738#if USE(DICTATION_ALTERNATIVES)
     739    Editor* editor = m_frame->editor();
     740    RefPtr<Range> selection = editor->selectedRange();
     741    if (!selection || !editor->shouldInsertText(alternativeString, selection.get(), EditorInsertActionPasted))
     742        return;
     743    DocumentMarkerController* markers = selection->startContainer()->document()->markers();
     744    Vector<DocumentMarker*> dictationAlternativesMarkers = markers->markersInRange(selection.get(), DocumentMarker::DictationAlternatives);
     745    for (size_t i = 0; i < dictationAlternativesMarkers.size(); ++i)
     746        removeDictationAlternativesForMarker(dictationAlternativesMarkers[i]);
     747
     748    applyAlternativeTextToRange(selection.get(), alternativeString, AlternativeTextTypeDictationAlternatives, markerTypesForAppliedDictationAlternative());
     749#else
     750    UNUSED_PARAM(alternativeString);
     751#endif
     752}
     753
    627754} // namespace WebCore
  • trunk/Source/WebCore/editing/AlternativeTextController.h

    r114220 r120357  
    2929#include "AlternativeTextClient.h"
    3030#include "DocumentMarker.h"
     31#include "FrameSelection.h"
    3132#include "Range.h"
    3233#include "TextChecking.h"
     
    109110    void respondToAppliedEditing(CompositeEditCommand*) UNLESS_ENABLED({ })
    110111    void respondToUnappliedEditing(EditCommandComposition*) UNLESS_ENABLED({ })
    111     void respondToChangedSelection(const VisibleSelection& oldSelection) UNLESS_ENABLED({ UNUSED_PARAM(oldSelection); })
     112    void respondToChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions) UNLESS_ENABLED({ UNUSED_PARAM(oldSelection); })
    112113
    113114    void stopPendingCorrection(const VisibleSelection& oldSelection) UNLESS_ENABLED({ UNUSED_PARAM(oldSelection); })
     
    131132
    132133    bool insertDictatedText(const String&, const Vector<DictationAlternative>&, Event*);
     134    void removeDictationAlternativesForMarker(const DocumentMarker*);
     135    Vector<String> dictationAlternativesForMarker(const DocumentMarker*);
     136    void applyDictationAlternative(const String& alternativeString);
    133137
    134138private:
    135139#if USE(AUTOCORRECTION_PANEL)
    136140    String dismissSoon(ReasonForDismissingAlternativeText);
    137     void applyAlternativeText(const String& alternative, const Vector<DocumentMarker::MarkerType>&);
     141    void applyAlternativeTextToRange(const Range*, const String& alternative, AlternativeTextType, const Vector<DocumentMarker::MarkerType>&);
    138142    void timerFired(Timer<AlternativeTextController>*);
    139143    void recordAutocorrectionResponseReversed(const String& replacedString, const String& replacementString);
    140144    void recordSpellcheckerResponseForModifiedCorrection(Range* rangeOfCorrection, const String& corrected, const String& correction);
     145    String markerDescriptionForAppliedAlternativeText(AlternativeTextType, DocumentMarker::MarkerType);
    141146
    142     bool shouldStartTimerFor(const DocumentMarker* marker, int endOffset) const
    143     {
    144         return (((marker->type() == DocumentMarker::Replacement && !marker->description().isNull())
    145                  || marker->type() == DocumentMarker::Spelling) && static_cast<int>(marker->endOffset()) == endOffset);
    146     }
     147    bool shouldStartTimerFor(const DocumentMarker&, int endOffset) const;
     148    bool respondToMarkerAtEndOfWord(const DocumentMarker&, const Position& endOfWordPosition, FrameSelection::SetSelectionOptions);
    147149
    148150    AlternativeTextClient* alternativeTextClient();
  • trunk/Source/WebCore/editing/Editor.cpp

    r120279 r120357  
    481481}
    482482
    483 void Editor::respondToChangedSelection(const VisibleSelection& oldSelection)
     483void Editor::notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions options)
    484484{
    485485    if (client())
     
    487487    setStartNewKillRingSequence(true);
    488488    m_deleteButtonController->respondToChangedSelection(oldSelection);
    489     m_alternativeTextController->respondToChangedSelection(oldSelection);
     489    m_alternativeTextController->respondToChangedSelection(oldSelection, options);
    490490}
    491491
     
    790790
    791791    // Don't clear the typing style with this selection change.  We do those things elsewhere if necessary.
    792     changeSelectionAfterCommand(newSelection, false, false);
     792    FrameSelection::SetSelectionOptions options = cmd->isDictationCommand() ? FrameSelection::DictationTriggered : 0;
     793    changeSelectionAfterCommand(newSelection, options);
    793794
    794795    if (!cmd->preservesTypingStyle())
     
    816817   
    817818    VisibleSelection newSelection(cmd->startingSelection());
    818     changeSelectionAfterCommand(newSelection, true, true);
     819    changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    819820    m_alternativeTextController->respondToUnappliedEditing(cmd.get());
    820821   
     
    832833   
    833834    VisibleSelection newSelection(cmd->endingSelection());
    834     changeSelectionAfterCommand(newSelection, true, true);
     835    changeSelectionAfterCommand(newSelection, FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle);
    835836   
    836837    m_lastEditCommand = 0;
     
    22672268    RefPtr<Range> wordRange = Range::create(document, startOfFirstWord.deepEquivalent(), endOfLastWord.deepEquivalent());
    22682269
     2270    Vector<DocumentMarker*> markers = document->markers()->markersInRange(wordRange.get(), DocumentMarker::DictationAlternatives);
     2271    for (size_t i = 0; i < markers.size(); ++i)
     2272        m_alternativeTextController->removeDictationAlternativesForMarker(markers[i]);
     2273
    22692274    document->markers()->removeMarkers(wordRange.get(), DocumentMarker::Spelling | DocumentMarker::CorrectionIndicator | DocumentMarker::SpellCheckingExemption | DocumentMarker::DictationAlternatives, DocumentMarkerController::RemovePartiallyOverlappingMarker);
    22702275    document->markers()->clearDescriptionOnMarkersIntersectingRange(wordRange.get(), DocumentMarker::Replacement);
     
    24142419}
    24152420
    2416 void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle)
     2421void Editor::changeSelectionAfterCommand(const VisibleSelection& newSelection,  FrameSelection::SetSelectionOptions options)
    24172422{
    24182423    // If the new selection is orphaned, then don't update the selection.
     
    24252430    // See <rdar://problem/5729315> Some shouldChangeSelectedDOMRange contain Ranges for selections that are no longer valid
    24262431    bool selectionDidNotChangeDOMPosition = newSelection == m_frame->selection()->selection();
    2427     if (selectionDidNotChangeDOMPosition || m_frame->selection()->shouldChangeSelection(newSelection)) {
    2428         FrameSelection::SetSelectionOptions options = 0;
    2429         if (closeTyping)
    2430             options |= FrameSelection::CloseTyping;
    2431         if (clearTypingStyle)
    2432             options |= FrameSelection::ClearTypingStyle;
     2432    if (selectionDidNotChangeDOMPosition || m_frame->selection()->shouldChangeSelection(newSelection))
    24332433        m_frame->selection()->setSelection(newSelection, options);
    2434     }
    24352434
    24362435    // Some editing operations change the selection visually without affecting its position within the DOM.
     
    28272826        m_frame->document()->markers()->removeMarkers(DocumentMarker::Grammar);
    28282827
    2829     respondToChangedSelection(oldSelection);
     2828    notifyComponentsOnChangedSelection(oldSelection, options);
    28302829}
    28312830
     
    29182917}
    29192918
     2919Vector<String> Editor::dictationAlternativesForMarker(const DocumentMarker* marker)
     2920{
     2921    return m_alternativeTextController->dictationAlternativesForMarker(marker);
     2922}
     2923
     2924void Editor::applyDictationAlternativelternative(const String& alternativeString)
     2925{
     2926    m_alternativeTextController->applyDictationAlternative(alternativeString);
     2927}
     2928
    29202929} // namespace WebCore
  • trunk/Source/WebCore/editing/Editor.h

    r120005 r120357  
    135135    bool shouldDeleteRange(Range*) const;
    136136    bool shouldApplyStyle(StylePropertySet*, Range*);
    137    
    138     void respondToChangedSelection(const VisibleSelection& oldSelection);
     137
    139138    void respondToChangedContents(const VisibleSelection& endingSelection);
    140139
     
    396395    EditorParagraphSeparator defaultParagraphSeparator() const { return m_defaultParagraphSeparator; }
    397396    void setDefaultParagraphSeparator(EditorParagraphSeparator separator) { m_defaultParagraphSeparator = separator; }
    398 
     397    Vector<String> dictationAlternativesForMarker(const DocumentMarker*);
     398    void applyDictationAlternativelternative(const String& alternativeString);
    399399private:
    400400    virtual void willDetachPage() OVERRIDE;
     
    430430    void setComposition(const String&, SetCompositionMode);
    431431
    432     void changeSelectionAfterCommand(const VisibleSelection& newSelection, bool closeTyping, bool clearTypingStyle);
     432    void changeSelectionAfterCommand(const VisibleSelection& newSelection, FrameSelection::SetSelectionOptions);
     433    void notifyComponentsOnChangedSelection(const VisibleSelection& oldSelection, FrameSelection::SetSelectionOptions);
    433434
    434435    Node* findEventTargetFromSelection() const;
  • trunk/Source/WebCore/editing/FrameSelection.h

    r119705 r120357  
    119119        SpellCorrectionTriggered = 1 << 3,
    120120        DoNotSetFocus = 1 << 4,
     121        DictationTriggered = 1 << 5
    121122    };
    122123    typedef unsigned SetSelectionOptions; // Union of values in SetSelectionOption and EUserTriggered
  • trunk/Source/WebCore/page/AlternativeTextClient.h

    r115369 r120357  
    3232#include <wtf/text/WTFString.h>
    3333
     34#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
     35// Some platforms provide UI for suggesting alternative dictation text.
     36#define WTF_USE_DICTATION_ALTERNATIVES 1
     37#endif // PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
     38
    3439namespace WebCore {
    3540
     
    4449    AlternativeTextTypeReversion,
    4550    AlternativeTextTypeSpellingSuggestions,
     51    AlternativeTextTypeDictationAlternatives
    4652};
    4753
     
    5561    virtual ~AlternativeTextClient() { }
    5662    virtual void pageDestroyed() = 0;
    57 
     63#if USE(AUTOCORRECTION_PANEL)
    5864    virtual void showCorrectionAlternative(AlternativeTextType, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacmentString, const Vector<String>& alternativeReplacementStrings) = 0;
    5965    virtual void dismissAlternative(ReasonForDismissingAlternativeText) = 0;
    6066    virtual String dismissAlternativeSoon(ReasonForDismissingAlternativeText) = 0;
    6167    virtual void recordAutocorrectionResponse(AutocorrectionResponseType, const String& replacedString, const String& replacementString) = 0;
     68#endif
     69#if USE(DICTATION_ALTERNATIVES)
     70    virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext) = 0;
     71    virtual void dismissDictationAlternativeUI() = 0;
     72    virtual void removeDictationAlternatives(uint64_t dictationContext) = 0;
     73    virtual Vector<String> dictationAlternatives(uint64_t dictationContext) = 0;
     74#endif
    6275};
    6376   
  • trunk/Source/WebCore/page/ContextMenuController.cpp

    r119687 r120357  
    482482        break;
    483483#endif
     484    case ContextMenuItemTagDictationAlternative:
     485        frame->editor()->applyDictationAlternativelternative(item->title());
     486        break;
    484487    default:
    485488        break;
     
    897900        FrameSelection* selection = frame->selection();
    898901        bool inPasswordField = selection->isInPasswordField();
    899         bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
    900 
    901         if (!inPasswordField && spellCheckingEnabled) {
    902             // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
    903             // is never considered a misspelling and bad grammar at the same time)
    904             bool misspelling;
    905             bool badGrammar;
    906             Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
    907             if (misspelling || badGrammar) {
    908                 size_t size = guesses.size();
    909                 if (size == 0) {
    910                     // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
    911                     // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
    912                     if (misspelling) {
    913                         appendItem(NoGuessesItem, m_contextMenu.get());
     902        if (!inPasswordField) {
     903            bool haveContextMenuItemsForMisspellingOrGrammer = false;
     904            bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
     905            if (spellCheckingEnabled) {
     906                // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
     907                // is never considered a misspelling and bad grammar at the same time)
     908                bool misspelling;
     909                bool badGrammar;
     910                Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
     911                if (misspelling || badGrammar) {
     912                    size_t size = guesses.size();
     913                    if (!size) {
     914                        // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
     915                        // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
     916                        if (misspelling) {
     917                            appendItem(NoGuessesItem, m_contextMenu.get());
     918                            appendItem(*separatorItem(), m_contextMenu.get());
     919                        }
     920                    } else {
     921                        for (unsigned i = 0; i < size; i++) {
     922                            const String &guess = guesses[i];
     923                            if (!guess.isEmpty()) {
     924                                ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
     925                                appendItem(item, m_contextMenu.get());
     926                            }
     927                        }
    914928                        appendItem(*separatorItem(), m_contextMenu.get());
    915929                    }
     930                    if (misspelling) {
     931                        appendItem(IgnoreSpellingItem, m_contextMenu.get());
     932                        appendItem(LearnSpellingItem, m_contextMenu.get());
     933                    } else
     934                        appendItem(IgnoreGrammarItem, m_contextMenu.get());
     935                    appendItem(*separatorItem(), m_contextMenu.get());
     936                    haveContextMenuItemsForMisspellingOrGrammer = true;
     937#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
    916938                } else {
    917                     for (unsigned i = 0; i < size; i++) {
    918                         const String &guess = guesses[i];
    919                         if (!guess.isEmpty()) {
    920                             ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
    921                             appendItem(item, m_contextMenu.get());
    922                         }
     939                    // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
     940                    String replacedString = m_hitTestResult.replacedString();
     941                    if (!replacedString.isEmpty()) {
     942                        ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
     943                        appendItem(item, m_contextMenu.get());
     944                        appendItem(*separatorItem(), m_contextMenu.get());
     945                        haveContextMenuItemsForMisspellingOrGrammer = true;
    923946                    }
    924                     appendItem(*separatorItem(), m_contextMenu.get());                   
     947#endif
    925948                }
    926                
    927                 if (misspelling) {
    928                     appendItem(IgnoreSpellingItem, m_contextMenu.get());
    929                     appendItem(LearnSpellingItem, m_contextMenu.get());
    930                 } else
    931                     appendItem(IgnoreGrammarItem, m_contextMenu.get());
    932                 appendItem(*separatorItem(), m_contextMenu.get());
    933 #if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
    934             } else {
    935                 // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
    936                 String replacedString = m_hitTestResult.replacedString();
    937                 if (!replacedString.isEmpty()) {
    938                     ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
    939                     appendItem(item, m_contextMenu.get());
     949            }
     950
     951            if (!haveContextMenuItemsForMisspellingOrGrammer) {
     952                // Spelling and grammar checking is mutually exclusive with dictation alternatives.
     953                Vector<String> dictationAlternatives = m_hitTestResult.dictationAlternatives();
     954                if (!dictationAlternatives.isEmpty()) {
     955                    for (size_t i = 0; i < dictationAlternatives.size(); ++i) {
     956                        ContextMenuItem item(ActionType, ContextMenuItemTagDictationAlternative, dictationAlternatives[i]);
     957                        appendItem(item, m_contextMenu.get());
     958                    }
    940959                    appendItem(*separatorItem(), m_contextMenu.get());
    941960                }
    942 #endif
    943961            }
    944962        }
     
    13531371        case ContextMenuItemLastCustomTag:
    13541372        case ContextMenuItemBaseApplicationTag:
     1373        case ContextMenuItemTagDictationAlternative:
    13551374            break;
    13561375        case ContextMenuItemTagMediaPlayPause:
  • trunk/Source/WebCore/platform/ContextMenuItem.h

    r117970 r120357  
    135135        ContextMenuItemTagPDFSinglePageScrolling,
    136136        ContextMenuItemTagPDFFacingPagesScrolling,
     137        ContextMenuItemTagDictationAlternative,
    137138#if ENABLE(INSPECTOR)
    138139        ContextMenuItemTagInspectElement,
  • trunk/Source/WebCore/rendering/HitTestResult.cpp

    r119733 r120357  
    711711}
    712712
     713Vector<String> HitTestResult::dictationAlternatives() const
     714{
     715    // Return the dictation context handle if the text at this point has DictationAlternative marker, which means this text is
     716    if (!m_innerNonSharedNode)
     717        return Vector<String>();
     718
     719    DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(hitTestPoint().point(), DocumentMarker::DictationAlternatives);
     720    if (!marker)
     721        return Vector<String>();
     722
     723    Frame* frame = innerNonSharedNode()->document()->frame();
     724    if (!frame)
     725        return Vector<String>();
     726
     727    return frame->editor()->dictationAlternativesForMarker(marker);
     728}
     729
    713730} // namespace WebCore
  • trunk/Source/WebCore/rendering/HitTestResult.h

    r117091 r120357  
    158158    const NodeSet& rectBasedTestResult() const;
    159159
     160    Vector<String> dictationAlternatives() const;
     161
    160162private:
    161163    NodeSet& mutableRectBasedTestResult(); // See above.
  • trunk/Source/WebCore/rendering/InlineTextBox.cpp

    r119528 r120357  
    10311031        markerSpansWholeBox = false;
    10321032
    1033     if (!markerSpansWholeBox || grammar) {
     1033    bool isDictationMarker = marker->type() == DocumentMarker::DictationAlternatives;
     1034    if (!markerSpansWholeBox || grammar || isDictationMarker) {
    10341035        int startPosition = max<int>(marker->startOffset() - m_start, 0);
    10351036        int endPosition = min<int>(marker->endOffset() - m_start, m_len);
     
    10511052        // Store rendered rects for bad grammar markers, so we can hit-test against it elsewhere in order to
    10521053        // display a toolTip. We don't do this for misspelling markers.
    1053         if (grammar) {
     1054        if (grammar || isDictationMarker) {
    10541055            markerRect.move(-boxOrigin.x(), -boxOrigin.y());
    10551056            markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
  • trunk/Source/WebKit/mac/ChangeLog

    r120029 r120357  
     12012-06-14  Jia Pu  <jpu@apple.com>
     2
     3        Mark text with text alternative with blue underline.
     4        https://bugs.webkit.org/show_bug.cgi?id=83047
     5
     6        Reviewed by Enrica Casucci.
     7
     8        Changes in WebKit include implementation of new functions declared in AlternativeTextClient,
     9        and logic for calling Editor::insertDictatedText() instead of Editor::insertText() when there's
     10        alternatives attached to the input string.
     11
     12        * WebCoreSupport/CorrectionPanel.mm:
     13        (correctionIndicatorType):
     14        (CorrectionPanel::handleAcceptedReplacement):
     15        * WebCoreSupport/WebAlternativeTextClient.h:
     16        (WebAlternativeTextClient):
     17        * WebCoreSupport/WebAlternativeTextClient.mm:
     18        (WebAlternativeTextClient::showCorrectionAlternative):
     19        (WebAlternativeTextClient::dismissAlternative):
     20        (WebAlternativeTextClient::dismissAlternativeSoon):
     21        (WebAlternativeTextClient::recordAutocorrectionResponse):
     22        (WebAlternativeTextClient::removeDictationAlternatives):
     23        (WebAlternativeTextClient::showDictationAlternativeUI):
     24        (WebAlternativeTextClient::dismissDictationAlternativeUI):
     25        (WebAlternativeTextClient::dictationAlternatives):
     26        * WebView/WebHTMLView.mm:
     27        (-[WebHTMLView validAttributesForMarkedText]):
     28        (-[WebHTMLView insertText:]):
     29        * WebView/WebView.mm:
     30        (-[WebView handleAcceptedAlternativeText:]):
     31        (-[WebView _getWebCoreDictationAlternatives:fromTextAlternatives:]):
     32        (-[WebView _showDictationAlternativeUI:WebCore::forDictationContext:]):
     33        (-[WebView _dismissDictationAlternativeUI]):
     34        (-[WebView _removeDictationAlternatives:]):
     35        (-[WebView _dictationAlternatives:]):
     36        * WebView/WebViewData.h:
     37        * WebView/WebViewData.mm:
     38        (-[WebViewPrivate init]):
     39        * WebView/WebViewInternal.h:
     40        * WebView/WebViewPrivate.h:
     41
    1422012-06-11  Alexis Menard  <alexis.menard@openbossa.org>
    243
  • trunk/Source/WebKit/mac/WebCoreSupport/CorrectionPanel.mm

    r113340 r120357  
    2626
    2727#import "WebViewInternal.h"
    28 #import "WebViewPrivate.h"
    2928
    3029#if USE(AUTOCORRECTION_PANEL)
     
    4039    case AlternativeTextTypeSpellingSuggestions:
    4140        return NSCorrectionIndicatorTypeGuesses;
     41    case AlternativeTextTypeDictationAlternatives:
     42        ASSERT_NOT_REACHED();
     43        break;
    4244    }
    4345    ASSERT_NOT_REACHED();
     
    132134    }
    133135   
    134     [m_view.get() handleCorrectionPanelResult:acceptedReplacement];
     136    [m_view.get() handleAcceptedAlternativeText:acceptedReplacement];
    135137    m_view.clear();
    136138    if (acceptedReplacement)
  • trunk/Source/WebKit/mac/WebCoreSupport/WebAlternativeTextClient.h

    r115369 r120357  
    3838    virtual ~WebAlternativeTextClient();
    3939    virtual void pageDestroyed() OVERRIDE;
     40#if USE(AUTOCORRECTION_PANEL)
    4041    virtual void showCorrectionAlternative(WebCore::AlternativeTextType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) OVERRIDE;
    4142    virtual void dismissAlternative(WebCore::ReasonForDismissingAlternativeText) OVERRIDE;
    4243    virtual String dismissAlternativeSoon(WebCore::ReasonForDismissingAlternativeText) OVERRIDE;
    4344    virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String& replacedString, const String& replacementString) OVERRIDE;
     45#endif
     46#if USE(DICTATION_ALTERNATIVES)
     47    virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext) OVERRIDE;
     48    virtual void dismissDictationAlternativeUI() OVERRIDE;
     49    virtual void removeDictationAlternatives(uint64_t dictationContext) OVERRIDE;
     50    virtual Vector<String> dictationAlternatives(uint64_t dictationContext) OVERRIDE;
     51#endif
    4452private:
    4553    WebView* m_webView;
  • trunk/Source/WebKit/mac/WebCoreSupport/WebAlternativeTextClient.mm

    r115369 r120357  
    2626#include "WebAlternativeTextClient.h"
    2727
     28#include "WebViewInternal.h"
     29
    2830using namespace WebCore;
    2931
     
    4547}
    4648
     49#if USE(AUTOCORRECTION_PANEL)
    4750void WebAlternativeTextClient::showCorrectionAlternative(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
    4851{
    49 #if USE(AUTOCORRECTION_PANEL)
    5052    m_correctionPanel.show(m_webView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
    51 #endif
    5253}
    5354
    5455void WebAlternativeTextClient::dismissAlternative(ReasonForDismissingAlternativeText reason)
    5556{
    56 #if USE(AUTOCORRECTION_PANEL)
    5757    m_correctionPanel.dismiss(reason);
    58 #endif
    5958}
    6059
    6160String WebAlternativeTextClient::dismissAlternativeSoon(ReasonForDismissingAlternativeText reason)
    6261{
    63 #if USE(AUTOCORRECTION_PANEL)
    6462    return m_correctionPanel.dismiss(reason);
    65 #else
    66 return String();
    67 #endif
    6863}
    6964
    7065void WebAlternativeTextClient::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
    7166{
    72 #if USE(AUTOCORRECTION_PANEL)
    7367    NSCorrectionResponse response = responseType == AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
    74 CorrectionPanel::recordAutocorrectionResponse(m_webView, response, replacedString, replacementString);
     68    CorrectionPanel::recordAutocorrectionResponse(m_webView, response, replacedString, replacementString);
     69}
    7570#endif
     71
     72#if USE(DICTATION_ALTERNATIVES)
     73void WebAlternativeTextClient::removeDictationAlternatives(uint64_t dictationContext)
     74{
     75    [m_webView _removeDictationAlternatives:dictationContext];
    7676}
     77
     78void WebAlternativeTextClient::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
     79{
     80    [m_webView _showDictationAlternativeUI:boundingBoxOfDictatedText forDictationContext:dictationContext];
     81}
     82
     83void WebAlternativeTextClient::dismissDictationAlternativeUI()
     84{
     85    [m_webView _dismissDictationAlternativeUI];
     86}
     87
     88Vector<String> WebAlternativeTextClient::dictationAlternatives(uint64_t dictationContext)
     89{
     90    return [m_webView _dictationAlternatives:dictationContext];
     91}
     92#endif
  • trunk/Source/WebKit/mac/WebView/WebHTMLView.mm

    r117695 r120357  
    114114#import <WebCore/StylePropertySet.h>
    115115#import <WebCore/Text.h>
     116#import <WebCore/TextAlternativeWithRange.h>
    116117#import <WebCore/WebCoreObjCExtras.h>
    117118#import <WebCore/WebFontCache.h>
     
    56045605        validAttributes = [[NSArray alloc] initWithObjects:
    56055606            NSUnderlineStyleAttributeName, NSUnderlineColorAttributeName,
    5606             NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName, nil];
     5607            NSMarkedClauseSegmentAttributeName, NSTextInputReplacementRangeAttributeName,
     5608#if USE(DICTATION_ALTERNATIVES)
     5609                           NSTextAlternativesAttributeName,
     5610#endif
     5611                           nil];
    56075612        // NSText also supports the following attributes, but it's
    56085613        // hard to tell which are really required for text input to
     
    59245929    bool isFromInputMethod = coreFrame && coreFrame->editor()->hasComposition();
    59255930
     5931    Vector<DictationAlternative> dictationAlternativeLocations;
    59265932    if (isAttributedString) {
     5933#if USE(DICTATION_ALTERNATIVES)
     5934        Vector<WebCore::TextAlternativeWithRange> textAlternatives;
     5935        collectDictationTextAlternatives(string, textAlternatives);
     5936        if (!textAlternatives.isEmpty())
     5937            [[self _webView] _getWebCoreDictationAlternatives:dictationAlternativeLocations fromTextAlternatives:textAlternatives];
     5938#endif
    59275939        // FIXME: We ignore most attributes from the string, so for example inserting from Character Palette loses font and glyph variation data.
    59285940        // It does not look like any input methods ever use insertText: with attributes other than NSTextInputReplacementRangeAttributeName.
     
    59635975        // An insertText: might be handled by other responders in the chain if we don't handle it.
    59645976        // One example is space bar that results in scrolling down the page.
    5965         eventHandled = coreFrame->editor()->insertText(eventText, event);
     5977
     5978        if (!dictationAlternativeLocations.isEmpty())
     5979            eventHandled = coreFrame->editor()->insertDictatedText(eventText, dictationAlternativeLocations, event);
     5980        else
     5981            eventHandled = coreFrame->editor()->insertText(eventText, event);
    59665982    } else {
    59675983        eventHandled = true;
  • trunk/Source/WebKit/mac/WebView/WebView.mm

    r118086 r120357  
    112112#import <JavaScriptCore/JSValueRef.h>
    113113#import <WebCore/AbstractDatabase.h>
     114#import <WebCore/AlternativeTextUIController.h>
    114115#import <WebCore/ApplicationCacheStorage.h>
    115116#import <WebCore/BackForwardListImpl.h>
     
    55375538#endif
    55385539
    5539 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
    5540 - (void)handleCorrectionPanelResult:(NSString*)result
    5541 {
    5542     WebFrame *webFrame = [self _selectedOrMainFrame];
    5543     Frame* coreFrame = core(webFrame);
    5544     if (coreFrame)
    5545         coreFrame->editor()->handleAlternativeTextUIResult(result);
    5546 }
    5547 #endif
    5548 
    55495540@end
    55505541
     
    64116402#endif
    64126403
     6404#if USE(AUTOCORRECTION_PANEL)
     6405- (void)handleAcceptedAlternativeText:(NSString*)text
     6406{
     6407    WebFrame *webFrame = [self _selectedOrMainFrame];
     6408    Frame* coreFrame = core(webFrame);
     6409    if (coreFrame)
     6410        coreFrame->editor()->handleAlternativeTextUIResult(text);
     6411}
     6412#endif
     6413
     6414#if USE(DICTATION_ALTERNATIVES)
     6415- (void)_getWebCoreDictationAlternatives:(Vector<DictationAlternative>&)alternatives fromTextAlternatives:(const Vector<TextAlternativeWithRange>&)alternativesWithRange
     6416{
     6417    for (size_t i = 0; i < alternativesWithRange.size(); ++i) {
     6418        const TextAlternativeWithRange& alternativeWithRange = alternativesWithRange[i];
     6419        uint64_t dictationContext = _private->m_alternativeTextUIController->addAlternatives(alternativeWithRange.alternatives);
     6420        if (dictationContext)
     6421            alternatives.append(DictationAlternative(alternativeWithRange.range.location, alternativeWithRange.range.length, dictationContext));
     6422    }
     6423}
     6424
     6425- (void)_showDictationAlternativeUI:(const WebCore::FloatRect&)boundingBoxOfDictatedText forDictationContext:(uint64_t)dictationContext
     6426{
     6427    _private->m_alternativeTextUIController->showAlternatives(self, [self _convertRectFromRootView:boundingBoxOfDictatedText], dictationContext, ^(NSString* acceptedAlternative) {
     6428        [self handleAcceptedAlternativeText:acceptedAlternative];
     6429    });
     6430}
     6431
     6432- (void)_dismissDictationAlternativeUI
     6433{
     6434    _private->m_alternativeTextUIController->dismissAlternatives();
     6435}
     6436
     6437- (void)_removeDictationAlternatives:(uint64_t)dictationContext
     6438{
     6439    _private->m_alternativeTextUIController->removeAlternatives(dictationContext);
     6440}
     6441
     6442- (Vector<String>)_dictationAlternatives:(uint64_t)dictationContext
     6443{
     6444    return _private->m_alternativeTextUIController->alternativesForContext(dictationContext);
     6445}
     6446#endif
     6447
    64136448- (NSPoint)_convertPointFromRootView:(NSPoint)point
    64146449{
  • trunk/Source/WebKit/mac/WebView/WebViewData.h

    r108409 r120357  
    3030#import "WebTypesInternal.h"
    3131#import "WebDelegateImplementationCaching.h"
     32#import <WebCore/AlternativeTextClient.h>
    3233#import <WebCore/LayerFlushScheduler.h>
    3334#import <WebCore/LayerFlushSchedulerClient.h>
     
    3940
    4041namespace WebCore {
    41     class HistoryItem;
    42     class Page;
     42class AlternativeTextUIController;
     43class HistoryItem;
     44class Page;
    4345}
    4446
     
    201203
    202204    float customDeviceScaleFactor;
     205
     206#if USE(DICTATION_ALTERNATIVES)
     207    OwnPtr<WebCore::AlternativeTextUIController> m_alternativeTextUIController;
     208#endif
    203209}
    204210@end
  • trunk/Source/WebKit/mac/WebView/WebViewData.mm

    r105552 r120357  
    3232#import "WebKitLogging.h"
    3333#import "WebPreferenceKeysPrivate.h"
     34#import <WebCore/AlternativeTextUIController.h>
    3435#import <WebCore/WebCoreObjCExtras.h>
    3536#import <WebCore/HistoryItem.h>
     
    101102    pluginDatabaseClientCount++;
    102103
     104#if USE(DICTATION_ALTERNATIVES)
     105    m_alternativeTextUIController = adoptPtr(new WebCore::AlternativeTextUIController);
     106#endif
     107
    103108    return self;
    104109}
  • trunk/Source/WebKit/mac/WebView/WebViewInternal.h

    r104181 r120357  
    3535
    3636#ifdef __cplusplus
     37#import <WebCore/AlternativeTextClient.h>
    3738#import <WebCore/FindOptions.h>
     39#import <WebCore/FloatRect.h>
     40#import <WebCore/TextAlternativeWithRange.h>
    3841#import <WebCore/WebCoreKeyboardUIMode.h>
    3942
    4043#include <wtf/Forward.h>
     44#include <wtf/RetainPtr.h>
    4145
    4246namespace WebCore {
    43     class Element;
    44     class Frame;
    45     class HistoryItem;
    46     class KURL;
    47     class KeyboardEvent;
    48     class Page;
    49     class RenderBox;
    50     class Node;
     47class Element;
     48class Event;
     49class Frame;
     50class HistoryItem;
     51class KURL;
     52class KeyboardEvent;
     53class Page;
     54class RenderBox;
     55class Node;
     56struct DictationAlternative;
    5157}
    5258#endif
     
    5965
    6066WebCore::FindOptions coreOptions(WebFindOptions options);
     67
     68#if USE(DICTATION_ALTERNATIVES)
     69OBJC_CLASS NSTextAlternatives;
     70#endif
    6171
    6272@interface WebView (WebViewEditingExtras)
     
    94104#if ENABLE(GLIB_SUPPORT)
    95105- (void)_scheduleGlibContextIterations;
     106#endif
     107
     108#if USE(AUTOCORRECTION_PANEL)
     109- (void)handleAcceptedAlternativeText:(NSString*)text;
     110#endif
     111
     112#if USE(DICTATION_ALTERNATIVES)
     113- (void)_getWebCoreDictationAlternatives:(Vector<WebCore::DictationAlternative>&)alternatives fromTextAlternatives:(const Vector<WebCore::TextAlternativeWithRange>&)alternativesWithRange;
     114- (void)_showDictationAlternativeUI:(const WebCore::FloatRect&)boundingBoxOfDictatedText forDictationContext:(uint64_t)dictationContext;
     115- (void)_dismissDictationAlternativeUI;
     116- (void)_removeDictationAlternatives:(uint64_t)dictationContext;
     117- (Vector<String>)_dictationAlternatives:(uint64_t)dictationContext;
    96118#endif
    97119
  • trunk/Source/WebKit/mac/WebView/WebViewPrivate.h

    r117460 r120357  
    688688- (void)toggleAutomaticSpellingCorrection:(id)sender;
    689689#endif
    690 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
    691 - (void)handleCorrectionPanelResult:(NSString*)result;
    692 #endif
    693690@end
    694691
  • trunk/Source/WebKit2/ChangeLog

    r120329 r120357  
     12012-06-14  Jia Pu  <jpu@apple.com>
     2
     3        Mark text with text alternative with blue underline.
     4        https://bugs.webkit.org/show_bug.cgi?id=83047
     5
     6        Reviewed by Enrica Casucci.
     7
     8        Changes in WebKit2 include implementation of new functions declared in AlternativeTextClient,
     9        and logic for calling Editor::insertDictatedText() instead of Editor::insertText() when there's
     10        alternatives attached to the input string.
     11
     12        * Shared/API/c/WKContextMenuItemTypes.h:
     13        * Shared/API/c/WKSharedAPICast.h:
     14        * Shared/WebCoreArgumentCoders.cpp:
     15        * Shared/WebCoreArgumentCoders.h:
     16        * UIProcess/API/mac/PageClientImpl.h:
     17        * UIProcess/API/mac/PageClientImpl.mm:
     18        (WebKit::PageClientImpl::PageClientImpl):
     19        (WebKit::PageClientImpl::pageClosed):
     20        (WebKit::PageClientImpl::addDictationAlternatives):
     21        (WebKit::PageClientImpl::removeDictationAlternatives):
     22        (WebKit::PageClientImpl::showDictationAlternativeUI):
     23        (WebKit::PageClientImpl::dictationAlternatives):
     24        (WebKit::PageClientImpl::dismissDictationAlternativeUI):
     25        * UIProcess/API/mac/WKView.mm:
     26        (-[WKView insertText:replacementRange:]):
     27        (-[WKView validAttributesForMarkedText]):
     28        (-[WKView handleAcceptedAlternativeText:]):
     29        * UIProcess/API/mac/WKViewInternal.h:
     30        * UIProcess/PageClient.h:
     31        * UIProcess/WebPageProxy.cpp:
     32        (WebKit::WebPageProxy::showDictationAlternativeUI):
     33        (WebKit::WebPageProxy::dismissDictationAlternativeUI):
     34        (WebKit::WebPageProxy::removeDictationAlternatives):
     35        (WebKit::WebPageProxy::dictationAlternatives):
     36        * UIProcess/WebPageProxy.h:
     37        * UIProcess/WebPageProxy.messages.in:
     38        * UIProcess/mac/CorrectionPanel.mm:
     39        (correctionIndicatorType):
     40        (WebKit::CorrectionPanel::handleAcceptedReplacement):
     41        * UIProcess/mac/WebPageProxyMac.mm:
     42        (WebKit::WebPageProxy::insertDictatedText):
     43        * WebProcess/WebCoreSupport/WebAlternativeTextClient.h:
     44        (WebAlternativeTextClient):
     45        * WebProcess/WebCoreSupport/mac/WebAlternativeTextClient.cpp:
     46        (WebKit::WebAlternativeTextClient::showCorrectionAlternative):
     47        (WebKit::WebAlternativeTextClient::dismissAlternative):
     48        (WebKit::WebAlternativeTextClient::dismissAlternativeSoon):
     49        (WebKit::WebAlternativeTextClient::recordAutocorrectionResponse):
     50        (WebKit::WebAlternativeTextClient::removeDictationAlternatives):
     51        (WebKit::WebAlternativeTextClient::showDictationAlternativeUI):
     52        (WebKit::WebAlternativeTextClient::dismissDictationAlternativeUI):
     53        (WebKit::WebAlternativeTextClient::dictationAlternatives):
     54        * WebProcess/WebPage/WebPage.h:
     55        * WebProcess/WebPage/WebPage.messages.in:
     56        * WebProcess/WebPage/mac/WebPageMac.mm:
     57        (WebKit::WebPage::insertDictatedText):
     58
    1592012-06-13  Andreas Kling  <kling@webkit.org>
    260
  • trunk/Source/WebKit2/Shared/API/c/WKContextMenuItemTypes.h

    r95901 r120357  
    8989    kWKContextMenuItemTagPDFSinglePageScrolling,
    9090    kWKContextMenuItemTagPDFFacingPagesScrolling,
     91    kWKContextMenuItemTagDictationAlternative,
    9192    kWKContextMenuItemTagInspectElement,
    9293    kWKContextMenuItemTagTextDirectionMenu,
  • trunk/Source/WebKit2/Shared/API/c/WKSharedAPICast.h

    r105855 r120357  
    415415    case WebCore::ContextMenuItemTagPDFFacingPagesScrolling:
    416416        return kWKContextMenuItemTagPDFFacingPagesScrolling;
     417    case WebCore::ContextMenuItemTagDictationAlternative:
     418        return kWKContextMenuItemTagDictationAlternative;
    417419#if ENABLE(INSPECTOR)
    418420    case WebCore::ContextMenuItemTagInspectElement:
     
    593595    case kWKContextMenuItemTagPDFFacingPagesScrolling:
    594596        return WebCore::ContextMenuItemTagPDFFacingPagesScrolling;
     597    case kWKContextMenuItemTagDictationAlternative:
     598        return WebCore::ContextMenuItemTagDictationAlternative;
    595599#if ENABLE(INSPECTOR)
    596600    case kWKContextMenuItemTagInspectElement:
  • trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.cpp

    r118697 r120357  
    3232#include <WebCore/Cursor.h>
    3333#include <WebCore/DatabaseDetails.h>
     34#include <WebCore/DictationAlternative.h>
    3435#include <WebCore/DragSession.h>
    3536#include <WebCore/Editor.h>
     
    526527}
    527528
     529void ArgumentCoder<DictationAlternative>::encode(ArgumentEncoder* encoder, const DictationAlternative& dictationAlternative)
     530{
     531    encoder->encode(dictationAlternative.rangeStart);
     532    encoder->encode(dictationAlternative.rangeLength);
     533    encoder->encode(dictationAlternative.dictationContext);
     534}
     535
     536bool ArgumentCoder<DictationAlternative>::decode(ArgumentDecoder* decoder, DictationAlternative& dictationAlternative)
     537{
     538    if (!decoder->decode(dictationAlternative.rangeStart))
     539        return false;
     540    if (!decoder->decode(dictationAlternative.rangeLength))
     541        return false;
     542    if (!decoder->decode(dictationAlternative.dictationContext))
     543        return false;
     544    return true;
     545}
     546
    528547
    529548void ArgumentCoder<FileChooserSettings>::encode(ArgumentEncoder* encoder, const FileChooserSettings& settings)
  • trunk/Source/WebKit2/Shared/WebCoreArgumentCoders.h

    r118697 r120357  
    5151    class ResourceResponse;
    5252    struct CompositionUnderline;
     53    struct DictationAlternative;
    5354    struct DragSession;
    5455    struct FileChooserSettings;
     
    210211};
    211212
     213template<> struct ArgumentCoder<WebCore::DictationAlternative> {
     214    static void encode(ArgumentEncoder*, const WebCore::DictationAlternative&);
     215    static bool decode(ArgumentDecoder*, WebCore::DictationAlternative&);
     216};
     217
    212218template<> struct ArgumentCoder<WebCore::FileChooserSettings> {
    213219    static void encode(ArgumentEncoder*, const WebCore::FileChooserSettings&);
  • trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h

    r120021 r120357  
    3434@class WKView;
    3535
     36namespace WebCore {
     37class AlternativeTextUIController;
     38}
     39
    3640namespace WebKit {
    37 
    3841class FindIndicatorWindow;
    3942
     
    131134    virtual WKView* wkView() const { return m_wkView; }
    132135
     136#if USE(DICTATION_ALTERNATIVES)
     137    virtual uint64_t addDictationAlternatives(const RetainPtr<NSTextAlternatives>&);
     138    virtual void removeDictationAlternatives(uint64_t dictationContext);
     139    virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext);
     140    virtual void dismissDictationAlternativeUI();
     141    virtual Vector<String> dictationAlternatives(uint64_t dictationContext);
     142#endif
     143
    133144    WKView* m_wkView;
    134145    RetainPtr<WKEditorUndoTargetObjC> m_undoTarget;
    135146#if USE(AUTOCORRECTION_PANEL)
    136147    CorrectionPanel m_correctionPanel;
     148#endif
     149#if USE(DICTATION_ALTERNATIVES)
     150    OwnPtr<WebCore::AlternativeTextUIController> m_alternativeTextUIController;
    137151#endif
    138152};
  • trunk/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm

    r120021 r120357  
    2727#import "PageClientImpl.h"
    2828
     29#if USE(DICTATION_ALTERNATIVES)
     30#import <AppKit/NSTextAlternatives.h>
     31#endif
    2932#import "ColorSpaceData.h"
    3033#import "DataReference.h"
     
    3942#import "WebEditCommandProxy.h"
    4043#import "WebPopupMenuProxyMac.h"
     44#import <WebCore/AlternativeTextUIController.h>
    4145#import <WebCore/BitmapImage.h>
    4246#import <WebCore/Cursor.h>
     
    124128    : m_wkView(wkView)
    125129    , m_undoTarget(AdoptNS, [[WKEditorUndoTargetObjC alloc] init])
     130#if USE(DICTATION_ALTERNATIVES)
     131    , m_alternativeTextUIController(adoptPtr(new AlternativeTextUIController))
     132#endif
    126133{
    127134}
     
    216223    [m_wkView _processDidCrash];
    217224}
    218    
     225
    219226void PageClientImpl::pageClosed()
    220227{
    221228    [m_wkView _pageClosed];
     229#if USE(DICTATION_ALTERNATIVES)
     230    m_alternativeTextUIController->clear();
     231#endif
    222232}
    223233
     
    536546}
    537547
     548#if USE(DICTATION_ALTERNATIVES)
     549uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr<NSTextAlternatives>& alternatives)
     550{
     551    return m_alternativeTextUIController->addAlternatives(alternatives);
     552}
     553
     554void PageClientImpl::removeDictationAlternatives(uint64_t dictationContext)
     555{
     556    m_alternativeTextUIController->removeAlternatives(dictationContext);
     557}
     558
     559void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
     560{
     561    if (!isViewVisible() || !isViewInWindow())
     562        return;
     563    m_alternativeTextUIController->showAlternatives(m_wkView, boundingBoxOfDictatedText, dictationContext, ^(NSString* acceptedAlternative){
     564        [m_wkView handleAcceptedAlternativeText:acceptedAlternative];
     565    });
     566}
     567
     568Vector<String> PageClientImpl::dictationAlternatives(uint64_t dictationContext)
     569{
     570    return m_alternativeTextUIController->alternativesForContext(dictationContext);
     571}
     572
     573void PageClientImpl::dismissDictationAlternativeUI()
     574{
     575    m_alternativeTextUIController->dismissAlternatives();
     576}
     577#endif
     578
    538579} // namespace WebKit
  • trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm

    r120021 r120357  
    2626#import "config.h"
    2727#import "WKView.h"
     28
     29#if USE(DICTATION_ALTERNATIVES)
     30#import <AppKit/NSTextAlternatives.h>
     31#import <AppKit/NSAttributedString.h>
     32#endif
    2833
    2934#import "AttributedString.h"
     
    7580#import <WebCore/RunLoop.h>
    7681#import <WebCore/SharedBuffer.h>
     82#import <WebCore/TextAlternativeWithRange.h>
    7783#import <WebCore/WebCoreNSStringExtras.h>
    7884#import <WebCore/FileSystem.h>
     
    11781184    bool isFromInputMethod = _data->_page->editorState().hasComposition;
    11791185
     1186    Vector<TextAlternativeWithRange> dictationAlternatives;
     1187
    11801188    if (isAttributedString) {
     1189#if USE(DICTATION_ALTERNATIVES)
     1190        collectDictationTextAlternatives(string, dictationAlternatives);
     1191#endif
    11811192        // FIXME: We ignore most attributes from the string, so for example inserting from Character Palette loses font and glyph variation data.
    11821193        text = [string string];
     
    12001211    String eventText = text;
    12011212    eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore
    1202     bool eventHandled = _data->_page->insertText(eventText, replacementRange.location, NSMaxRange(replacementRange));
     1213    bool eventHandled;
     1214    if (!dictationAlternatives.isEmpty())
     1215        eventHandled = _data->_page->insertDictatedText(eventText, replacementRange.location, NSMaxRange(replacementRange), dictationAlternatives);
     1216    else
     1217        eventHandled = _data->_page->insertText(eventText, replacementRange.location, NSMaxRange(replacementRange));
    12031218
    12041219    if (parameters)
     
    14521467        validAttributes = [[NSArray alloc] initWithObjects:
    14531468                           NSUnderlineStyleAttributeName, NSUnderlineColorAttributeName,
    1454                            NSMarkedClauseSegmentAttributeName, nil];
     1469                           NSMarkedClauseSegmentAttributeName,
     1470#if USE(DICTATION_ALTERNATIVES)
     1471                           NSTextAlternativesAttributeName,
     1472#endif
     1473                           nil];
    14551474        // NSText also supports the following attributes, but it's
    14561475        // hard to tell which are really required for text input to
     
    29072926}
    29082927
    2909 - (void)handleCorrectionPanelResult:(NSString*)result
    2910 {
    2911     _data->_page->handleAlternativeTextUIResult(result);
     2928- (void)handleAcceptedAlternativeText:(NSString*)text
     2929{
     2930    _data->_page->handleAlternativeTextUIResult(text);
    29122931}
    29132932
  • trunk/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h

    r120021 r120357  
    100100
    101101- (NSInteger)spellCheckerDocumentTag;
    102 - (void)handleCorrectionPanelResult:(NSString*)result;
     102- (void)handleAcceptedAlternativeText:(NSString*)text;
     103
    103104@end
  • trunk/Source/WebKit2/UIProcess/PageClient.h

    r120021 r120357  
    3939#if USE(APPKIT)
    4040OBJC_CLASS WKView;
     41OBJC_CLASS NSTextAlternatives;
    4142#endif
    4243#endif
     
    202203#if USE(APPKIT)
    203204    virtual WKView* wkView() const = 0;
    204 #endif
    205 #endif
     205#if USE(DICTATION_ALTERNATIVES)
     206    virtual uint64_t addDictationAlternatives(const RetainPtr<NSTextAlternatives>&) = 0;
     207    virtual void removeDictationAlternatives(uint64_t dictationContext) = 0;
     208    virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext) = 0;
     209    virtual void dismissDictationAlternativeUI() = 0;
     210    virtual Vector<String> dictationAlternatives(uint64_t dictationContext) = 0;
     211#endif // USE(DICTATION_ALTERNATIVES)
     212#endif // USE(APPKIT)
     213#endif // PLATFORM(MAC)
    206214
    207215    virtual void didChangeScrollbarsForMainFrame() const = 0;
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp

    r120301 r120357  
    38413841#endif
    38423842}
     3843
     3844#if USE(DICTATION_ALTERNATIVES)
     3845void WebPageProxy::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
     3846{
     3847    m_pageClient->showDictationAlternativeUI(boundingBoxOfDictatedText, dictationContext);
     3848}
     3849
     3850void WebPageProxy::dismissDictationAlternativeUI()
     3851{
     3852    m_pageClient->dismissDictationAlternativeUI();
     3853}
     3854
     3855void WebPageProxy::removeDictationAlternatives(uint64_t dictationContext)
     3856{
     3857    m_pageClient->removeDictationAlternatives(dictationContext);
     3858}
     3859
     3860void WebPageProxy::dictationAlternatives(uint64_t dictationContext, Vector<String>& result)
     3861{
     3862    result = m_pageClient->dictationAlternatives(dictationContext);
     3863}
     3864#endif
     3865
    38433866#endif // PLATFORM(MAC)
    38443867
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r120301 r120357  
    5959#include "WebResourceLoadClient.h"
    6060#include "WebUIClient.h"
     61#include <WebCore/AlternativeTextClient.h>
     62#include <WebCore/DragActions.h>
     63#include <WebCore/DragSession.h>
    6164#include <WebCore/HitTestResult.h>
    6265#include <WebCore/Page.h>
     
    9699    class ProtectionSpace;
    97100    struct FileChooserSettings;
     101    struct TextAlternativeWithRange;
    98102    struct TextCheckingResult;
    99103    struct ViewportAttributes;
     
    362366    void cancelComposition();
    363367    bool insertText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd);
     368    bool insertDictatedText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, const Vector<WebCore::TextAlternativeWithRange>& dictationAlternatives);
    364369    void getMarkedRange(uint64_t& location, uint64_t& length);
    365370    void getSelectedRange(uint64_t& location, uint64_t& length);
     
    922927    void recordAutocorrectionResponse(int32_t responseType, const String& replacedString, const String& replacementString);
    923928#endif // !defined(BUILDING_ON_SNOW_LEOPARD)
     929
     930#if USE(DICTATION_ALTERNATIVES)
     931    void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext);
     932    void dismissDictationAlternativeUI();
     933    void removeDictationAlternatives(uint64_t dictationContext);
     934    void dictationAlternatives(uint64_t dictationContext, Vector<String>& result);
     935#endif
    924936#endif // PLATFORM(MAC)
    925937
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in

    r120301 r120357  
    290290#endif
    291291
     292#if USE(DICTATION_ALTERNATIVES)
     293    ShowDictationAlternativeUI(WebCore::FloatRect boundingBoxOfDictatedText, uint64_t dictationContext)
     294    DismissDictationAlternativeUI()
     295    RemoveDictationAlternatives(uint64_t dictationContext)
     296    DictationAlternatives(uint64_t dictationContext) -> (Vector<String> alternatives)
     297#endif
     298
    292299#if PLATFORM(WIN)
    293300    # Windows 7 Gesture Messages
  • trunk/Source/WebKit2/UIProcess/mac/CorrectionPanel.mm

    r119349 r120357  
    4444    case AlternativeTextTypeSpellingSuggestions:
    4545        return NSCorrectionIndicatorTypeGuesses;
     46    case AlternativeTextTypeDictationAlternatives:
     47        ASSERT_NOT_REACHED();
     48        break;
    4649    }
    4750    ASSERT_NOT_REACHED();
     
    139142    }
    140143
    141     [m_view.get() handleCorrectionPanelResult:acceptedReplacement];
     144    [m_view.get() handleAcceptedAlternativeText:acceptedReplacement];
    142145    m_view.clear();
    143146    if (acceptedReplacement)
  • trunk/Source/WebKit2/UIProcess/mac/WebPageProxyMac.mm

    r120021 r120357  
    4040#import "WebPageMessages.h"
    4141#import "WebProcessProxy.h"
     42#import <WebCore/DictationAlternative.h>
    4243#import <WebCore/SharedBuffer.h>
     44#import <WebCore/TextAlternativeWithRange.h>
    4345#import <WebKitSystemInterface.h>
    4446#import <wtf/text/StringConcatenate.h>
     
    200202}
    201203
     204bool WebPageProxy::insertDictatedText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, const Vector<TextAlternativeWithRange>& dictationAlternativesWithRange)
     205{
     206#if USE(DICTATION_ALTERNATIVES)
     207    if (dictationAlternativesWithRange.isEmpty())
     208        return insertText(text, replacementRangeStart, replacementRangeEnd);
     209
     210    if (!isValid())
     211        return true;
     212
     213    Vector<DictationAlternative> dictationAlternatives;
     214
     215    for (size_t i = 0; i < dictationAlternativesWithRange.size(); ++i) {
     216        const TextAlternativeWithRange& alternativeWithRange = dictationAlternativesWithRange[i];
     217        uint64_t dictationContext = m_pageClient->addDictationAlternatives(alternativeWithRange.alternatives);
     218        if (dictationContext)
     219            dictationAlternatives.append(DictationAlternative(alternativeWithRange.range.location, alternativeWithRange.range.length, dictationContext));
     220    }
     221
     222    if (dictationAlternatives.isEmpty())
     223        return insertText(text, replacementRangeStart, replacementRangeEnd);
     224
     225    bool handled = true;
     226    process()->sendSync(Messages::WebPage::InsertDictatedText(text, replacementRangeStart, replacementRangeEnd, dictationAlternatives), Messages::WebPage::InsertDictatedText::Reply(handled, m_editorState), m_pageID);
     227    return handled;
     228#else
     229    return insertText(text, replacementRangeStart, replacementRangeEnd);
     230#endif
     231}
     232
    202233void WebPageProxy::getMarkedRange(uint64_t& location, uint64_t& length)
    203234{
  • trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebAlternativeTextClient.h

    r115369 r120357  
    3939    virtual ~WebAlternativeTextClient();
    4040    virtual void pageDestroyed() OVERRIDE;
     41#if USE(AUTOCORRECTION_PANEL)
    4142    virtual void showCorrectionAlternative(WebCore::AlternativeTextType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) OVERRIDE;
    4243    virtual void dismissAlternative(WebCore::ReasonForDismissingAlternativeText) OVERRIDE;
    4344    virtual String dismissAlternativeSoon(WebCore::ReasonForDismissingAlternativeText) OVERRIDE;
    4445    virtual void recordAutocorrectionResponse(WebCore::AutocorrectionResponseType, const String& replacedString, const String& replacementString) OVERRIDE;
     46#endif
     47#if USE(DICTATION_ALTERNATIVES)
     48    virtual void showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext) OVERRIDE;
     49    virtual void dismissDictationAlternativeUI() OVERRIDE;
     50    virtual void removeDictationAlternatives(uint64_t dictationContext) OVERRIDE;
     51    virtual Vector<String> dictationAlternatives(uint64_t dictationContext) OVERRIDE;
     52#endif
    4553private:
    4654    WebPage *m_page;
  • trunk/Source/WebKit2/WebProcess/WebCoreSupport/mac/WebAlternativeTextClient.cpp

    r115369 r120357  
    5252}
    5353
     54#if USE(AUTOCORRECTION_PANEL)
    5455void WebAlternativeTextClient::showCorrectionAlternative(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
    5556{
    56 #if USE(AUTOCORRECTION_PANEL)
    5757    m_page->send(Messages::WebPageProxy::ShowCorrectionPanel(type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings));
    58 #endif
    5958}
    6059
    6160void WebAlternativeTextClient::dismissAlternative(ReasonForDismissingAlternativeText reason)
    6261{
    63 #if USE(AUTOCORRECTION_PANEL)
    6462    m_page->send(Messages::WebPageProxy::DismissCorrectionPanel(reason));
    65 #endif
    6663}
    6764
     
    6966{
    7067    String result;
    71 #if USE(AUTOCORRECTION_PANEL)
    7268    m_page->sendSync(Messages::WebPageProxy::DismissCorrectionPanelSoon(reason), Messages::WebPageProxy::DismissCorrectionPanelSoon::Reply(result));
    73 #endif
    7469    return result;
    7570}
     
    7772void WebAlternativeTextClient::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
    7873{
    79 #if USE(AUTOCORRECTION_PANEL)
    8074    m_page->send(Messages::WebPageProxy::RecordAutocorrectionResponse(responseType, replacedString, replacementString));
     75}
     76#endif
     77
     78#if USE(DICTATION_ALTERNATIVES)
     79void WebAlternativeTextClient::removeDictationAlternatives(uint64_t dictationContext)
     80{
     81    m_page->send(Messages::WebPageProxy::RemoveDictationAlternatives(dictationContext));
     82}
     83
     84void WebAlternativeTextClient::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
     85{
     86    m_page->send(Messages::WebPageProxy::ShowDictationAlternativeUI(boundingBoxOfDictatedText, dictationContext));
     87}
     88
     89void WebAlternativeTextClient::dismissDictationAlternativeUI()
     90{
     91    m_page->send(Messages::WebPageProxy::DismissDictationAlternativeUI());
     92}
     93
     94Vector<String> WebAlternativeTextClient::dictationAlternatives(uint64_t dictationContext)
     95{
     96    Vector<String> result;
     97    m_page->sendSync(Messages::WebPageProxy::DictationAlternatives(dictationContext), Messages::WebPageProxy::DictationAlternatives::Reply(result));
     98    return result;
     99}
    81100#endif
    82101}
    83 
    84 }
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h

    r120262 r120357  
    4949#include "ShareableBitmap.h"
    5050#include "WebUndoStep.h"
     51#include <WebCore/DictationAlternative.h>
    5152#include <WebCore/DragData.h>
    5253#include <WebCore/Editor.h>
     
    420421    void acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent&, bool& result);
    421422    bool performNonEditingBehaviorForSelector(const String&);
    422 
     423    void insertDictatedText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations, bool& handled, EditorState& newState);
    423424#elif PLATFORM(WIN)
    424425    void confirmComposition(const String& compositionString);
     
    508509    void unmarkAllMisspellings();
    509510    void unmarkAllBadGrammar();
    510 
    511511#if PLATFORM(MAC) && !defined(BUILDING_ON_SNOW_LEOPARD)
    512512    void handleAlternativeTextUIResult(const String&);
  • trunk/Source/WebKit2/WebProcess/WebPage/WebPage.messages.in

    r120262 r120357  
    251251    ShouldDelayWindowOrderingEvent(WebKit::WebMouseEvent event) -> (bool result)
    252252    AcceptsFirstMouse(int eventNumber, WebKit::WebMouseEvent event) -> (bool result)
     253    InsertDictatedText(WTF::String text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, WTF::Vector<WebCore::DictationAlternative> dictationAlternatives) -> (bool handled, WebKit::EditorState newState)
    253254#endif
    254255#if PLATFORM(WIN)
  • trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm

    r117695 r120357  
    291291}
    292292
     293void WebPage::insertDictatedText(const String& text, uint64_t replacementRangeStart, uint64_t replacementRangeEnd, const Vector<WebCore::DictationAlternative>& dictationAlternativeLocations, bool& handled, EditorState& newState)
     294{
     295    Frame* frame = m_page->focusController()->focusedOrMainFrame();
     296
     297    if (replacementRangeStart != NSNotFound) {
     298        RefPtr<Range> replacementRange = convertToRange(frame, NSMakeRange(replacementRangeStart, replacementRangeEnd - replacementRangeStart));
     299        if (replacementRange)
     300            frame->selection()->setSelection(VisibleSelection(replacementRange.get(), SEL_DEFAULT_AFFINITY));
     301    }
     302
     303    ASSERT(!frame->editor()->hasComposition());
     304    handled = frame->editor()->insertDictatedText(text, dictationAlternativeLocations, m_keyboardEventBeingInterpreted);
     305    newState = editorState();
     306}
     307
    293308void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
    294309{
  • trunk/Tools/ChangeLog

    r120355 r120357  
     12012-06-14  Jia Pu  <jpu@apple.com>
     2
     3        Mark text with text alternative with blue underline.
     4        https://bugs.webkit.org/show_bug.cgi?id=83047
     5
     6        Reviewed by NOBODY Enrica Casucci.
     7
     8        * DumpRenderTree/mac/TextInputController.m:
     9        (+[TextInputController isSelectorExcludedFromWebScript:]):
     10        (+[TextInputController webScriptNameForSelector:]):
     11        (-[TextInputController dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:]):
     12
    1132012-06-14  Sheriff Bot  <webkit.review.bot@gmail.com>
    214
  • trunk/Tools/DumpRenderTree/mac/TextInputController.m

    r69952 r120357  
    3232#import "DumpRenderTreeMac.h"
    3333#import <AppKit/NSInputManager.h>
     34#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
     35#define SUPPORT_DICTATION_ALTERNATIVES
     36#import <AppKit/NSTextAlternatives.h>
     37#endif
    3438#import <WebKit/WebDocument.h>
    3539#import <WebKit/WebFrame.h>
     
    171175            || aSelector == @selector(validAttributesForMarkedText)
    172176            || aSelector == @selector(attributedStringWithString:)
    173             || aSelector == @selector(setInputMethodHandler:))
     177            || aSelector == @selector(setInputMethodHandler:)
     178            || aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:))
    174179        return NO;
    175180    return YES;
     
    195200        return @"makeAttributedString"; // just a factory method, doesn't call into NSTextInput
    196201    else if (aSelector == @selector(setInputMethodHandler:))
    197         return @"setInputMethodHandler";
     202        return @"setInputMethodHandler";
     203    else if (aSelector == @selector(dictatedStringWithPrimaryString:alternative:alternativeOffset:alternativeLength:))
     204        return @"makeDictatedString";
    198205
    199206    return nil;
     
    374381{
    375382    return [[[NSMutableAttributedString alloc] initWithString:aString] autorelease];
     383}
     384
     385- (NSMutableAttributedString*)dictatedStringWithPrimaryString:(NSString*)aString alternative:(NSString*)alternative alternativeOffset:(int)offset alternativeLength:(int)length
     386{
     387#if defined(SUPPORT_DICTATION_ALTERNATIVES)
     388    NSMutableAttributedString* dictatedString = [self attributedStringWithString:aString];
     389    NSRange rangeWithAlternative = NSMakeRange((NSUInteger)offset, (NSUInteger)length);
     390    NSString* subStringWithAlternative = [aString substringWithRange:rangeWithAlternative];
     391    if (!subStringWithAlternative)
     392        return nil;
     393
     394    NSTextAlternatives* alternativeObject = [[[NSTextAlternatives alloc] initWithPrimaryString:subStringWithAlternative alternativeStrings:[NSArray arrayWithObject:alternative]] autorelease];
     395    if (!alternativeObject)
     396        return nil;
     397
     398    [dictatedString addAttribute:NSTextAlternativesAttributeName value:alternativeObject range:rangeWithAlternative];
     399
     400    return dictatedString;
     401#else
     402    return nil;
     403#endif
    376404}
    377405
Note: See TracChangeset for help on using the changeset viewer.