X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=Source%2FWebKit2%2FWebProcess%2FWebPage%2Fefl%2FWebPageEfl.cpp;h=0766b715fdaf99d7a25f91b144c06f41c773566a;hb=a35b4d9f8ad7aa3ecaf0b9ffa9d7c7d72b722f6c;hp=9254da922d7d25c8a754e1a29a8b913a9040b9c7;hpb=1b4fe0ece5d5c51bf5aa1974f4e8f3eb2bffad17;p=framework%2Fweb%2Fwebkit-efl.git diff --git a/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp b/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp index 9254da9..0766b71 100755 --- a/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp +++ b/Source/WebKit2/WebProcess/WebPage/efl/WebPageEfl.cpp @@ -28,6 +28,7 @@ #include "config.h" #include "WebPage.h" +#include "EditorState.h" #include "NamedNodeMap.h" #include "NotImplemented.h" #include "WebEvent.h" @@ -245,6 +246,91 @@ void WebPage::setThemePath(const String& themePath) theme->setThemePath(themePath); } +static Frame* targetFrameForEditing(WebPage* page) +{ + Frame* frame = page->corePage()->focusController()->focusedOrMainFrame(); + if (!frame) + return 0; + + Editor* editor = frame->editor(); + if (!editor->canEdit()) + return 0; + + if (editor->hasComposition()) { + // We should verify the parent node of this IME composition node are + // editable because JavaScript may delete a parent node of the composition + // node. In this case, WebKit crashes while deleting texts from the parent + // node, which doesn't exist any longer. + if (PassRefPtr range = editor->compositionRange()) { + Node* node = range->startContainer(); + if (!node || !node->isContentEditable()) + return 0; + } + } + + return frame; +} + +void WebPage::confirmComposition(const String& compositionString) +{ + Frame* targetFrame = targetFrameForEditing(this); + if (!targetFrame) + return; + + targetFrame->editor()->confirmComposition(compositionString); +} + +void WebPage::setComposition(const String& compositionString, const Vector& underlines, uint64_t cursorPosition) +{ + Frame* targetFrame = targetFrameForEditing(this); + if (!targetFrame) + return; + +#if ENABLE(TIZEN_ISF_PORT) + if (targetFrame->selection()->rootEditableElement()) { + HTMLTextFormControlElement* textFormControl = toTextFormControl(targetFrame->selection()->rootEditableElement()->shadowAncestorNode()); + if (textFormControl && textFormControl->maxLength() >= 0) { + unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length(); + if (targetFrame->editor()->hasComposition()) + availableLength += (targetFrame->editor()->compositionEnd() - targetFrame->editor()->compositionStart()); + if (!availableLength) + return; + + if (availableLength < compositionString.length()) { + String newCompositionString = compositionString.substring(0, availableLength); + Vector newUnderlines; + size_t numUnderlines = underlines.size(); + for (size_t index = 0; index < numUnderlines; ++index) { + if (underlines[index].startOffset < availableLength) { + newUnderlines.append(underlines[index]); + if (newUnderlines.last().endOffset > availableLength) + newUnderlines.last().endOffset = availableLength; + } + } + targetFrame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0); + return; + } + } + } + m_isSettingComposition = true; +#endif + + targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0); + +#if ENABLE(TIZEN_ISF_PORT) + m_isSettingComposition = false; +#endif +} + +void WebPage::cancelComposition() +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (!frame) + return; + + frame->editor()->cancelComposition(); +} + #if OS(TIZEN) #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE) @@ -402,65 +488,14 @@ void WebPage::createPagesToPDF(const IntSize& surfaceSize, const IntSize& conten } #endif -void WebPage::confirmComposition(const String& compositionString) -{ - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame || !frame->editor()->canEdit()) - return; - frame->editor()->confirmComposition(compositionString); -#if ENABLE(TIZEN_ISF_PORT) - updateCursorOffset(); -#endif -} - -void WebPage::setComposition(const String& compositionString, const Vector& underlines, uint64_t cursorPosition) -{ - Frame* frame = m_page->focusController()->focusedOrMainFrame(); - if (!frame || !frame->editor()->canEdit()) - return; -#if ENABLE(TIZEN_ISF_PORT) - if (frame->selection()->rootEditableElement()) { - HTMLTextFormControlElement* textFormControl = toTextFormControl(frame->selection()->rootEditableElement()->shadowAncestorNode()); - if (textFormControl && textFormControl->maxLength() >= 0) { - unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length(); - if (frame->editor()->hasComposition()) - availableLength += (frame->editor()->compositionEnd() - frame->editor()->compositionStart()); - if (!availableLength) - return; - - if (availableLength < compositionString.length()) { - String newCompositionString = compositionString.substring(0, availableLength); - Vector newUnderlines; - size_t numUnderlines = underlines.size(); - for (size_t index = 0; index < numUnderlines; ++index) { - if (underlines[index].startOffset < availableLength) { - newUnderlines.append(underlines[index]); - if (newUnderlines.last().endOffset > availableLength) - newUnderlines.last().endOffset = availableLength; - } - } - frame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0); - return; - } - } - } - m_isSettingComposition = true; -#endif - frame->editor()->setComposition(compositionString, underlines, cursorPosition, 0); -#if ENABLE(TIZEN_ISF_PORT) - m_isSettingComposition = false; - updateCursorOffset(); -#endif -} - #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2) -bool WebPage::setCaretPosition(const WebCore::IntPoint& pos) +bool WebPage::setCaretPosition(const IntPoint& pos) { Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (!frame) return false; - WebCore::FrameSelection* controller = frame->selection(); + FrameSelection* controller = frame->selection(); if (!controller) return false; @@ -468,24 +503,24 @@ bool WebPage::setCaretPosition(const WebCore::IntPoint& pos) if (!frameView) return false; - WebCore::IntPoint point = m_page->mainFrame()->view()->windowToContents(pos); - WebCore::HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true); + IntPoint point = m_page->mainFrame()->view()->windowToContents(pos); + HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true); if (result.scrollbar()) return false; - WebCore::Node* innerNode = result.innerNode(); + Node* innerNode = result.innerNode(); if (!innerNode || !innerNode->renderer()) return false; - WebCore::VisiblePosition visiblePos; + VisiblePosition visiblePos; // we check if content is richly editable - because those input field behave other than plain text ones // sometimes they may consists a node structure and they need special approach if (innerNode->rendererIsRichlyEditable()) { // point gets inner node local coordinates point = flooredIntPoint(result.localPoint()); - WebCore::IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true); + IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true); // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone // will have a better idea how to solve it @@ -495,13 +530,13 @@ bool WebPage::setCaretPosition(const WebCore::IntPoint& pos) // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field // node, not outside of it - WebCore::Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode(); + Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode(); if (!deepInnerNode || !deepInnerNode->renderer()) return false; // so we get a base node rectange - WebCore::IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true); + IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true); // we modify our local point to adjust it to base node local coordinates point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y()); @@ -521,35 +556,41 @@ bool WebPage::setCaretPosition(const WebCore::IntPoint& pos) if (!controller->isCaret() || !controller->caretRenderer()) return false; - const WebCore::Node* node = controller->start().deprecatedNode(); + const Node* node = controller->start().deprecatedNode(); if (!node || !node->renderer()) return false; - WebCore::IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true); + IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true); -// FIXME: The below codes should be updated to apply the positon of focusedFrame. -#if 0 + // The below wirtten code is not correct way to implement. Presntly the is no + // other working way. To be replaced by better logic // here we also cheat input field that we actually are just inside of if - if (point.x() < rect.x()) - point.setX(rect.x()); - else if (point.x() > rect.maxX()) - point.setX(rect.maxX()); + IntPoint focusedFramePoint = frame->view()->windowToContents(pos); + IntPoint oldFocusedFramePoint = focusedFramePoint; const int boundariesWidth = 2; - if (point.y() < rect.y() + boundariesWidth) - point.setY(rect.y() + boundariesWidth); - else if (point.y() >= rect.maxY() - boundariesWidth) - point.setY(rect.maxY() - boundariesWidth - 1); -#endif + if (focusedFramePoint.x() < rect.x()) + focusedFramePoint.setX(rect.x()); + else if (focusedFramePoint.x() > rect.maxX()) + focusedFramePoint.setX(rect.maxX()); + if (focusedFramePoint.y() < rect.y() + boundariesWidth) + focusedFramePoint.setY(rect.y() + boundariesWidth); + else if (focusedFramePoint.y() >= rect.maxY() - boundariesWidth) + focusedFramePoint.setY(rect.maxY() - boundariesWidth - 1); + + int diffX = focusedFramePoint.x() - oldFocusedFramePoint.x(); + int diffY = focusedFramePoint.y() - oldFocusedFramePoint.y(); + point.setX((point.x())+diffX); + point.setY((point.y())+diffY); // hit test with fake (adjusted) coordinates - WebCore::IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point); - WebCore::HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true); + IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point); + HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true); if (!newResult.isContentEditable()) return false; - WebCore::Node* newInnerNode = newResult.innerNode(); + Node* newInnerNode = newResult.innerNode(); if (!newInnerNode || !newInnerNode->renderer()) return false; @@ -561,25 +602,25 @@ bool WebPage::setCaretPosition(const WebCore::IntPoint& pos) } // create visible selection from visible position - WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos); - controller->setSelection(newSelection, WebCore::CharacterGranularity); + VisibleSelection newSelection = VisibleSelection(visiblePos); + controller->setSelection(newSelection, CharacterGranularity); // after setting selection caret blinking is suspended by default so we are unsuspedning it controller->setCaretBlinkingSuspended(false); return true; } -void WebPage::getCaretPosition(WebCore::IntRect& rect) +void WebPage::getCaretPosition(IntRect& rect) { Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (!frame) return; - WebCore::FrameSelection* controller = frame->selection(); + FrameSelection* controller = frame->selection(); if (!controller) return; - WebCore::Node* node = controller->start().deprecatedNode(); + Node* node = controller->start().deprecatedNode(); if (!node || !node->renderer() || !node->isContentEditable()) return; @@ -594,13 +635,6 @@ void WebPage::getCaretPosition(WebCore::IntRect& rect) #endif #if ENABLE(TIZEN_ISF_PORT) -void WebPage::updateCursorOffset() -{ - int offset; - getCursorOffset(offset); - send(Messages::WebPageProxy::UpdateCursorOffset(offset)); -} - void WebPage::didCancelComposition(Node* valueChangedNode) { if (m_isSettingComposition) @@ -696,8 +730,6 @@ void WebPage::setFocusedInputElementValue(const String& inputValue) inputElement->toNode()->dispatchFocusEvent(0); inputElement->setValue(inputValue, DispatchChangeEvent); - - updateCursorOffset(); } void WebPage::getFocusedInputElementValue(String& inputValue) @@ -840,8 +872,12 @@ static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page) focusableNode = focusableNode->parentNode(); } - if (!isFocusRingDrawable) + if (!isFocusRingDrawable) { + if (node->hasTagName(HTMLNames::imgTag)) + return getNodeRect(node, node, !hitTestResult.absoluteImageURL().isEmpty()); + return IntRect(); + } return getNodeRect(node, focusableNode, !hitTestResult.absoluteImageURL().isEmpty()); } @@ -1238,16 +1274,16 @@ void WebPage::selectClosestWord(const IntPoint& point, bool isStartedTextSelecti result = true; } -void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result) +void WebPage::setLeftSelection(const IntPoint& point, bool& result) { result = false; Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame(); - WebCore::FrameSelection* frameSelection = focusedFrame->selection(); + FrameSelection* frameSelection = focusedFrame->selection(); if (!frameSelection->isRange()) return; - WebCore::Node* selectionEndNode = frameSelection->end().deprecatedNode(); + Node* selectionEndNode = frameSelection->end().deprecatedNode(); if (!selectionEndNode || !selectionEndNode->renderer()) return; @@ -1255,8 +1291,8 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result) if (!frameView) return; - WebCore::IntPoint pos = frameView->windowToContents(point); - WebCore::IntRect leftRect, rightRect; + IntPoint pos = frameView->windowToContents(point); + IntRect leftRect, rightRect; getSelectionHandlers(leftRect, rightRect); if ((rightRect.y() + rightRect.height()) < pos.y()) pos.setY(rightRect.y() + (rightRect.height()/2)); @@ -1264,7 +1300,7 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result) if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) { const int boundariesWidth = 2; - WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true); + IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true); // here we cheat input field that we actually are just inside of if if (pos.y() < rect.y() + boundariesWidth) pos.setY(rect.y() + boundariesWidth); @@ -1272,21 +1308,21 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result) pos.setY(rect.maxY() - boundariesWidth - 1); } - OwnPtr position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos))); - WebCore::Position extent = frameSelection->extent(); + OwnPtr position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos))); + Position extent = frameSelection->extent(); - WebCore::Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode(); + Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode(); // both start and end nodes should be in the same area type: both should be editable or both should be not editable // Check if the new position is before the extent's position if (newSelectionStartNode && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable() - && WebCore::comparePositions(position->deepEquivalent(), extent) < 0) { + && comparePositions(position->deepEquivalent(), extent) < 0) { // Change the 'base' and 'extent' positions to 'start' and 'end' positions. // We do it, because without this, the other modification of the selection // would destroy the 'start' and/or 'end' positions and set them to // the 'base'/'extent' positions accordingly - WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end()); + VisibleSelection sel(frameSelection->start(), frameSelection->end()); frameSelection->setSelection(sel); bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling(); @@ -1303,17 +1339,17 @@ void WebPage::setLeftSelection(const WebCore::IntPoint& point, bool& result) } -void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result) +void WebPage::setRightSelection(const IntPoint& point, bool& result) { result = false; Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame(); - WebCore::FrameSelection* frameSelection = focusedFrame->selection(); + FrameSelection* frameSelection = focusedFrame->selection(); if (!frameSelection->isRange()) return; - WebCore::Node* selectionStartNode = frameSelection->start().deprecatedNode(); + Node* selectionStartNode = frameSelection->start().deprecatedNode(); if (!selectionStartNode || !selectionStartNode->renderer()) return; @@ -1321,11 +1357,11 @@ void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result) if (!frameView) return; - WebCore::IntPoint pos = frameView->windowToContents(point); + IntPoint pos = frameView->windowToContents(point); if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) { const int boundariesWidth = 2; - WebCore::IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true); + IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true); // here we cheat input field that we actually are just inside of if if (pos.y() < rect.y() + boundariesWidth) pos.setY(rect.y() + boundariesWidth); @@ -1333,22 +1369,22 @@ void WebPage::setRightSelection(const WebCore::IntPoint& point, bool& result) pos.setY(rect.maxY() - boundariesWidth - 1); } - OwnPtr position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos))); - WebCore::Position base = frameSelection->base(); + OwnPtr position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos))); + Position base = frameSelection->base(); - WebCore::Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode(); + Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode(); // both start and end nodes should be in the same area type: both should be editable or both should be not editable // Check if the new position is after the base's position if (newSelectionEndNode && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable() - && WebCore::comparePositions(position->deepEquivalent(), base) > 0) { + && comparePositions(position->deepEquivalent(), base) > 0) { // Change the 'base' and 'extent' positions to 'start' and 'end' positions. // We do it, because without this, the other modifications of the selection // would destroy the 'start' and/or 'end' positions and set them to // the 'base'/'extent' positions accordingly - WebCore::VisibleSelection sel(frameSelection->start(), frameSelection->end()); + VisibleSelection sel(frameSelection->start(), frameSelection->end()); frameSelection->setSelection(sel); bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling(); @@ -1369,14 +1405,25 @@ void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect) return; // Is this check necessary? Leaving it for safety. - WebCore::RenderView* root = focusedFrame->contentRenderer(); + RenderView* root = focusedFrame->contentRenderer(); if (!root) return; - RefPtr selectedRange = focusedFrame->selection()->toNormalizedRange(); + RefPtr selectedRange = focusedFrame->selection()->toNormalizedRange(); - Vector rects; - selectedRange->textRects(rects, true); + Vector rects, tempRects; + selectedRange->boundingBoxEx(tempRects, true); + + IntRect boundsRect = enclosingIntRect(focusedFrame->selection()->bounds()); + for (size_t i = 0; i < tempRects.size(); i++) { + if (boundsRect.contains(tempRects[i])) + rects.append(tempRects[i]); + else { + tempRects[i].intersect(boundsRect); + if (!tempRects[i].isEmpty()) + rects.append(tempRects[i]); + } + } unsigned size = rects.size(); if (size > 0) { @@ -1388,7 +1435,15 @@ void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect) if (size == 1) { Element* selectionRoot = focusedFrame->selection()->rootEditableElement(); if (selectionRoot) { - WebCore::IntRect editorRect = focusedFrame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect()); + IntRect editorRect = focusedFrame->view()->contentsToWindow(selectionRoot->getPixelSnappedRect()); + +#if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION) + if (m_editorState.editorRect != editorRect) { + EditorState state = editorState(); + state.updateEditorRectOnly = true; + send(Messages::WebPageProxy::EditorStateChanged(state)); + } +#endif if (leftRect.maxY() > editorRect.maxY()) { leftRect.setY(editorRect.y()); @@ -1427,13 +1482,13 @@ void WebPage::selectionRangeClear(bool& result) result = false; Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame(); - WebCore::FrameSelection* frameSelection = focusedFrame->selection(); + FrameSelection* frameSelection = focusedFrame->selection(); if (frameSelection && frameSelection->isRange() && frameSelection->isContentEditable()) { - WebCore::VisiblePosition visiblePos(frameSelection->extent()); + VisiblePosition visiblePos(frameSelection->extent()); if (visiblePos.isNull()) return; - WebCore::VisibleSelection newSelection = WebCore::VisibleSelection(visiblePos); - frameSelection->setSelection(newSelection, WebCore::CharacterGranularity); + VisibleSelection newSelection = VisibleSelection(visiblePos); + frameSelection->setSelection(newSelection, CharacterGranularity); frameSelection->setCaretBlinkingSuspended(false); } else selectionClearAllSelection(m_page->mainFrame()); @@ -1446,7 +1501,7 @@ void WebPage::selectionClearAllSelection(Frame* frame) if (!frame) return; - WebCore::FrameSelection* frameSelection = frame->selection(); + FrameSelection* frameSelection = frame->selection(); if (frameSelection) frameSelection->clear(); @@ -1459,7 +1514,6 @@ void WebPage::selectionClearAllSelection(Frame* frame) } else if (frame->tree()->nextSibling()) selectionClearAllSelection(frame->tree()->nextSibling()); } - #endif #if ENABLE(TIZEN_LINK_MAGNIFIER)