#include "config.h"
#include "WebPage.h"
+#include "EditorState.h"
#include "NamedNodeMap.h"
#include "NotImplemented.h"
#include "WebEvent.h"
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> 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<WebCore::CompositionUnderline>& 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<CompositionUnderline> 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)
}
#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<WebCore::CompositionUnderline>& 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<CompositionUnderline> 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;
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
// 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());
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;
}
// 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;
#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)
inputElement->toNode()->dispatchFocusEvent(0);
inputElement->setValue(inputValue, DispatchChangeEvent);
-
- updateCursorOffset();
}
void WebPage::getFocusedInputElementValue(String& inputValue)
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());
}
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;
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));
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);
pos.setY(rect.maxY() - boundariesWidth - 1);
}
- OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
- WebCore::Position extent = frameSelection->extent();
+ OwnPtr<VisiblePosition> 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();
}
-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;
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);
pos.setY(rect.maxY() - boundariesWidth - 1);
}
- OwnPtr<WebCore::VisiblePosition> position = adoptPtr(new WebCore::VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
- WebCore::Position base = frameSelection->base();
+ OwnPtr<VisiblePosition> 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();
return;
// Is this check necessary? Leaving it for safety.
- WebCore::RenderView* root = focusedFrame->contentRenderer();
+ RenderView* root = focusedFrame->contentRenderer();
if (!root)
return;
- RefPtr<WebCore::Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
+ RefPtr<Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
- Vector<WebCore::IntRect> rects;
- selectedRange->textRects(rects, true);
+ Vector<IntRect> 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) {
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());
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());
if (!frame)
return;
- WebCore::FrameSelection* frameSelection = frame->selection();
+ FrameSelection* frameSelection = frame->selection();
if (frameSelection)
frameSelection->clear();
} else if (frame->tree()->nextSibling())
selectionClearAllSelection(frame->tree()->nextSibling());
}
-
#endif
#if ENABLE(TIZEN_LINK_MAGNIFIER)