2010-12-23 Darin Adler <darin@apple.com>
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Dec 2010 22:34:52 +0000 (22:34 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Dec 2010 22:34:52 +0000 (22:34 +0000)
        Reviewed by Sam Weinig.

        WKView should not try to do asynchronous validation for selectors that are not editor commands
        https://bugs.webkit.org/show_bug.cgi?id=51555

        * UIProcess/API/mac/WKView.mm:
        (-[WKView validateUserInterfaceItem:]): Removed the special case for startSpeaking.
        Added call to commandIsSupportedFromMenuOrKeyBinding so we only try to do validation
        for commands that are supported. Tweaked comments and added some bug numbers.
        (-[WKView _setUserInterfaceItemState:enabled:state:]): Tweaked comment and added
        bug number.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@74582 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
WebKit2/ChangeLog
WebKit2/Shared/SelectionState.h [new file with mode: 0644]
WebKit2/UIProcess/API/mac/PageClientImpl.h
WebKit2/UIProcess/API/mac/PageClientImpl.mm
WebKit2/UIProcess/API/mac/WKView.mm
WebKit2/UIProcess/API/mac/WKViewInternal.h
WebKit2/UIProcess/PageClient.h
WebKit2/UIProcess/WebPageProxy.cpp
WebKit2/UIProcess/WebPageProxy.h
WebKit2/UIProcess/WebPageProxy.messages.in
WebKit2/UIProcess/win/WebView.cpp
WebKit2/UIProcess/win/WebView.h
WebKit2/WebKit2.xcodeproj/project.pbxproj
WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
WebKit2/WebProcess/WebCoreSupport/mac/WebEditorClientMac.mm
WebKit2/WebProcess/WebPage/WebPage.cpp
WebKit2/WebProcess/WebPage/WebPage.h
WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
WebKit2/win/WebKit2.vcproj

index c96a4df..d7f9a6c 100644 (file)
 
 2010-12-23  Anders Carlsson  <andersca@apple.com>
 
+        Reviewed by Darin Adler.
+
+        Clean up the selection handling code
+        https://bugs.webkit.org/show_bug.cgi?id=51550
+
+        * Shared/SelectionState.h: Added.
+        Add SelectionState class which hold information about the current selection.
+
+        * UIProcess/API/mac/PageClientImpl.h:
+        * UIProcess/API/mac/PageClientImpl.mm:
+        Remove selectionChanged function.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView initWithFrame:contextRef:pageGroupRef:]):
+        Remove all the selection related state; it lives in the WebPageProxy object now.
+        
+        (-[WKView insertText:]):
+        (-[WKView selectedRange]):
+        (-[WKView hasMarkedText]):
+        Get the selection information from the WebPageProxy.
+
+        * UIProcess/API/mac/WKViewInternal.h:
+        Remove _selectionChanged declaration.
+
+        * UIProcess/PageClient.h:
+        Remove selectionChanged functions.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::selectionStateChanged):
+        Update the selection state.
+
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::selectionState):
+        Return the selection state.
+
+        * UIProcess/WebPageProxy.messages.in:
+        Add SelectionStateChanged message.
+
+        * UIProcess/win/WebView.cpp:
+        (WebKit::WebView::WebView):
+        Remove all the selection related state; it lives in the WebPageProxy object now.
+
+        (WebKit::WebView::compositionSelectionChanged):
+        (WebKit::WebView::onIMEComposition):
+        (WebKit::WebView::onIMEEndComposition):
+        (WebKit::WebView::onIMERequestCharPosition):
+        (WebKit::WebView::onIMERequest):
+        Get the selection information from the WebPageProxy.
+        
+        * WebKit2.xcodeproj/project.pbxproj:
+        Add SelectionState.h
+
+        * WebProcess/WebCoreSupport/WebEditorClient.cpp:
+        (WebKit::WebEditorClient::respondToChangedSelection):
+        Send a SelectionStateChanged message with the updated state.
+
+        * WebProcess/WebCoreSupport/mac/WebEditorClientMac.mm:
+        Remove mac specific code.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::getLocationAndLengthFromRange):
+        Rename this function from convertRangeToPlatformRange and move it out of WebPageMac.mm
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::getMarkedRange):
+        (WebKit::WebPage::characterIndexForPoint):
+        Call getLocationAndLengthFromRange.
+
+        * win/WebKit2.vcproj:
+        Add SelectionState.h
+
+2010-12-23  Anders Carlsson  <andersca@apple.com>
+
         Reviewed by Sam Weinig.
 
         New popup windows open disproportionately big
diff --git a/WebKit2/Shared/SelectionState.h b/WebKit2/Shared/SelectionState.h
new file mode 100644 (file)
index 0000000..2ce0e9c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SelectionState_h
+#define SelectionState_h
+
+#include "ArgumentCoders.h"
+#include <wtf/NotFound.h>
+
+namespace WebKit {
+
+struct SelectionState {
+    SelectionState()
+        : isNone(true)
+        , isContentEditable(false)
+        , isInPasswordField(false)
+        , hasComposition(false)
+        , selectedRangeStart(notFound)
+        , selectedRangeLength(0)
+    {
+    }
+
+    // Whether there is a selection at all. This will be false when there is a caret selection.
+    bool isNone;
+
+    // Whether the selection is in a content editable area.
+    bool isContentEditable;
+
+    // Whether the selection is in a password field.
+    bool isInPasswordField;
+
+    // Whether the selection has a composition.
+    bool hasComposition;
+
+    // The start of the selected range.
+    uint64_t selectedRangeStart;
+    
+    // The length of the selected range.
+    uint64_t selectedRangeLength;
+};
+
+} // namespace WebKit
+
+namespace CoreIPC {
+template<> struct ArgumentCoder<WebKit::SelectionState> : SimpleArgumentCoder<WebKit::SelectionState> { };
+};
+
+#endif // SelectionState_h
index d4e9133..78a9016 100644 (file)
@@ -64,7 +64,6 @@ private:
     virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&);
 
     virtual void didNotHandleKeyEvent(const NativeWebKeyboardEvent&);
-    virtual void selectionChanged(bool, bool, bool, bool, uint64_t, uint64_t);
 
     virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*);
     virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*);
index fe14b76..715ed7e 100644 (file)
@@ -147,11 +147,6 @@ void PageClientImpl::setViewportArguments(const WebCore::ViewportArguments&)
 
 }
 
-void PageClientImpl::selectionChanged(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition, uint64_t location, uint64_t length)
-{
-    [m_wkView _selectionChanged:isNone isEditable:isContentEditable isPassword:isPasswordField hasMarkedText:hasComposition range:NSMakeRange(location, length)];
-}
-
 static NSString* nameForEditAction(EditAction editAction)
 {
     // FIXME: Use localized strings.
index e36fea4..b09951d 100644 (file)
@@ -109,14 +109,9 @@ typedef HashMap<String, ValidationVector> ValidationMap;
     // The identifier of the plug-in we want to send complex text input to, or 0 if there is none.
     uint64_t _pluginComplexTextInputIdentifier;
 
-    BOOL _isSelectionNone;
-    BOOL _isSelectionEditable;
-    BOOL _isSelectionInPasswordField;
-    BOOL _hasMarkedText;
     Vector<CompositionUnderline> _underlines;
     unsigned _selectionStart;
     unsigned _selectionEnd;
-    NSRange _selectedRange;
 }
 @end
 
@@ -165,12 +160,6 @@ typedef HashMap<String, ValidationVector> ValidationMap;
     _data->_page->initializeWebPage(IntSize(frame.size));
     _data->_page->setIsInWindow([self window]);
 
-    _data->_isSelectionNone = YES;
-    _data->_isSelectionEditable = NO;
-    _data->_isSelectionInPasswordField = NO;
-    _data->_hasMarkedText = NO;
-    _data->_selectedRange = NSMakeRange(NSNotFound, 0);
-
     WebContext::statistics().wkViewCount++;
 
     return self;
@@ -472,7 +461,7 @@ MOUSE_EVENT_HANDLER(mouseUp)
     
     LOG(TextInput, "insertText:\"%@\"", isAttributedString ? [string string] : string);
     NSString *text;
-    bool isFromInputMethod = _data->_hasMarkedText;
+    bool isFromInputMethod = _data->_page->selectionState().hasComposition;
 
     if (isAttributedString) {
         text = [string string];
@@ -549,15 +538,6 @@ MOUSE_EVENT_HANDLER(mouseUp)
     _data->_keyDownEventBeingResent = [event retain];
 }
 
-- (void)_selectionChanged:(BOOL)isNone isEditable:(BOOL)isContentEditable isPassword:(BOOL)isPasswordField hasMarkedText:(BOOL)hasComposition range:(NSRange)newrange
-{
-    _data->_isSelectionNone = isNone;
-    _data->_isSelectionEditable = isContentEditable;
-    _data->_isSelectionInPasswordField = isPasswordField;
-    _data->_hasMarkedText = hasComposition;
-    _data->_selectedRange = newrange;
-}
-
 - (Vector<KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent 
 {
     _data->_commandsList.clear();
@@ -616,17 +596,17 @@ MOUSE_EVENT_HANDLER(mouseUp)
 
 - (NSRange)selectedRange
 {
-    if (_data->_isSelectionNone || !_data->_isSelectionEditable)
+    if (_data->_page->selectionState().isNone || !_data->_page->selectionState().isContentEditable)
         return NSMakeRange(NSNotFound, 0);
     
-    LOG(TextInput, "selectedRange -> (%u, %u)", _data->_selectedRange.location, _data->_selectedRange.length);
-    return _data->_selectedRange;
+    LOG(TextInput, "selectedRange -> (%u, %u)", _data->_page->selectionState().selectedRangeStart, _data->_page->selectionState().selectedRangeLength);
+    return NSMakeRange(_data->_page->selectionState().selectedRangeStart, _data->_page->selectionState().selectedRangeLength);
 }
 
 - (BOOL)hasMarkedText
 {
-    LOG(TextInput, "hasMarkedText -> %u", _data-> _hasMarkedText);
-    return _data->_hasMarkedText;
+    LOG(TextInput, "hasMarkedText -> %u", _data->_page->selectionState().hasComposition);
+    return _data->_page->selectionState().hasComposition;
 }
 
 - (void)unmarkText
index c348e0a..56c5b31 100644 (file)
@@ -43,8 +43,6 @@ namespace WebKit {
 - (void)_setEventBeingResent:(NSEvent *)event;
 - (NSRect)_convertToDeviceSpace:(NSRect)rect;
 - (NSRect)_convertToUserSpace:(NSRect)rect;
-- (void)_selectionChanged:(BOOL)isNone isEditable:(BOOL)isContentEditable isPassword:(BOOL)isPasswordField hasMarkedText:(BOOL)hasComposition range:(NSRange)newrange;
-
 - (void)_setFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator fadeOut:(BOOL)fadeOut;
 
 #if USE(ACCELERATED_COMPOSITING)
index b6bbf80..553ea0f 100644 (file)
@@ -70,9 +70,6 @@ public:
     virtual void setEditCommandState(const String& commandName, bool isEnabled, int state) = 0;
 #if PLATFORM(MAC)
     virtual void interceptKeyEvent(const NativeWebKeyboardEvent&, Vector<WebCore::KeypressCommand>&, uint32_t, uint32_t, Vector<WebCore::CompositionUnderline>&) = 0;
-    virtual void selectionChanged(bool, bool, bool, bool, uint64_t, uint64_t) = 0;
-#else
-    virtual void selectionChanged(bool, bool, bool, bool) = 0;
 #endif
 #if PLATFORM(WIN)
     virtual void compositionSelectionChanged(bool) = 0;
index aa233c9..cd26b24 100644 (file)
@@ -1552,13 +1552,12 @@ void WebPageProxy::backForwardForwardListCount(int32_t& count)
     count = m_backForwardList->forwardListCount();
 }
 
-#if PLATFORM(MAC)
-// Selection change support
-void WebPageProxy::didSelectionChange(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition, uint64_t location, uint64_t length)
+void WebPageProxy::selectionStateChanged(const SelectionState& selectionState)
 {
-    m_pageClient->selectionChanged(isNone, isContentEditable, isPasswordField, hasComposition, location, length);
+    m_selectionState = selectionState;
 }
 
+#if PLATFORM(MAC)
 // Complex text input support for plug-ins.
 void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
 {
@@ -1567,12 +1566,6 @@ void WebPageProxy::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputI
     
     process()->send(Messages::WebPage::SendComplexTextInputToPlugin(pluginComplexTextInputIdentifier, textInput), m_pageID);
 }
-    
-#else    
-void WebPageProxy::didChangeSelection(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition)
-{
-    m_pageClient->selectionChanged(isNone, isContentEditable, isPasswordField, hasComposition);
-}
 #endif
 
 #if PLATFORM(WIN)
index 0163332..c022a5b 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "APIObject.h"
 #include "DrawingAreaProxy.h"
+#include "SelectionState.h"
 #include "SharedMemory.h"
 #include "WKBase.h"
 #include "WebContextMenuItemData.h"
@@ -171,17 +172,15 @@ public:
     void executeEditCommand(const String& commandName);
     void validateMenuItem(const String& commandName);
 
-// These are only used on Mac currently.
+    const SelectionState& selectionState() const { return m_selectionState; }
+
 #if PLATFORM(MAC)
     void updateWindowIsVisible(bool windowIsVisible);
     void windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates);
     void getMarkedRange(uint64_t& location, uint64_t& length);
     uint64_t characterIndexForPoint(const WebCore::IntPoint);
     WebCore::IntRect firstRectForCharacterRange(uint64_t, uint64_t);
-    void didSelectionChange(bool, bool, bool, bool, uint64_t, uint64_t);
     void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
-#else
-    void didChangeSelection(bool, bool, bool, bool);
 #endif
 #if PLATFORM(WIN)
     void didChangeCompositionSelection(bool);
@@ -384,6 +383,9 @@ private:
     void didFindZoomableArea(const WebCore::IntRect&);
 #endif
 
+    // Selection
+    void selectionStateChanged(const SelectionState&);
+
     // Back/Forward list management
     void backForwardAddItem(uint64_t itemID);
     void backForwardGoToItem(uint64_t itemID);
@@ -492,6 +494,8 @@ private:
 
     String m_toolTip;
 
+    SelectionState m_selectionState;
+
     // REMOVE: For demo purposes only.
     String m_urlAtProcessExit;
 
index cbecd10..e6bfee8 100644 (file)
@@ -131,12 +131,8 @@ messages -> WebPageProxy {
     ClearAllEditCommands()
     
     # Selection messages.
-#if PLATFORM(MAC)
-    DidSelectionChange(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition, uint64_t location, uint64_t length)
-#endif
-#if !PLATFORM(MAC)
-    DidChangeSelection(bool isNone, bool isContentEditable, bool isPasswordField, bool hasComposition)
-#endif
+    SelectionStateChanged(WebKit::SelectionState selectionState)
+
 #if PLATFORM(WIN)
     DidChangeCompositionSelection(bool hasChanged)
 #endif
index 384a1d4..1530779 100644 (file)
@@ -225,10 +225,6 @@ WebView::WebView(RECT rect, WebContext* context, WebPageGroup* pageGroup, HWND p
     , m_overrideCursor(0)
     , m_trackingMouseLeave(false)
     , m_isBeingDestroyed(false)
-    , m_selectionIsNone(true)
-    , m_selectionIsEditable(false)
-    , m_selectionInPasswordField(false)
-    , m_hasMarkedText(false)
     , m_inIMEComposition(0)
 {
     registerWebViewWindowClass();
@@ -693,17 +689,9 @@ void WebView::setInputMethodState(bool enabled)
     Ime::ImmAssociateContextEx(m_window, 0, enabled ? IACE_DEFAULT : 0);
 }
 
-void WebView::selectionChanged(bool isNone, bool isEditable, bool isPasswordField, bool hasComposition)
-{
-    m_selectionIsNone = isNone;
-    m_selectionIsEditable = isEditable;
-    m_selectionInPasswordField = isPasswordField;
-    m_hasMarkedText = hasComposition;
-}
-
 void WebView::compositionSelectionChanged(bool hasChanged)
 {
-    if (m_hasMarkedText && !hasChanged)
+    if (m_page->selectionState().hasComposition && !hasChanged)
         resetIME();
 }
 
@@ -811,7 +799,7 @@ bool WebView::onIMEComposition(LPARAM lparam)
     if (!hInputContext)
         return true;
 
-    if (!m_selectionIsEditable)
+    if (!m_page->selectionState().isContentEditable)
         return true;
 
     prepareCandidateWindow(hInputContext);
@@ -854,7 +842,7 @@ bool WebView::onIMEEndComposition()
     LOG(TextInput, "onIMEEndComposition");
     // If the composition hasn't been confirmed yet, it needs to be cancelled.
     // This happens after deleting the last character from inline input hole.
-    if (m_hasMarkedText)
+    if (m_page->selectionState().hasComposition)
         m_page->confirmComposition(String());
 
     if (m_inIMEComposition)
@@ -865,7 +853,7 @@ bool WebView::onIMEEndComposition()
 
 LRESULT WebView::onIMERequestCharPosition(IMECHARPOSITION* charPos)
 {
-    if (charPos->dwCharPos && !m_hasMarkedText)
+    if (charPos->dwCharPos && !m_page->selectionState().hasComposition)
         return 0;
     IntRect caret = m_page->firstRectForCharacterInSelectedRange(charPos->dwCharPos);
     charPos->pt.x = caret.x();
@@ -897,7 +885,7 @@ LRESULT WebView::onIMERequestReconvertString(RECONVERTSTRING* reconvertString)
 LRESULT WebView::onIMERequest(WPARAM request, LPARAM data)
 {
     LOG(TextInput, "onIMERequest %s", imeRequestName(request).latin1().data());
-    if (!m_selectionIsEditable)
+    if (!m_page->selectionState().isContentEditable)
         return 0;
 
     switch (request) {
index 05a7e94..c7729e2 100644 (file)
@@ -117,7 +117,6 @@ private:
     virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&);
     virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&);
     virtual void didNotHandleKeyEvent(const NativeWebKeyboardEvent&);
-    virtual void selectionChanged(bool, bool, bool, bool);
     virtual void compositionSelectionChanged(bool);
     virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*);
     virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*);
@@ -151,11 +150,6 @@ private:
 
     RefPtr<WebPageProxy> m_page;
 
-    // Text input state values
-    bool m_selectionIsNone;
-    bool m_selectionIsEditable;
-    bool m_selectionInPasswordField;
-    bool m_hasMarkedText;
     unsigned m_inIMEComposition;
 };
 
index 8dc11bc..dd5dc4f 100644 (file)
                1AA1CD07100FA1BA0078DEBC /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AA1CD06100FA1BA0078DEBC /* Carbon.framework */; };
                1AA417CB12C00CCA002BE67B /* TextChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA417C912C00CCA002BE67B /* TextChecker.h */; };
                1AA417EF12C00D87002BE67B /* TextCheckerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AA417ED12C00D87002BE67B /* TextCheckerMac.mm */; };
+               1AA41AB512C02EC4002BE67B /* SelectionState.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA41AB412C02EC4002BE67B /* SelectionState.h */; };
                1AA4792312A59FD9008236C3 /* PluginProcessMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AA4792212A59FD9008236C3 /* PluginProcessMac.mm */; };
                1AA479B012A5A436008236C3 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1AA1CD06100FA1BA0078DEBC /* Carbon.framework */; };
                1AA56F2911E92BC80061B882 /* PluginController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1AA56F2811E92BC80061B882 /* PluginController.h */; };
                1AA1CD06100FA1BA0078DEBC /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
                1AA417C912C00CCA002BE67B /* TextChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextChecker.h; sourceTree = "<group>"; };
                1AA417ED12C00D87002BE67B /* TextCheckerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TextCheckerMac.mm; sourceTree = "<group>"; };
+               1AA41AB412C02EC4002BE67B /* SelectionState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectionState.h; sourceTree = "<group>"; };
                1AA4792212A59FD9008236C3 /* PluginProcessMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PluginProcessMac.mm; sourceTree = "<group>"; };
                1AA56F2811E92BC80061B882 /* PluginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PluginController.h; sourceTree = "<group>"; };
                1AA5889011EE70400061B882 /* NetscapePluginStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetscapePluginStream.h; sourceTree = "<group>"; };
                                BCC43AB9127B95DC00317F16 /* PlatformPopupMenuData.h */,
                                BC2D021612AC41CB00E732A3 /* SameDocumentNavigationType.h */,
                                1AAB4A8C1296F0A20023952F /* SandboxExtension.h */,
+                               1AA41AB412C02EC4002BE67B /* SelectionState.h */,
                                BCBD3C3A125BFA7A00D2C29F /* StringPairVector.h */,
                                BCB0B0DF12305AB100B1341E /* UserMessageCoders.h */,
                                1A0F29C9120B37160053D1B9 /* VisitedLinkTable.cpp */,
                                1A4A9F3312B844E2008FE984 /* PluginQuirks.h in Headers */,
                                BC858A2012C0357B00EDEB2E /* WebResourceLoadClient.h in Headers */,
                                1AA417CB12C00CCA002BE67B /* TextChecker.h in Headers */,
+                               1AA41AB512C02EC4002BE67B /* SelectionState.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 92feab8..c2c3a3e 100644 (file)
@@ -28,6 +28,7 @@
 #define DISABLE_NOT_IMPLEMENTED_WARNINGS 1
 #include "NotImplemented.h"
 
+#include "SelectionState.h"
 #include "WebFrameLoaderClient.h"
 #include "WebPage.h"
 #include "WebPageProxyMessages.h"
@@ -178,7 +179,6 @@ void WebEditorClient::respondToChangedContents()
     notImplemented();
 }
 
-#if !PLATFORM(MAC)
 void WebEditorClient::respondToChangedSelection()
 {
     static const String WebViewDidChangeSelectionNotification = "WebViewDidChangeSelectionNotification";
@@ -187,8 +187,18 @@ void WebEditorClient::respondToChangedSelection()
     if (!frame)
         return;
 
-    m_page->send(Messages::WebPageProxy::DidChangeSelection(frame->selection()->isNone(), frame->selection()->isContentEditable(), frame->selection()->isInPasswordField(), frame->editor()->hasComposition()));
+    SelectionState selectionState;
+    selectionState.isNone = frame->selection()->isNone();
+    selectionState.isContentEditable = frame->selection()->isContentEditable();
+    selectionState.isInPasswordField = frame->selection()->isInPasswordField();
+    selectionState.hasComposition = frame->editor()->hasComposition();
+
+    WebPage::getLocationAndLengthFromRange(frame->selection()->toNormalizedRange().get(), selectionState.selectedRangeStart, selectionState.selectedRangeLength);
+
+    m_page->send(Messages::WebPageProxy::SelectionStateChanged(selectionState));
+
 #if PLATFORM(WIN)
+    // FIXME: This should also go into the selection state.
     if (!frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange())
         return;
 
@@ -197,7 +207,6 @@ void WebEditorClient::respondToChangedSelection()
     m_page->send(Messages::WebPageProxy::DidChangeCompositionSelection(frame->editor()->getCompositionSelection(start, end)));
 #endif
 }
-#endif
     
 void WebEditorClient::didEndEditing()
 {
index 5f29b0c..51e009c 100644 (file)
@@ -51,7 +51,6 @@
 #endif
 
 using namespace WebCore;
-using namespace WTF;
 
 @interface NSAttributedString (WebNSAttributedStringDetails)
 - (DOMDocumentFragment*)_documentFromRange:(NSRange)range document:(DOMDocument*)document documentAttributes:(NSDictionary *)dict subresources:(NSArray **)subresources;
@@ -62,19 +61,6 @@ using namespace WTF;
 @end
 
 namespace WebKit {
-
-void WebEditorClient::respondToChangedSelection()
-{
-    static const String WebViewDidChangeSelectionNotification = "WebViewDidChangeSelectionNotification";
-    m_page->injectedBundleEditorClient().didChangeSelection(m_page, WebViewDidChangeSelectionNotification.impl());
-    WebCore::Frame* frame = m_page->corePage()->focusController()->focusedFrame();
-    if (!frame)
-        return;
-    uint64_t location;
-    uint64_t length;
-    WebPage::convertRangeToPlatformRange(frame, frame->selection()->toNormalizedRange().get(), location, length);
-    m_page->send(Messages::WebPageProxy::DidSelectionChange(frame->selection()->isNone(), frame->selection()->isContentEditable(), frame->selection()->isInPasswordField(), frame->editor()->hasComposition(), location, length));
-}
     
 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
 {
index 6d77dc0..42266ac 100644 (file)
@@ -76,6 +76,7 @@
 #include <WebCore/Settings.h>
 #include <WebCore/SharedBuffer.h>
 #include <WebCore/SubstituteData.h>
+#include <WebCore/TextIterator.h>
 #include <runtime/JSLock.h>
 #include <runtime/JSValue.h>
 
@@ -610,6 +611,35 @@ WebContextMenu* WebPage::contextMenu()
     return m_contextMenu.get();
 }
 
+void WebPage::getLocationAndLengthFromRange(Range* range, uint64_t& location, uint64_t& length)
+{
+    location = notFound;
+    length = 0;
+
+    if (!range || !range->startContainer())
+        return;
+
+    Element* selectionRoot = range->ownerDocument()->frame()->selection()->rootEditableElement();
+    Element* scope = selectionRoot ? selectionRoot : range->ownerDocument()->documentElement();
+    
+    // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
+    // that is not inside the current editable region.  These checks ensure we don't produce
+    // potentially invalid data when responding to such requests.
+    if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
+        return;
+    if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
+        return;
+
+    RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
+    ASSERT(testRange->startContainer() == scope);
+    location = TextIterator::rangeLength(testRange.get());
+    
+    ExceptionCode ec;
+    testRange->setEnd(range->endContainer(), range->endOffset(), ec);
+    ASSERT(testRange->startContainer() == scope);
+    length = TextIterator::rangeLength(testRange.get()) - location;
+}
+
 // Events 
 
 static const WebEvent* g_currentEvent = 0;
index 7b24691..1cf257c 100644 (file)
@@ -244,14 +244,15 @@ public:
     };
 
     SandboxExtensionTracker& sandboxExtensionTracker() { return m_sandboxExtensionTracker; }
-    
+
+    static void getLocationAndLengthFromRange(WebCore::Range*, uint64_t& location, uint64_t& length);
+
 #if PLATFORM(MAC)
     void sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput);
 
     void getMarkedRange(uint64_t& location, uint64_t& length);
     void characterIndexForPoint(const WebCore::IntPoint point, uint64_t& result);
     void firstRectForCharacterRange(uint64_t location, uint64_t length, WebCore::IntRect& resultRect);
-    static void convertRangeToPlatformRange(WebCore::Frame* frame, WebCore::Range *range, uint64_t& location, uint64_t& length);
 #elif PLATFORM(WIN)
     void confirmComposition(const String& compositionString);
     void setComposition(const WTF::String& compositionString, const WTF::Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition);
index 12c7700..25b0326 100644 (file)
@@ -123,34 +123,6 @@ bool WebPage::interceptEditingKeyboardEvent(KeyboardEvent* evt, bool shouldSaveC
     return eventWasHandled;
 }
 
-void WebPage::convertRangeToPlatformRange(WebCore::Frame* frame, WebCore::Range *range, uint64_t& location, uint64_t& length)
-{
-    location = NSNotFound;
-    length = 0;
-    if (!range || !range->startContainer())
-        return;
-        
-    Element* selectionRoot = frame->selection()->rootEditableElement();
-    Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();
-    
-    // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
-    // that is not inside the current editable region.  These checks ensure we don't produce
-    // potentially invalid data when responding to such requests.
-    if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
-        return;
-    if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
-        return;
-            
-    RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
-    ASSERT(testRange->startContainer() == scope);
-    location = TextIterator::rangeLength(testRange.get());
-            
-    ExceptionCode ec;
-    testRange->setEnd(range->endContainer(), range->endOffset(), ec);
-    ASSERT(testRange->startContainer() == scope);
-    length = TextIterator::rangeLength(testRange.get()) - location;
-}
-
 void WebPage::sendComplexTextInputToPlugin(uint64_t pluginComplexTextInputIdentifier, const String& textInput)
 {
     for (HashSet<PluginView*>::const_iterator it = m_pluginViews.begin(), end = m_pluginViews.end(); it != end; ++it) {
@@ -167,7 +139,7 @@ void WebPage::getMarkedRange(uint64_t& location, uint64_t& length)
     if (!frame)
         return;
     
-    convertRangeToPlatformRange(frame, frame->editor()->compositionRange().get(), location, length);
+    getLocationAndLengthFromRange(frame->editor()->compositionRange().get(), location, length);
 }
 
 static Range *characterRangeAtPoint(Frame* frame, const IntPoint point)
@@ -206,9 +178,11 @@ void WebPage::characterIndexForPoint(IntPoint point, uint64_t& index)
     frame = result.innerNonSharedNode() ? result.innerNonSharedNode()->document()->frame() : m_page->focusController()->focusedOrMainFrame();
     
     Range *range = characterRangeAtPoint(frame, result.point());
+    if (!range)
+        return;
+
     uint64_t length;
-    if (range)
-        convertRangeToPlatformRange(frame, range, index, length);
+    getLocationAndLengthFromRange(range, index, length);
 }
 
 static PassRefPtr<Range> convertToRange(Frame* frame, NSRange nsrange)
index a2a991a..dd43e08 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\Shared\SelectionState.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\Shared\StringPairVector.h"
                                >
                        </File>