Changeset 182603 in webkit
- Timestamp:
- Apr 9, 2015 11:31:51 AM (9 years ago)
- Location:
- trunk/Source
- Files:
-
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r182601 r182603 1 2015-04-09 Chris Dumez <cdumez@apple.com> 2 3 [WK2][iOS] editorState() should not cause a synchronous layout 4 https://bugs.webkit.org/show_bug.cgi?id=142536 5 <rdar://problem/20041506> 6 7 Reviewed by Enrica Casucci. 8 9 Add didChangeSelectionAndUpdateLayout() callback to EditorClient 10 that is called at the end of FrameSelection::updateAndRevealSelection(). 11 12 * editing/FrameSelection.cpp: 13 (WebCore::FrameSelection::updateAndRevealSelection): 14 * loader/EmptyClients.h: 15 * page/EditorClient.h: 16 1 17 2015-04-08 Anders Carlsson <andersca@apple.com> 2 18 -
trunk/Source/WebCore/editing/FrameSelection.cpp
r181166 r182603 382 382 383 383 notifyAccessibilityForSelectionChange(); 384 385 m_frame->editor().client()->didChangeSelectionAndUpdateLayout(); 384 386 } 385 387 -
trunk/Source/WebCore/loader/EmptyClients.h
r182573 r182603 447 447 virtual void respondToChangedContents() override { } 448 448 virtual void respondToChangedSelection(Frame*) override { } 449 virtual void didChangeSelectionAndUpdateLayout() override { } 449 450 virtual void discardedComposition(Frame*) override { } 450 451 virtual void didEndEditing() override { } -
trunk/Source/WebCore/page/EditorClient.h
r177152 r182603 94 94 virtual void respondToChangedContents() = 0; 95 95 virtual void respondToChangedSelection(Frame*) = 0; 96 virtual void didChangeSelectionAndUpdateLayout() = 0; 96 97 virtual void didEndEditing() = 0; 97 98 virtual void willWriteSelectionToPasteboard(Range*) = 0; -
trunk/Source/WebKit/mac/ChangeLog
r182581 r182603 1 2015-04-09 Chris Dumez <cdumez@apple.com> 2 3 [WK2][iOS] editorState() should not cause a synchronous layout 4 https://bugs.webkit.org/show_bug.cgi?id=142536 5 <rdar://problem/20041506> 6 7 Reviewed by Enrica Casucci. 8 9 Provide implementation for EditorClient::didChangeSelectionAndUpdateLayout(). 10 11 * WebCoreSupport/WebEditorClient.h: 12 1 13 2015-04-08 Brent Fulgham <bfulgham@apple.com> 2 14 -
trunk/Source/WebKit/mac/WebCoreSupport/WebEditorClient.h
r177152 r182603 111 111 virtual void respondToChangedContents() override; 112 112 virtual void respondToChangedSelection(WebCore::Frame*) override; 113 virtual void didChangeSelectionAndUpdateLayout() override { } 113 114 virtual void discardedComposition(WebCore::Frame*) override; 114 115 -
trunk/Source/WebKit/win/ChangeLog
r182573 r182603 1 2015-04-09 Chris Dumez <cdumez@apple.com> 2 3 [WK2][iOS] editorState() should not cause a synchronous layout 4 https://bugs.webkit.org/show_bug.cgi?id=142536 5 <rdar://problem/20041506> 6 7 Reviewed by Enrica Casucci. 8 9 Provide implementation for EditorClient::didChangeSelectionAndUpdateLayout(). 10 11 * WebCoreSupport/WebEditorClient.h: 12 1 13 2015-04-08 Brady Eidson <beidson@apple.com> 2 14 -
trunk/Source/WebKit/win/WebCoreSupport/WebEditorClient.h
r177152 r182603 61 61 virtual void respondToChangedContents(); 62 62 virtual void respondToChangedSelection(WebCore::Frame*); 63 virtual void didChangeSelectionAndUpdateLayout() override { } 63 64 virtual void discardedComposition(WebCore::Frame*) override; 64 65 -
trunk/Source/WebKit2/ChangeLog
r182602 r182603 1 2015-04-09 Chris Dumez <cdumez@apple.com> 2 3 [WK2][iOS] editorState() should not cause a synchronous layout 4 https://bugs.webkit.org/show_bug.cgi?id=142536 5 <rdar://problem/20041506> 6 7 Reviewed by Enrica Casucci. 8 9 platformEditorState() on iOS does a synchronous layout to compute some 10 of the EditorState members (e.g. caretRectAtStart / caretRectAtEnd). 11 This is bad for performance as this is called every time the selection 12 is changed (which happens for e.g. when you set the value of a focused 13 HTMLInputElement). 14 15 This patch updates the behavior on iOS to only send a partial EditorState 16 on selection change so that the UIProcess gets most of the information 17 (the ones that do not require style recalc or layout) ASAP. A full Editor 18 state is then sent after the asynchronous layout is done. 19 20 With this change, I see a 38% improvement on Speedometer (26.4 +/- 0.37 21 -> 36.5 +/- 0.54) on iPhone 6 Plus. 22 23 * Shared/EditorState.cpp: 24 (WebKit::EditorState::encode): 25 (WebKit::EditorState::decode): 26 (WebKit::EditorState::PostLayoutData::encode): 27 (WebKit::EditorState::PostLayoutData::decode): 28 * Shared/EditorState.h: 29 (WebKit::EditorState::EditorState): Deleted. 30 * UIProcess/ios/WKContentView.mm: 31 (-[WKContentView _didCommitLayerTree:]): 32 * UIProcess/ios/WKContentViewInteraction.mm: 33 (WebKit::WKSelectionDrawingInfo::WKSelectionDrawingInfo): 34 (-[WKContentView webSelectionRects]): 35 (-[WKContentView _addShortcut:]): 36 (-[WKContentView selectedText]): 37 (-[WKContentView isReplaceAllowed]): 38 (-[WKContentView _promptForReplace:]): 39 (-[WKContentView _transliterateChinese:]): 40 (-[WKContentView textStylingAtPosition:inDirection:]): 41 (-[WKContentView canPerformAction:withSender:]): 42 (-[WKContentView _showDictionary:]): 43 (-[WKContentView _characterBeforeCaretSelection]): 44 (-[WKContentView _characterInRelationToCaretSelection:]): 45 (-[WKContentView _selectionAtDocumentStart]): 46 (-[WKContentView selectedTextRange]): 47 (-[WKContentView hasContent]): 48 * WebProcess/WebCoreSupport/WebEditorClient.cpp: 49 (WebKit::WebEditorClient::didChangeSelectionAndUpdateLayout): 50 * WebProcess/WebCoreSupport/WebEditorClient.h: 51 * WebProcess/WebPage/WebPage.cpp: 52 (WebKit::WebPage::editorState): 53 (WebKit::WebPage::didChangeSelection): 54 (WebKit::WebPage::sendPostLayoutEditorStateIfNeeded): 55 * WebProcess/WebPage/WebPage.h: 56 * WebProcess/WebPage/efl/WebPageEfl.cpp: 57 (WebKit::WebPage::platformEditorState): 58 * WebProcess/WebPage/gtk/WebPageGtk.cpp: 59 (WebKit::WebPage::platformEditorState): 60 * WebProcess/WebPage/ios/WebPageIOS.mm: 61 (WebKit::WebPage::platformEditorState): 62 * WebProcess/WebPage/mac/WebPageMac.mm: 63 (WebKit::WebPage::platformEditorState): 64 1 65 2015-04-09 Antti Koivisto <antti@apple.com> 2 66 -
trunk/Source/WebKit2/Shared/EditorState.cpp
r180768 r182603 42 42 encoder << isInPlugin; 43 43 encoder << hasComposition; 44 encoder << isMissingPostLayoutData; 44 45 45 46 #if PLATFORM(IOS) 46 encoder << isReplaceAllowed; 47 encoder << hasContent; 48 encoder << characterAfterSelection; 49 encoder << characterBeforeSelection; 50 encoder << twoCharacterBeforeSelection; 51 encoder << caretRectAtStart; 52 encoder << caretRectAtEnd; 53 encoder << selectionRects; 54 encoder << selectedTextLength; 55 encoder << wordAtSelection; 47 if (!isMissingPostLayoutData) 48 m_postLayoutData.encode(encoder); 49 56 50 encoder << firstMarkedRect; 57 51 encoder << lastMarkedRect; 58 52 encoder << markedText; 59 encoder << typingAttributes;60 53 #endif 61 54 … … 91 84 return false; 92 85 86 if (!decoder.decode(result.isMissingPostLayoutData)) 87 return false; 88 93 89 #if PLATFORM(IOS) 94 if (!decoder.decode(result.isReplaceAllowed)) 95 return false; 96 if (!decoder.decode(result.hasContent)) 97 return false; 98 if (!decoder.decode(result.characterAfterSelection)) 99 return false; 100 if (!decoder.decode(result.characterBeforeSelection)) 101 return false; 102 if (!decoder.decode(result.twoCharacterBeforeSelection)) 103 return false; 104 if (!decoder.decode(result.caretRectAtStart)) 105 return false; 106 if (!decoder.decode(result.caretRectAtEnd)) 107 return false; 108 if (!decoder.decode(result.selectionRects)) 109 return false; 110 if (!decoder.decode(result.selectedTextLength)) 111 return false; 112 if (!decoder.decode(result.wordAtSelection)) 113 return false; 90 if (!result.isMissingPostLayoutData) { 91 if (!PostLayoutData::decode(decoder, result.postLayoutData())) 92 return false; 93 } 94 114 95 if (!decoder.decode(result.firstMarkedRect)) 115 96 return false; … … 117 98 return false; 118 99 if (!decoder.decode(result.markedText)) 119 return false;120 if (!decoder.decode(result.typingAttributes))121 100 return false; 122 101 #endif … … 130 109 } 131 110 111 #if PLATFORM(IOS) 112 void EditorState::PostLayoutData::encode(IPC::ArgumentEncoder& encoder) const 113 { 114 encoder << selectionRects; 115 encoder << caretRectAtStart; 116 encoder << caretRectAtEnd; 117 encoder << wordAtSelection; 118 encoder << selectedTextLength; 119 encoder << characterAfterSelection; 120 encoder << characterBeforeSelection; 121 encoder << twoCharacterBeforeSelection; 122 encoder << typingAttributes; 123 encoder << isReplaceAllowed; 124 encoder << hasContent; 132 125 } 126 127 bool EditorState::PostLayoutData::decode(IPC::ArgumentDecoder& decoder, PostLayoutData& result) 128 { 129 if (!decoder.decode(result.selectionRects)) 130 return false; 131 if (!decoder.decode(result.caretRectAtStart)) 132 return false; 133 if (!decoder.decode(result.caretRectAtEnd)) 134 return false; 135 if (!decoder.decode(result.wordAtSelection)) 136 return false; 137 if (!decoder.decode(result.selectedTextLength)) 138 return false; 139 if (!decoder.decode(result.characterAfterSelection)) 140 return false; 141 if (!decoder.decode(result.characterBeforeSelection)) 142 return false; 143 if (!decoder.decode(result.twoCharacterBeforeSelection)) 144 return false; 145 if (!decoder.decode(result.typingAttributes)) 146 return false; 147 if (!decoder.decode(result.isReplaceAllowed)) 148 return false; 149 if (!decoder.decode(result.hasContent)) 150 return false; 151 152 return true; 153 } 154 #endif 155 156 } -
trunk/Source/WebKit2/Shared/EditorState.h
r180768 r182603 45 45 46 46 struct EditorState { 47 EditorState() 48 : shouldIgnoreCompositionSelectionChange(false) 49 , selectionIsNone(true) 50 , selectionIsRange(false) 51 , isContentEditable(false) 52 , isContentRichlyEditable(false) 53 , isInPasswordField(false) 54 , isInPlugin(false) 55 , hasComposition(false) 56 #if PLATFORM(IOS) 57 , isReplaceAllowed(false) 58 , hasContent(false) 59 , characterAfterSelection(0) 60 , characterBeforeSelection(0) 61 , twoCharacterBeforeSelection(0) 62 , selectedTextLength(0) 63 , typingAttributes(AttributeNone) 64 #endif 65 { 66 } 47 bool shouldIgnoreCompositionSelectionChange { false }; 67 48 68 bool shouldIgnoreCompositionSelectionChange; 69 70 bool selectionIsNone; // This will be false when there is a caret selection. 71 bool selectionIsRange; 72 bool isContentEditable; 73 bool isContentRichlyEditable; 74 bool isInPasswordField; 75 bool isInPlugin; 76 bool hasComposition; 49 bool selectionIsNone { true }; // This will be false when there is a caret selection. 50 bool selectionIsRange { false }; 51 bool isContentEditable { false }; 52 bool isContentRichlyEditable { false }; 53 bool isInPasswordField { false }; 54 bool isInPlugin { false }; 55 bool hasComposition { false }; 56 bool isMissingPostLayoutData { false }; 77 57 78 58 #if PLATFORM(IOS) 79 bool isReplaceAllowed;80 bool hasContent;81 UChar32 characterAfterSelection;82 UChar32 characterBeforeSelection;83 UChar32 twoCharacterBeforeSelection;84 WebCore::IntRect caretRectAtStart;85 WebCore::IntRect caretRectAtEnd;86 Vector<WebCore::SelectionRect> selectionRects;87 uint64_t selectedTextLength;88 String wordAtSelection;89 59 WebCore::IntRect firstMarkedRect; 90 60 WebCore::IntRect lastMarkedRect; 91 61 String markedText; 92 uint32_t typingAttributes; 62 63 struct PostLayoutData { 64 Vector<WebCore::SelectionRect> selectionRects; 65 WebCore::IntRect caretRectAtStart; 66 WebCore::IntRect caretRectAtEnd; 67 String wordAtSelection; 68 uint64_t selectedTextLength { 0 }; 69 UChar32 characterAfterSelection { 0 }; 70 UChar32 characterBeforeSelection { 0 }; 71 UChar32 twoCharacterBeforeSelection { 0 }; 72 uint32_t typingAttributes { AttributeNone }; 73 bool isReplaceAllowed { false }; 74 bool hasContent { false }; 75 76 void encode(IPC::ArgumentEncoder&) const; 77 static bool decode(IPC::ArgumentDecoder&, PostLayoutData&); 78 }; 79 80 const PostLayoutData& postLayoutData() const; 81 PostLayoutData& postLayoutData(); 93 82 #endif 94 83 … … 99 88 void encode(IPC::ArgumentEncoder&) const; 100 89 static bool decode(IPC::ArgumentDecoder&, EditorState&); 90 91 #if PLATFORM(IOS) 92 private: 93 PostLayoutData m_postLayoutData; 94 #endif 101 95 }; 96 97 #if PLATFORM(IOS) 98 inline auto EditorState::postLayoutData() -> PostLayoutData& 99 { 100 ASSERT_WITH_MESSAGE(!isMissingPostLayoutData, "Attempt to access post layout data before receiving it"); 101 return m_postLayoutData; 102 } 103 104 inline auto EditorState::postLayoutData() const -> const PostLayoutData& 105 { 106 ASSERT_WITH_MESSAGE(!isMissingPostLayoutData, "Attempt to access post layout data before receiving it"); 107 return m_postLayoutData; 108 } 109 #endif 102 110 103 111 } -
trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm
r180539 r182603 491 491 } 492 492 493 [self _updateChangedSelection]; 493 // Updating the selection requires a full editor state. If the editor state is missing post layout 494 // data then it means there is a layout pending and we're going to be called again after the layout 495 // so we delay the selection update. 496 if (!_page->editorState().isMissingPostLayoutData) 497 [self _updateChangedSelection]; 494 498 } 495 499 -
trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
r182126 r182603 86 86 87 87 type = SelectionType::Range; 88 caretRect = editorState.caretRectAtEnd; 89 selectionRects = editorState.selectionRects; 88 auto& postLayoutData = editorState.postLayoutData(); 89 caretRect = postLayoutData.caretRectAtEnd; 90 selectionRects = postLayoutData.selectionRects; 90 91 } 91 92 … … 987 988 - (NSArray *)webSelectionRects 988 989 { 989 unsigned size = _page->editorState().selectionRects.size(); 990 const auto& selectionRects = _page->editorState().postLayoutData().selectionRects; 991 unsigned size = selectionRects.size(); 990 992 if (!size) 991 993 return nil; … … 993 995 NSMutableArray *webRects = [NSMutableArray arrayWithCapacity:size]; 994 996 for (unsigned i = 0; i < size; i++) { 995 const WebCore::SelectionRect& coreRect = _page->editorState().selectionRects[i];997 const WebCore::SelectionRect& coreRect = selectionRects[i]; 996 998 WebSelectionRect *webRect = [WebSelectionRect selectionRect]; 997 999 webRect.rect = coreRect.rect(); … … 1278 1280 { 1279 1281 if (_textSelectionAssistant && [_textSelectionAssistant respondsToSelector:@selector(showTextServiceFor:fromRect:)]) 1280 [_textSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState(). selectionRects[0].rect()];1282 [_textSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState().postLayoutData().selectionRects[0].rect()]; 1281 1283 else if (_webSelectionAssistant && [_webSelectionAssistant respondsToSelector:@selector(showTextServiceFor:fromRect:)]) 1282 [_webSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState(). selectionRects[0].rect()];1284 [_webSelectionAssistant showTextServiceFor:[self selectedText] fromRect:_page->editorState().postLayoutData().selectionRects[0].rect()]; 1283 1285 } 1284 1286 1285 1287 - (NSString *)selectedText 1286 1288 { 1287 return (NSString *)_page->editorState(). wordAtSelection;1289 return (NSString *)_page->editorState().postLayoutData().wordAtSelection; 1288 1290 } 1289 1291 1290 1292 - (BOOL)isReplaceAllowed 1291 1293 { 1292 return _page->editorState(). isReplaceAllowed;1294 return _page->editorState().postLayoutData().isReplaceAllowed; 1293 1295 } 1294 1296 … … 1305 1307 - (void)_promptForReplace:(id)sender 1306 1308 { 1307 if (_page->editorState().wordAtSelection.isEmpty()) 1309 const auto& wordAtSelection = _page->editorState().postLayoutData().wordAtSelection; 1310 if (wordAtSelection.isEmpty()) 1308 1311 return; 1309 1312 1310 1313 if ([_textSelectionAssistant respondsToSelector:@selector(scheduleReplacementsForText:)]) 1311 [_textSelectionAssistant scheduleReplacementsForText: _page->editorState().wordAtSelection];1314 [_textSelectionAssistant scheduleReplacementsForText:wordAtSelection]; 1312 1315 } 1313 1316 … … 1315 1318 { 1316 1319 if ([_textSelectionAssistant respondsToSelector:@selector(scheduleChineseTransliterationForText:)]) 1317 [_textSelectionAssistant scheduleChineseTransliterationForText:_page->editorState(). wordAtSelection];1320 [_textSelectionAssistant scheduleChineseTransliterationForText:_page->editorState().postLayoutData().wordAtSelection]; 1318 1321 } 1319 1322 … … 1335 1338 NSMutableDictionary* result = [NSMutableDictionary dictionary]; 1336 1339 1340 auto typingAttributes = _page->editorState().postLayoutData().typingAttributes; 1337 1341 CTFontSymbolicTraits symbolicTraits = 0; 1338 if ( _page->editorState().typingAttributes & AttributeBold)1342 if (typingAttributes & AttributeBold) 1339 1343 symbolicTraits |= kCTFontBoldTrait; 1340 if ( _page->editorState().typingAttributes & AttributeItalics)1344 if (typingAttributes & AttributeItalics) 1341 1345 symbolicTraits |= kCTFontTraitItalic; 1342 1346 … … 1352 1356 [result setObject:(id)font.get() forKey:NSFontAttributeName]; 1353 1357 1354 if ( _page->editorState().typingAttributes & AttributeUnderline)1358 if (typingAttributes & AttributeUnderline) 1355 1359 [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName]; 1356 1360 … … 1390 1394 return NO; 1391 1395 1392 NSUInteger textLength = _page->editorState(). selectedTextLength;1396 NSUInteger textLength = _page->editorState().postLayoutData().selectedTextLength; 1393 1397 // FIXME: We should be calling UIReferenceLibraryViewController to check if the length is 1394 1398 // acceptable, but the interface takes a string. … … 1419 1423 1420 1424 if (action == @selector(_promptForReplace:)) { 1421 if (!_page->editorState().selectionIsRange || !_page->editorState(). isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled])1425 if (!_page->editorState().selectionIsRange || !_page->editorState().postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) 1422 1426 return NO; 1423 1427 if ([[self selectedText] _containsCJScriptsOnly]) … … 1427 1431 1428 1432 if (action == @selector(_transliterateChinese:)) { 1429 if (!_page->editorState().selectionIsRange || !_page->editorState(). isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled])1433 if (!_page->editorState().selectionIsRange || !_page->editorState().postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) 1430 1434 return NO; 1431 1435 return UIKeyboardEnabledInputModesAllowChineseTransliterationForText([self selectedText]); … … 1433 1437 1434 1438 if (action == @selector(_reanalyze:)) { 1435 if (!_page->editorState().selectionIsRange || !_page->editorState(). isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled])1439 if (!_page->editorState().selectionIsRange || !_page->editorState().postLayoutData().isReplaceAllowed || ![[UIKeyboardImpl activeInstance] autocorrectSpellingEnabled]) 1436 1440 return NO; 1437 1441 return UIKeyboardCurrentInputModeAllowsChineseOrJapaneseReanalysisForText([self selectedText]); … … 1531 1535 - (void)_showDictionary:(NSString *)text 1532 1536 { 1533 CGRect presentationRect = _page->editorState(). selectionRects[0].rect();1537 CGRect presentationRect = _page->editorState().postLayoutData().selectionRects[0].rect(); 1534 1538 if (_textSelectionAssistant) 1535 1539 [_textSelectionAssistant showDictionaryFor:text fromRect:presentationRect]; … … 1938 1942 - (UTF32Char)_characterBeforeCaretSelection 1939 1943 { 1940 return _page->editorState(). characterBeforeSelection;1944 return _page->editorState().postLayoutData().characterBeforeSelection; 1941 1945 } 1942 1946 … … 1945 1949 switch (amount) { 1946 1950 case 0: 1947 return _page->editorState(). characterAfterSelection;1951 return _page->editorState().postLayoutData().characterAfterSelection; 1948 1952 case -1: 1949 return _page->editorState(). characterBeforeSelection;1953 return _page->editorState().postLayoutData().characterBeforeSelection; 1950 1954 case -2: 1951 return _page->editorState(). twoCharacterBeforeSelection;1955 return _page->editorState().postLayoutData().twoCharacterBeforeSelection; 1952 1956 default: 1953 1957 return 0; … … 1957 1961 - (BOOL)_selectionAtDocumentStart 1958 1962 { 1959 return !_page->editorState(). characterBeforeSelection;1963 return !_page->editorState().postLayoutData().characterBeforeSelection; 1960 1964 } 1961 1965 … … 2131 2135 - (UITextRange *)selectedTextRange 2132 2136 { 2133 FloatRect startRect = _page->editorState().caretRectAtStart; 2134 FloatRect endRect = _page->editorState().caretRectAtEnd; 2137 auto& postLayoutEditorStateData = _page->editorState().postLayoutData(); 2138 FloatRect startRect = postLayoutEditorStateData.caretRectAtStart; 2139 FloatRect endRect = postLayoutEditorStateData.caretRectAtEnd; 2135 2140 double inverseScale = [self inverseScale]; 2136 2141 // We want to keep the original caret width, while the height scales with … … 2160 2165 endRect:endRect 2161 2166 selectionRects:[self webSelectionRects] 2162 selectedTextLength: _page->editorState().selectedTextLength];2167 selectedTextLength:postLayoutEditorStateData.selectedTextLength]; 2163 2168 } 2164 2169 … … 2681 2686 - (BOOL)hasContent 2682 2687 { 2683 return _page->editorState(). hasContent;2688 return _page->editorState().postLayoutData().hasContent; 2684 2689 } 2685 2690 -
trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.cpp
r179409 r182603 191 191 } 192 192 193 void WebEditorClient::didChangeSelectionAndUpdateLayout() 194 { 195 m_page->sendPostLayoutEditorStateIfNeeded(); 196 } 197 193 198 void WebEditorClient::discardedComposition(Frame*) 194 199 { -
trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebEditorClient.h
r177152 r182603 65 65 virtual void respondToChangedContents() override; 66 66 virtual void respondToChangedSelection(WebCore::Frame*) override; 67 virtual void didChangeSelectionAndUpdateLayout() override; 67 68 virtual void discardedComposition(WebCore::Frame*) override; 68 69 virtual void didEndEditing() override; -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp
r182581 r182603 740 740 #endif 741 741 742 EditorState WebPage::editorState( ) const742 EditorState WebPage::editorState(IncludePostLayoutDataHint shouldIncludePostLayoutData) const 743 743 { 744 744 Frame& frame = m_page->focusController().focusedOrMainFrame(); … … 765 765 result.shouldIgnoreCompositionSelectionChange = frame.editor().ignoreCompositionSelectionChange(); 766 766 767 platformEditorState(frame, result );767 platformEditorState(frame, result, shouldIncludePostLayoutData); 768 768 769 769 return result; … … 4366 4366 void WebPage::didChangeSelection() 4367 4367 { 4368 Frame& frame = m_page->focusController().focusedOrMainFrame(); 4369 FrameView* view = frame.view(); 4370 bool needsLayout = view && view->needsLayout(); 4371 4372 // If there is a layout pending, we should avoid populating EditorState that require layout to be done or it will 4373 // trigger a synchronous layout every time the selection changes. sendPostLayoutEditorStateIfNeeded() will be called 4374 // to send the full editor state after layout is done if we send a partial editor state here. 4375 auto editorState = this->editorState(needsLayout ? IncludePostLayoutDataHint::No : IncludePostLayoutDataHint::Yes); 4376 ASSERT_WITH_MESSAGE(needsLayout == (view && view->needsLayout()), "Calling editorState() should not cause a synchronous layout."); 4377 m_isEditorStateMissingPostLayoutData = editorState.isMissingPostLayoutData; 4378 4368 4379 #if PLATFORM(MAC) && USE(ASYNC_NSTEXTINPUTCLIENT) 4369 Frame& frame = m_page->focusController().focusedOrMainFrame();4370 4380 // Abandon the current inline input session if selection changed for any other reason but an input method direct action. 4371 4381 // FIXME: This logic should be in WebCore. … … 4374 4384 if (frame.editor().hasComposition() && !frame.editor().ignoreCompositionSelectionChange() && !frame.selection().isNone()) { 4375 4385 frame.editor().cancelComposition(); 4376 send(Messages::WebPageProxy::CompositionWasCanceled(editorState ()));4386 send(Messages::WebPageProxy::CompositionWasCanceled(editorState)); 4377 4387 } else 4378 send(Messages::WebPageProxy::EditorStateChanged(editorState ()));4388 send(Messages::WebPageProxy::EditorStateChanged(editorState)); 4379 4389 #else 4380 send(Messages::WebPageProxy::EditorStateChanged(editorState ()), pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply);4390 send(Messages::WebPageProxy::EditorStateChanged(editorState), pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply); 4381 4391 #endif 4382 4392 … … 4384 4394 m_drawingArea->scheduleCompositingLayerFlush(); 4385 4395 #endif 4396 } 4397 4398 void WebPage::sendPostLayoutEditorStateIfNeeded() 4399 { 4400 if (!m_isEditorStateMissingPostLayoutData) 4401 return; 4402 4403 send(Messages::WebPageProxy::EditorStateChanged(editorState(IncludePostLayoutDataHint::Yes)), pageID(), IPC::DispatchMessageEvenWhenWaitingForSyncReply); 4404 m_isEditorStateMissingPostLayoutData = false; 4386 4405 } 4387 4406 -
trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h
r182556 r182603 328 328 #endif // ENABLE(WEBGL) 329 329 330 EditorState editorState() const; 330 enum class IncludePostLayoutDataHint { No, Yes }; 331 EditorState editorState(IncludePostLayoutDataHint = IncludePostLayoutDataHint::Yes) const; 332 void sendPostLayoutEditorStateIfNeeded(); 331 333 332 334 String renderTreeExternalRepresentation() const; … … 879 881 void platformInitialize(); 880 882 void platformDetach(); 881 void platformEditorState(WebCore::Frame&, EditorState& result ) const;883 void platformEditorState(WebCore::Frame&, EditorState& result, IncludePostLayoutDataHint) const; 882 884 883 885 void didReceiveWebPageMessage(IPC::Connection&, IPC::MessageDecoder&); … … 1354 1356 bool m_mainFrameProgressCompleted; 1355 1357 bool m_shouldDispatchFakeMouseMoveEvents; 1358 bool m_isEditorStateMissingPostLayoutData { false }; 1356 1359 }; 1357 1360 -
trunk/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp
r180465 r182603 83 83 } 84 84 85 void WebPage::platformEditorState(Frame&, EditorState& ) const85 void WebPage::platformEditorState(Frame&, EditorState&, IncludePostLayoutDataHint) const 86 86 { 87 87 } -
trunk/Source/WebKit2/WebProcess/WebPage/gtk/WebPageGtk.cpp
r180465 r182603 69 69 } 70 70 71 void WebPage::platformEditorState(Frame& frame, EditorState& result ) const71 void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint) const 72 72 { 73 73 result.cursorRect = frame.selection().absoluteCaretBounds(); -
trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm
r182162 r182603 129 129 } 130 130 131 void WebPage::platformEditorState(Frame& frame, EditorState& result) const 132 { 133 const VisibleSelection& selection = frame.selection().selection(); 131 void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint shouldIncludePostLayoutData) const 132 { 134 133 if (frame.editor().hasComposition()) { 135 134 RefPtr<Range> compositionRange = frame.editor().compositionRange(); … … 146 145 } 147 146 } 147 148 // We only set the remaining EditorState entries if the layout is done. To compute these 149 // entries, we need the layout to be done and we don't want to trigger a synchronous 150 // layout as this would be bad for performance. If we have a composition, we send everything 151 // right away as the UIProcess needs the caretRects ASAP for marked text. 152 if (shouldIncludePostLayoutData == IncludePostLayoutDataHint::No && !frame.editor().hasComposition()) { 153 result.isMissingPostLayoutData = true; 154 return; 155 } 156 157 auto& postLayoutData = result.postLayoutData(); 148 158 FrameView* view = frame.view(); 159 const VisibleSelection& selection = frame.selection().selection(); 149 160 if (selection.isCaret()) { 150 result.caretRectAtStart = view->contentsToRootView(frame.selection().absoluteCaretBounds());151 result.caretRectAtEnd = result.caretRectAtStart;161 postLayoutData.caretRectAtStart = view->contentsToRootView(frame.selection().absoluteCaretBounds()); 162 postLayoutData.caretRectAtEnd = postLayoutData.caretRectAtStart; 152 163 // FIXME: The following check should take into account writing direction. 153 result.isReplaceAllowed = result.isContentEditable && atBoundaryOfGranularity(selection.start(), WordGranularity, DirectionForward);154 result.wordAtSelection = plainTextReplacingNoBreakSpace(wordRangeFromPosition(selection.start()).get());164 postLayoutData.isReplaceAllowed = result.isContentEditable && atBoundaryOfGranularity(selection.start(), WordGranularity, DirectionForward); 165 postLayoutData.wordAtSelection = plainTextReplacingNoBreakSpace(wordRangeFromPosition(selection.start()).get()); 155 166 if (selection.isContentEditable()) { 156 charactersAroundPosition(selection.start(), result.characterAfterSelection, result.characterBeforeSelection, result.twoCharacterBeforeSelection);167 charactersAroundPosition(selection.start(), postLayoutData.characterAfterSelection, postLayoutData.characterBeforeSelection, postLayoutData.twoCharacterBeforeSelection); 157 168 Node* root = selection.rootEditableElement(); 158 result.hasContent = root && root->hasChildNodes() && !isEndOfEditableOrNonEditableContent(firstPositionInNode(root));169 postLayoutData.hasContent = root && root->hasChildNodes() && !isEndOfEditableOrNonEditableContent(firstPositionInNode(root)); 159 170 } 160 171 } else if (selection.isRange()) { 161 result.caretRectAtStart = view->contentsToRootView(VisiblePosition(selection.start()).absoluteCaretBounds());162 result.caretRectAtEnd = view->contentsToRootView(VisiblePosition(selection.end()).absoluteCaretBounds());172 postLayoutData.caretRectAtStart = view->contentsToRootView(VisiblePosition(selection.start()).absoluteCaretBounds()); 173 postLayoutData.caretRectAtEnd = view->contentsToRootView(VisiblePosition(selection.end()).absoluteCaretBounds()); 163 174 RefPtr<Range> selectedRange = selection.toNormalizedRange(); 164 175 String selectedText; 165 176 if (selectedRange) { 166 selectedRange->collectSelectionRects( result.selectionRects);167 convertSelectionRectsToRootView(view, result.selectionRects);177 selectedRange->collectSelectionRects(postLayoutData.selectionRects); 178 convertSelectionRectsToRootView(view, postLayoutData.selectionRects); 168 179 selectedText = plainTextReplacingNoBreakSpace(selectedRange.get(), TextIteratorDefaultBehavior, true); 169 result.selectedTextLength = selectedText.length();180 postLayoutData.selectedTextLength = selectedText.length(); 170 181 const int maxSelectedTextLength = 200; 171 182 if (selectedText.length() <= maxSelectedTextLength) 172 result.wordAtSelection = selectedText;183 postLayoutData.wordAtSelection = selectedText; 173 184 } 174 185 // FIXME: We should disallow replace when the string contains only CJ characters. 175 result.isReplaceAllowed = result.isContentEditable && !result.isInPasswordField && !selectedText.containsOnlyWhitespace();186 postLayoutData.isReplaceAllowed = result.isContentEditable && !result.isInPasswordField && !selectedText.containsOnlyWhitespace(); 176 187 } 177 188 if (!selection.isNone()) { … … 182 193 183 194 if (traits & kCTFontTraitBold) 184 result.typingAttributes |= AttributeBold;195 postLayoutData.typingAttributes |= AttributeBold; 185 196 if (traits & kCTFontTraitItalic) 186 result.typingAttributes |= AttributeItalics;197 postLayoutData.typingAttributes |= AttributeItalics; 187 198 188 199 RefPtr<EditingStyle> typingStyle = frame.selection().typingStyle(); … … 190 201 String value = typingStyle->style()->getPropertyValue(CSSPropertyWebkitTextDecorationsInEffect); 191 202 if (value.contains("underline")) 192 result.typingAttributes |= AttributeUnderline;203 postLayoutData.typingAttributes |= AttributeUnderline; 193 204 } else { 194 205 if (style->textDecorationsInEffect() & TextDecorationUnderline) 195 result.typingAttributes |= AttributeUnderline;206 postLayoutData.typingAttributes |= AttributeUnderline; 196 207 } 197 208 -
trunk/Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
r182573 r182603 123 123 } 124 124 125 void WebPage::platformEditorState(Frame& frame, EditorState& result ) const125 void WebPage::platformEditorState(Frame& frame, EditorState& result, IncludePostLayoutDataHint) const 126 126 { 127 127 }
Note: See TracChangeset
for help on using the changeset viewer.