2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
4 * Copyright (C) 2011 Igalia S.L.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
31 #include "EditorState.h"
32 #include "NamedNodeMap.h"
33 #include "NotImplemented.h"
35 #include "WindowsKeyboardCodes.h"
36 #include <WebCore/EflKeyboardUtilities.h>
37 #include <WebCore/FocusController.h>
38 #include <WebCore/Frame.h>
39 #include <WebCore/FrameView.h>
40 #include <WebCore/KeyboardEvent.h>
41 #include <WebCore/Page.h>
42 #include <WebCore/PlatformKeyboardEvent.h>
43 #include <WebCore/RenderThemeEfl.h>
44 #include <WebCore/Settings.h>
47 #include "Arguments.h"
48 #include "GraphicsContext.h"
49 #include "WebCoreArgumentCoders.h"
52 #include "WebPageProxyMessages.h"
53 #include <WebCore/FrameView.h>
55 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
56 #include <WebCore/HTMLInputElement.h>
57 #include <WebCore/HTMLNames.h>
60 #if ENABLE(TIZEN_MULTIPLE_SELECT)
61 #include "WebPopupMenu.h"
62 #include <WebCore/PopupMenuClient.h>
65 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
66 #include <WebCore/PlatformContextCairo.h>
69 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
70 #include <WebCore/ClipboardTizen.h>
73 #if ENABLE(TIZEN_PASTEBOARD)
74 #include <WebCore/Pasteboard.h>
77 #if ENABLE(TIZEN_REMOTE_WEB_INSPECTOR)
78 #include "WebInspectorServerTizen.h"
81 #if ENABLE(TIZEN_WEB_STORAGE)
82 #include <WebCore/GroupSettings.h>
83 #include <WebCore/PageGroup.h>
86 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
87 #include "PluginView.h"
90 #if ENABLE(TIZEN_PREFERENCE)
91 #include "WebPreferencesStore.h"
92 #include <WebCore/Settings.h>
95 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
96 #include <WebCore/HTMLFrameOwnerElement.h>
97 #include <WebCore/HTMLImageElement.h>
100 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
101 #include "DeviceMotionClientTizen.h"
102 #include "DeviceOrientationClientTizen.h"
105 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
106 #include "RenderLayer.h"
107 #include "WebGraphicsLayer.h"
108 #include <WebCore/RenderView.h>
111 #if ENABLE(TIZEN_ISF_PORT)
112 #include <WebCore/Text.h>
113 #include <WebCore/EditorClient.h>
116 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION) || ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
117 #include "EditorClient.h"
120 #if ENABLE(TIZEN_DATALIST_ELEMENT)
121 #include "HTMLCollection.h"
122 #include "HTMLDataListElement.h"
123 #include "HTMLOptionElement.h"
126 #if ENABLE(TIZEN_STYLE_SCOPED)
127 #include <WebCore/RuntimeEnabledFeatures.h>
130 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
131 #include "htmlediting.h"
134 #if ENABLE(TIZEN_LINK_MAGNIFIER)
135 #include "LinkMagnifier.h"
138 #if ENABLE(TIZEN_SCREEN_READER)
139 #include "WebEventConversion.h"
142 #if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
143 #include <WebCore/HTMLAreaElement.h>
146 #if ENABLE(TIZEN_CSP)
147 #include <WebCore/ContentSecurityPolicy.h>
150 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
151 #include "WebPageSerializerTizen.h"
154 #if ENABLE(TIZEN_USE_SETTINGS_FONT)
155 #include "fontconfig/fontconfig.h"
156 #include <WebCore/FontCache.h>
159 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
160 #include "visible_units.h"
162 #endif // #if OS(TIZEN)
164 using namespace WebCore;
168 void WebPage::platformInitialize()
170 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
171 WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientTizen);
172 WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientTizen);
176 #if ENABLE(TIZEN_PREFERENCE)
177 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
179 Settings* settings = m_page->settings();
180 settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
181 settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
182 #if ENABLE(TIZEN_LOAD_REMOTE_IMAGES)
183 settings->setLoadRemoteImages(store.getBoolValueForKey(WebPreferencesKey::loadRemoteImagesKey()));
185 #if ENABLE(TIZEN_LINK_EFFECT)
186 settings->setLinkEffectEnabled(store.getBoolValueForKey(WebPreferencesKey::linkEffectEnabledKey()));
188 #if ENABLE(TIZEN_ISF_PORT)
189 settings->setEnableDefaultKeypad(store.getBoolValueForKey(WebPreferencesKey::defaultKeypadEnabledKey()));
191 #if ENABLE(TIZEN_STYLE_SCOPED)
192 WebCore::RuntimeEnabledFeatures::setStyleScopedEnabled(store.getBoolValueForKey(WebPreferencesKey::styleScopedEnabledKey()));
194 #if ENABLE(TIZEN_WEB_AUDIO)
195 settings->setWebAudioEnabled(true);
199 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
203 #endif // #if ENABLE(TIZEN_PREFERENCE)
205 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
207 page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
210 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
216 bool WebPage::platformHasLocalDataForURL(const KURL&)
222 String WebPage::cachedResponseMIMETypeForURL(const KURL&)
228 bool WebPage::platformCanHandleRequest(const ResourceRequest&)
234 String WebPage::cachedSuggestedFilenameForURL(const KURL&)
240 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
246 const char* WebPage::interpretKeyEvent(const KeyboardEvent* event)
248 ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
250 if (event->type() == eventNames().keydownEvent)
251 return getKeyDownCommandName(event);
253 return getKeyPressCommandName(event);
256 void WebPage::setThemePath(const String& themePath)
258 WebCore::RenderThemeEfl* theme = static_cast<WebCore::RenderThemeEfl*>(m_page->theme());
259 theme->setThemePath(themePath);
262 static Frame* targetFrameForEditing(WebPage* page)
264 Frame* frame = page->corePage()->focusController()->focusedOrMainFrame();
268 Editor* editor = frame->editor();
269 if (!editor->canEdit())
272 if (editor->hasComposition()) {
273 // We should verify the parent node of this IME composition node are
274 // editable because JavaScript may delete a parent node of the composition
275 // node. In this case, WebKit crashes while deleting texts from the parent
276 // node, which doesn't exist any longer.
277 if (PassRefPtr<Range> range = editor->compositionRange()) {
278 Node* node = range->startContainer();
279 if (!node || !node->isContentEditable())
287 void WebPage::confirmComposition(const String& compositionString)
289 Frame* targetFrame = targetFrameForEditing(this);
293 #if ENABLE(TIZEN_ISF_PORT)
294 if (m_prepareKeyDownEvent) {
295 m_keyPressCommands.append(adoptPtr(new ConfirmCompositionKeyPressCommand(compositionString)));
300 targetFrame->editor()->confirmComposition(compositionString);
302 #if ENABLE(TIZEN_ISF_PORT)
303 m_page->editorClient()->respondToChangedSelection(targetFrame);
307 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
309 Frame* targetFrame = targetFrameForEditing(this);
313 #if ENABLE(TIZEN_ISF_PORT)
314 if (!targetFrame->editor()->hasComposition() && compositionString.isEmpty())
317 if (m_prepareKeyDownEvent) {
318 m_keyPressCommands.append(adoptPtr(new SetCompositionKeyPressCommand(compositionString, underlines, cursorPosition)));
322 if (targetFrame->selection()->rootEditableElement()) {
323 HTMLTextFormControlElement* textFormControl = toTextFormControl(targetFrame->selection()->rootEditableElement()->shadowAncestorNode());
324 if (textFormControl && textFormControl->maxLength() >= 0) {
325 unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length();
326 if (targetFrame->editor()->hasComposition())
327 availableLength += (targetFrame->editor()->compositionEnd() - targetFrame->editor()->compositionStart());
328 if (!availableLength)
331 if (availableLength < compositionString.length()) {
332 String newCompositionString = compositionString.substring(0, availableLength);
333 Vector<CompositionUnderline> newUnderlines;
334 size_t numUnderlines = underlines.size();
335 for (size_t index = 0; index < numUnderlines; ++index) {
336 if (underlines[index].startOffset < availableLength) {
337 newUnderlines.append(underlines[index]);
338 if (newUnderlines.last().endOffset > availableLength)
339 newUnderlines.last().endOffset = availableLength;
342 targetFrame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0);
349 targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
351 #if ENABLE(TIZEN_ISF_PORT)
352 m_page->editorClient()->respondToChangedSelection(targetFrame);
356 void WebPage::cancelComposition()
358 Frame* frame = m_page->focusController()->focusedOrMainFrame();
362 frame->editor()->cancelComposition();
367 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
368 IntSize WebPage::contentsSize() const
370 FrameView* frameView = m_page->mainFrame()->view();
372 return IntSize(0, 0);
374 return frameView->contentsSize();
378 void WebPage::scrollMainFrameBy(const IntSize& scrollOffset)
380 m_page->mainFrame()->view()->scrollBy(scrollOffset);
383 void WebPage::scrollMainFrameTo(const IntPoint& scrollPosition)
385 m_page->mainFrame()->view()->setScrollPosition(scrollPosition);
388 void WebPage::createSnapshot(const IntRect rect, float scaleFactor, ShareableBitmap::Handle& snapshotHandle)
390 FrameView* frameView = m_mainFrame->coreFrame()->view();
394 RefPtr<WebImage> snapshotImage = scaledSnapshotInViewCoordinates(rect, scaleFactor, ImageOptionsShareable);
395 if (!snapshotImage || !snapshotImage->bitmap())
398 snapshotImage->bitmap()->createHandle(snapshotHandle);
401 void WebPage::requestUpdateFormNavigation()
403 Frame* frame = m_page->focusController()->focusedOrMainFrame();
407 Document* document = frame->document();
411 Node* focusedNode = document->focusedNode();
413 Vector<RefPtr<Node> > focusableNodes;
414 document->getFocusableNodes(focusableNodes);
416 int formElementCount = 0;
417 int currentNodeIndex = -1;
418 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
419 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
420 AtomicString nodeName = (*it).get()->nodeName();
421 if (equalIgnoringCase(nodeName, "SELECT")
422 || (equalIgnoringCase(nodeName, "INPUT")
423 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
424 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
425 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "SUBMIT")
428 if ((*it).get() == focusedNode)
429 currentNodeIndex = formElementCount;
434 if (currentNodeIndex == -1)
437 send(Messages::WebPageProxy::UpdateFormNavigation(formElementCount, currentNodeIndex));
440 void WebPage::moveFocus(int newIndex)
442 Frame* frame = m_page->focusController()->focusedOrMainFrame();
446 Document* document = frame->document();
450 Vector<RefPtr<Node> > focusableNodes;
451 document->getFocusableNodes(focusableNodes);
454 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
455 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
456 AtomicString nodeName = (*it).get()->nodeName();
457 if (equalIgnoringCase(nodeName, "SELECT")) {
458 if (index == newIndex) {
459 (*it).get()->setFocus();
460 LayoutPoint position = LayoutPoint(0, 0);
461 PlatformMouseEvent event(flooredIntPoint(position), flooredIntPoint(position), LeftButton, PlatformEvent::MouseMoved, 1, false, false, false, false, 0);
462 (*it).get()->dispatchMouseEvent(event, "mousedown", 0, 0);
465 } else if (equalIgnoringCase(nodeName, "INPUT")
466 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
467 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
469 if (index == newIndex) {
470 HTMLInputElement* elem = (*it).get()->toInputElement();
478 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
479 #define INCH_TO_MM 25.4
480 #define INCH_TO_POINTS 72.0
482 void WebPage::createPagesToPDF(const IntSize& surfaceSize, const IntSize& contentsSize, const String& fileName)
484 FrameView* frameView = m_mainFrame->coreFrame()->view();
488 RefPtr<WebImage> pageshotImage = WebImage::create(contentsSize, ImageOptionsShareable);
489 if (!pageshotImage->bitmap())
492 double pdfWidth = (double)surfaceSize.width() / INCH_TO_MM * INCH_TO_POINTS;
493 double pdfHeight = (double)surfaceSize.height() / INCH_TO_MM * INCH_TO_POINTS;
494 double scaleFactorPdf = 1.0;
495 if (contentsSize.width() > pdfWidth)
496 scaleFactorPdf = pdfWidth / (double)contentsSize.width();
498 OwnPtr<WebCore::GraphicsContext> graphicsContext = pageshotImage->bitmap()->createGraphicsContextForPdfSurface(fileName, pdfWidth, pdfHeight);
499 graphicsContext->scale(FloatSize(scaleFactorPdf, scaleFactorPdf));
501 frameView->updateLayoutAndStyleIfNeededRecursive();
503 int pageNumber = ((contentsSize.height() * scaleFactorPdf) / pdfHeight) + 1;
506 PaintBehavior oldBehavior = frameView->paintBehavior();
507 frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
508 for (int i = 0; i < pageNumber; i++) {
509 IntRect paintRect(0, (int)paintY, contentsSize.width(), (int)(pdfHeight / scaleFactorPdf));
511 frameView->paint(graphicsContext.get(), paintRect);
512 cairo_show_page(graphicsContext->platformContext()->cr());
513 graphicsContext->translate(0, -ceil(pdfHeight / scaleFactorPdf));
514 paintY += (pdfHeight / scaleFactorPdf);
516 frameView->setPaintBehavior(oldBehavior);
518 pageshotImage.release();
522 #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2)
523 bool WebPage::setCaretPosition(const IntPoint& pos)
525 Frame* frame = m_page->focusController()->focusedOrMainFrame();
529 FrameSelection* controller = frame->selection();
533 FrameView* frameView = frame->view();
537 IntPoint point = m_page->mainFrame()->view()->windowToContents(pos);
538 HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
539 if (result.scrollbar())
542 Node* innerNode = result.innerNode();
544 if (!innerNode || !innerNode->renderer())
547 VisiblePosition visiblePos;
549 // we check if content is richly editable - because those input field behave other than plain text ones
550 // sometimes they may consists a node structure and they need special approach
551 if (innerNode->rendererIsRichlyEditable()) {
552 // point gets inner node local coordinates
553 point = flooredIntPoint(result.localPoint());
554 IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true);
556 // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone
557 // will have a better idea how to solve it
558 // here we are getting innerNode from HitTestResult - unfortunately this is a kind of high level node
559 // in the code below I am trying to obtain low level node - #text - to get its coordinates and size
561 // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user
562 // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field
563 // node, not outside of it
564 Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode();
566 if (!deepInnerNode || !deepInnerNode->renderer())
569 // so we get a base node rectange
570 IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true);
572 // we modify our local point to adjust it to base node local coordinates
573 point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y());
575 // if we are outside the rect we cheat, that we are just inside of it
578 else if (point.y() >= deepNodeRect.height())
579 point.setY(deepNodeRect.height() - 1);
581 // visible position created - caret ready to set
582 visiblePos = deepInnerNode->renderer()->positionForPoint(point);
583 if (visiblePos.isNull())
586 // for plain text input fields we can get only a caret bounding box
587 if (!controller->isCaret() || !controller->caretRenderer())
590 const Node* node = controller->start().deprecatedNode();
591 if (!node || !node->renderer())
594 Element* currentRootEditableElement = node->rootEditableElement();
595 Element* newRootEditableElement = innerNode->rootEditableElement();
596 if (currentRootEditableElement != newRootEditableElement)
599 IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true);
601 // The below wirtten code is not correct way to implement. Presntly the is no
602 // other working way. To be replaced by better logic
603 // here we also cheat input field that we actually are just inside of if
604 IntPoint focusedFramePoint = frame->view()->windowToContents(pos);
605 IntPoint oldFocusedFramePoint = focusedFramePoint;
607 const int boundariesWidth = 2;
608 if (focusedFramePoint.x() < rect.x())
609 focusedFramePoint.setX(rect.x());
610 else if (focusedFramePoint.x() > rect.maxX())
611 focusedFramePoint.setX(rect.maxX());
612 if (focusedFramePoint.y() < rect.y() + boundariesWidth)
613 focusedFramePoint.setY(rect.y() + boundariesWidth);
614 else if (focusedFramePoint.y() >= rect.maxY() - boundariesWidth)
615 focusedFramePoint.setY(rect.maxY() - boundariesWidth - 1);
617 int diffX = focusedFramePoint.x() - oldFocusedFramePoint.x();
618 int diffY = focusedFramePoint.y() - oldFocusedFramePoint.y();
619 point.setX((point.x())+diffX);
620 point.setY((point.y())+diffY);
622 // hit test with fake (adjusted) coordinates
623 IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point);
624 HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
626 if (!newResult.isContentEditable())
629 Node* newInnerNode = newResult.innerNode();
631 if (!newInnerNode || !newInnerNode->renderer())
634 // visible position created
635 visiblePos = newInnerNode->renderer()->positionForPoint(newResult.localPoint());
636 if (visiblePos.isNull())
640 // create visible selection from visible position
641 VisibleSelection newSelection = VisibleSelection(visiblePos);
642 controller->setSelection(newSelection, CharacterGranularity);
643 // after setting selection caret blinking is suspended by default so we are unsuspedning it
644 controller->setCaretBlinkingSuspended(false);
649 void WebPage::getCaretPosition(IntRect& rect)
651 Frame* frame = m_page->focusController()->focusedOrMainFrame();
655 FrameSelection* controller = frame->selection();
659 Node* node = controller->start().deprecatedNode();
660 if (!node || !node->renderer() || !node->isContentEditable())
663 if (controller->isCaret()) {
664 FrameView* frameView = frame->view();
668 rect = frameView->contentsToWindow(controller->absoluteCaretBounds());
673 #if ENABLE(TIZEN_ISF_PORT)
674 void WebPage::didCancelComposition(Node* valueChangedNode)
676 Frame* frame = m_page->focusController()->focusedOrMainFrame();
677 if (!frame || frame->editor()->ignoreCompositionSelectionChange() || !valueChangedNode->containsIncludingShadowDOM(frame->editor()->compositionNode()))
680 frame->editor()->cancelComposition();
681 send(Messages::WebPageProxy::DidCancelComposition());
684 void WebPage::prepareKeyDownEvent()
686 m_prepareKeyDownEvent = true;
687 m_keyPressCommands.clear();
690 void WebPage::swapKeyPressCommands(Vector<OwnPtr<KeyPressCommand> >& commands)
692 m_keyPressCommands.swap(commands);
695 void WebPage::getCursorOffset(int& offset)
698 Frame* frame = m_page->focusController()->focusedOrMainFrame();
699 if (!frame || !frame->editor()->canEdit())
702 Position base = frame->selection()->base();
703 Node* baseNode = base.containerNode();
705 offset = baseNode->isTextNode() ? base.offsetInContainerNode() : 0;
708 void WebPage::getSurroundingTextAndCursorOffset(String& text, int& offset)
713 Frame* frame = m_page->focusController()->focusedOrMainFrame();
714 if (!frame || !frame->editor()->canEdit())
717 Position base = frame->selection()->base();
718 Node* baseNode = base.containerNode();
719 if (baseNode && baseNode->isTextNode()) {
720 text = baseNode->textContent();
721 offset = base.offsetInContainerNode();
725 void WebPage::getSelectionRect(bool isOnlyEditable, IntRect& rect)
729 Frame* frame = m_page->focusController()->focusedFrame();
730 if (!frame || !frame->view())
733 FrameSelection* selection = frame->selection();
734 Node* node = selection->start().deprecatedNode();
735 if (!node || !node->renderer() || (isOnlyEditable && !node->isContentEditable()))
738 if (selection->isCaret())
739 rect = frame->view()->contentsToWindow(selection->absoluteCaretBounds());
740 else if (selection->isRange())
741 rect = frame->view()->contentsToWindow(enclosingIntRect(selection->bounds(false)));
744 void WebPage::deleteSurroundingText(int offset, int count)
746 Frame* frame = m_page->focusController()->focusedOrMainFrame();
747 if (!frame || !frame->editor()->canEdit())
750 if (m_prepareKeyDownEvent) {
751 m_keyPressCommands.append(adoptPtr(new DeleteTextKeyPressCommand(offset, count)));
755 Position base(frame->selection()->base());
756 offset += base.offsetInContainerNode();
757 base.moveToOffset(offset);
758 Position extent(base);
759 extent.moveToOffset(offset + count);
760 VisibleSelection selection(base, extent);
761 if (!selection.isRange())
764 frame->selection()->setSelection(selection);
765 frame->editor()->deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
769 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION) || ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
770 void WebPage::setFocusedInputElementValue(const String& inputValue)
772 Frame* frame = m_page->focusController()->focusedOrMainFrame();
773 if (!frame || !frame->document() || !frame->document()->focusedNode())
776 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
780 inputElement->toNode()->dispatchFocusEvent(0);
781 inputElement->setValue(inputValue, DispatchChangeEvent);
784 void WebPage::getFocusedInputElementValue(String& inputValue)
786 inputValue = String();
788 Frame* frame = m_page->focusController()->focusedOrMainFrame();
789 if (!frame || !frame->document() || !frame->document()->focusedNode())
792 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
796 inputValue = inputElement->value();
800 #if ENABLE(TIZEN_DATALIST_ELEMENT)
801 void WebPage::getFocusedInputElementDataList(Vector<String>& optionList)
803 Frame* frame = m_page->focusController()->focusedOrMainFrame();
804 if (!frame || !frame->document())
807 Node* node = frame->document()->focusedNode();
811 HTMLInputElement* input = node->toInputElement();
815 HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
819 RefPtr<HTMLCollection> options = static_cast<HTMLDataListElement*>(dataList)->options();
820 for (unsigned i = 0; Node* node = options->item(i); i++) {
821 HTMLOptionElement* optionElement = static_cast<HTMLOptionElement*>(node);
822 String value = optionElement->value();
823 optionList.append(value);
828 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
829 static IntRect getNodeRect(Node* node, Node* focusableNode, bool isImage)
835 IntRect imageNodeRect = pixelSnappedIntRect(node->getRect());
836 if (!focusableNode->renderRect(&isReplaced).isEmpty() && imageNodeRect.contains(pixelSnappedIntRect(focusableNode->getRect()))) {
837 // If render rect of focusableNode is empty and rect of imageNode include rect of focusableNode,
838 // we have to get rect of focusableNode.
839 // for example - The rect of google logo image in www.google.com pc site's search result page is bigger than rect of focusableNode.
840 // for example - The rect of category menu image in www.gmarket.co.kr pc site is bigger than rect of focusableNode.
841 rect = pixelSnappedIntRect(focusableNode->getRect());
844 // otherwise we have to get rect of imageNode.
845 // for example - The render rect of images in www.pudelek.pl is empty.
846 // for example - The rect of focusableNode of 'Test your browser GO' image in peacekeeper.futuremark.com is bigger than rect of 'Test your browser GO' image.
847 rect = imageNodeRect;
848 focusableNode = node;
851 // If focusedNode have multiple child nodes, we have to unite rect of child nodes.
852 // for example - links in www.google.com's search result page.
854 for (Node* childNode = focusableNode->firstChild(); childNode; childNode = childNode->traverseNextNode(focusableNode)) {
856 if (focusableNode->renderRect(&isReplaced).contains(childNode->getRect()))
857 tempRect.unite(pixelSnappedIntRect(childNode->getRect()));
860 // If tempRect is empty or rect of focusableNode include tempRect,
861 // we have to get rect of focusableNode.
862 // for example - list menu item in m.naver.com.
863 // otherwise we have to get rect of tempRect.
864 // getRect API do not return correct rect if the node is a container node,
865 // hence using absoluteBoundingBoxRect to get the correct bounding rect.
866 LayoutRect renderRect = focusableNode->renderer() ? focusableNode->renderer()->absoluteBoundingBoxRect() : focusableNode->getRect();
867 if (tempRect.isEmpty() || renderRect.contains(tempRect))
868 rect = pixelSnappedIntRect(renderRect);
873 // We have to get render rect from ancestor node if current rect is empty.
874 // for example - The rect of naver logo image in www.naver.com pc site is empty.
876 for (Node* loopNode = focusableNode; loopNode && rect.isEmpty(); loopNode = loopNode->parentNode()) {
877 RenderObject* renderer = loopNode->renderer();
878 if (renderer && renderer->isRoot())
881 rect = pixelSnappedIntRect(loopNode->renderRect(&isReplaced));
884 Frame* nodeFrame = focusableNode->document()->frame();
886 while (nodeFrame && (owner = nodeFrame->ownerElement())) {
887 rect.moveBy(owner->getRect().pixelSnappedLocation());
888 nodeFrame = owner->document()->frame();
891 // The y position of tab menu item in www.google.com is negative value,
892 // so we do not want to draw focus ring in that case.
893 if ((rect.maxX() < 0) || (rect.maxY() < 0))
900 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
901 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
902 static bool isClickableOrFocusable(Node* focusableNode)
907 if (focusableNode->disabled())
909 if (!focusableNode->inDocument())
911 if (!focusableNode->renderer() || focusableNode->renderer()->style()->visibility() != VISIBLE)
913 if (focusableNode->isFocusable()) {
914 if (focusableNode->isLink()
915 || focusableNode->hasTagName(HTMLNames::inputTag)
916 || focusableNode->hasTagName(HTMLNames::selectTag)
917 || focusableNode->hasTagName(HTMLNames::buttonTag))
920 if (focusableNode->supportsFocus()
921 || focusableNode->hasEventListeners(eventNames().clickEvent)
922 || focusableNode->hasEventListeners(eventNames().mousedownEvent)
923 || focusableNode->hasEventListeners(eventNames().mouseupEvent)) {
929 #if ENABLE(TOUCH_ADJUSTMENT)
930 static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page, const IntPoint& point, const IntSize& area)
932 static IntRect getFocusedRect(HitTestResult hitTestResult, Page* page)
935 Node* node = hitTestResult.innerNode();
936 #if ENABLE(TOUCH_ADJUSTMENT)
937 Node* adjustedNode = 0;
938 IntPoint adustedPoint;
939 Frame* mainFrame = page->mainFrame();
940 if (!isClickableOrFocusable(node))
941 mainFrame->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adustedPoint, adjustedNode);
949 bool isFocusRingDrawable = false;
950 Node* focusableNode = node;
951 while (focusableNode) {
952 RenderObject* renderer = focusableNode->renderer();
953 if (renderer && (renderer->isBody() || renderer->isRenderView() || renderer->isRoot()))
956 if (isClickableOrFocusable(focusableNode)) {
957 isFocusRingDrawable = true;
961 focusableNode = focusableNode->parentNode();
964 // Don't draw focus ring if child is focusable or has trigger
965 if (focusableNode && focusableNode->isContainerNode() && !focusableNode->isLink()) {
966 WebCore::Node *child = static_cast<const ContainerNode*>(focusableNode)->firstChild();
968 if( child->supportsFocus()
969 || child->hasEventListeners(eventNames().clickEvent)
970 || child->hasEventListeners(eventNames().mousedownEvent)
971 || child->hasEventListeners(eventNames().mouseupEvent)) {
974 child = child->traverseNextNode(focusableNode);
978 if (!isFocusRingDrawable) {
979 if (node->hasTagName(HTMLNames::imgTag))
980 return getNodeRect(node, node, !hitTestResult.absoluteImageURL().isEmpty());
985 return getNodeRect(node, focusableNode, !hitTestResult.absoluteImageURL().isEmpty());
989 #if ENABLE(TOUCH_ADJUSTMENT)
990 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, const IntSize& area, WebHitTestResult::Data& hitTestResultData)
992 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, WebHitTestResult::Data& hitTestResultData)
995 Frame* frame = m_page->mainFrame();
996 FrameView* frameView = frame->view();
1000 HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), false);
1001 hitTestResultData.absoluteImageURL = hitTestResult.absoluteImageURL().string();
1002 hitTestResultData.absoluteLinkURL = hitTestResult.absoluteLinkURL().string();
1003 hitTestResultData.absoluteMediaURL = hitTestResult.absoluteMediaURL().string();
1004 hitTestResultData.linkLabel = hitTestResult.textContent();
1005 hitTestResultData.linkTitle = hitTestResult.titleDisplayString();
1006 hitTestResultData.isContentEditable = hitTestResult.isContentEditable();
1007 #if ENABLE(TIZEN_DRAG_SUPPORT)
1008 hitTestResultData.isDragSupport = hitTestResult.isDragSupport();
1011 int context = WebHitTestResult::HitTestResultContextDocument;
1013 if (!hitTestResult.absoluteLinkURL().isEmpty())
1014 context |= WebHitTestResult::HitTestResultContextLink;
1015 if (!hitTestResult.absoluteImageURL().isEmpty())
1016 context |= WebHitTestResult::HitTestResultContextImage;
1017 if (!hitTestResult.absoluteMediaURL().isEmpty())
1018 context |= WebHitTestResult::HitTestResultContextMedia;
1019 if (hitTestResult.isSelected())
1020 context |= WebHitTestResult::HitTestResultContextSelection;
1021 if (hitTestResult.isContentEditable())
1022 context |= WebHitTestResult::HitTestResultContextEditable;
1023 if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode())
1024 context |= WebHitTestResult::HitTestResultContextText;
1026 hitTestResultData.context = context;
1027 hitTestResultData.hitTestMode = hitTestMode;
1029 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
1030 #if ENABLE(TOUCH_ADJUSTMENT)
1031 hitTestResultData.focusedRect = getFocusedRect(hitTestResult, m_page.get(), point, area);
1033 hitTestResultData.focusedRect = getFocusedRect(hitTestResult, m_page.get());
1036 // Don't display FocusRect if the size is too big..
1037 IntRect framerect = frameView->visibleContentRect(true);
1038 if (hitTestResultData.focusedRect.width() > (0.8 * framerect.width())
1039 && hitTestResultData.focusedRect.height() > (0.8 * framerect.height())) {
1040 hitTestResultData.focusedRect = IntRect();
1043 if (hitTestResult.innerNode() && hitTestResult.innerNode()->renderer() && hitTestResult.innerNode()->renderer()->style()) {
1044 hitTestResultData.focusedColor = hitTestResult.innerNode()->renderer()->style()->tapHighlightColor();
1045 if (!hitTestResultData.focusedColor.hasAlpha())
1046 hitTestResultData.focusedColor = Color(hitTestResultData.focusedColor.red(), hitTestResultData.focusedColor.green(), hitTestResultData.focusedColor.blue(), RenderStyle::initialTapHighlightColor().alpha());
1050 if (hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeNodeData) {
1051 WebCore::Node* hitNode = hitTestResult.innerNonSharedNode();
1053 hitTestResultData.nodeData.nodeValue = hitNode->nodeValue();
1055 if ((hitTestResultData.context & WebHitTestResult::HitTestResultContextText) && hitNode->parentNode())
1056 hitNode = hitNode->parentNode(); // if hittest inner node is Text node, fill tagName with parent node's info and fill attributeMap with parent node's attributes.
1058 if (hitNode->isElementNode()) {
1059 WebCore::Element* hitElement = static_cast<WebCore::Element*>(hitNode);
1061 hitTestResultData.nodeData.tagName = hitElement->tagName();
1065 WebCore::NamedNodeMap* namedNodeMap = hitNode->attributes();
1067 for (size_t i = 0; i < namedNodeMap->length(); i++) {
1068 const WebCore::Attribute* attribute = namedNodeMap->element()->attributeItem(i);
1069 String key = attribute->name().toString();
1070 String value = attribute->value();
1071 hitTestResultData.nodeData.attributeMap.add(key, value);
1077 if ((hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeImageData) && (hitTestResultData.context & WebHitTestResult::HitTestResultContextImage)) {
1078 WebCore::Image* hitImage = hitTestResult.image();
1079 if (hitImage && hitImage->data() && hitImage->data()->data()) {
1080 hitTestResultData.imageData.data.append(hitImage->data()->data(), hitImage->data()->size());
1081 hitTestResultData.imageData.fileNameExtension = hitImage->filenameExtension();
1087 #if ENABLE(TIZEN_WEB_STORAGE)
1088 void WebPage::getStorageQuotaBytes(uint64_t callbackID)
1090 uint32_t quota = m_page->group().groupSettings()->localStorageQuotaBytes();
1091 send(Messages::WebPageProxy::DidGetWebStorageQuotaBytes(quota, callbackID));
1094 void WebPage::setStorageQuotaBytes(uint32_t quota)
1096 m_page->group().groupSettings()->setLocalStorageQuotaBytes(quota);
1100 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
1101 void WebPage::setClipboardDataForPaste(const String& data, const String& type)
1103 #if ENABLE(TIZEN_PASTEBOARD)
1104 // FIXME: Should move to EditorClient like Clipboard
1105 Pasteboard::generalPasteboard()->setDataWithType(data, type);
1107 Frame* mainFrame = m_page->mainFrame();
1111 mainFrame->editor()->client()->setClipboardDataForPaste(data, type);
1116 void WebPage::suspendJavaScriptAndResources()
1118 Frame* mainFrame = m_page->mainFrame();
1122 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1123 frame->document()->suspendScheduledTasks(WebCore::ActiveDOMObject::PageWillBeSuspended);
1124 mainFrame->loader()->suspendAllLoaders();
1127 void WebPage::resumeJavaScriptAndResources()
1129 Frame* mainFrame = m_page->mainFrame();
1133 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1134 frame->document()->resumeScheduledTasks();
1135 mainFrame->loader()->resumeAllLoaders();
1138 void WebPage::suspendAnimations()
1140 Frame* mainFrame = m_page->mainFrame();
1144 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1145 frame->animation()->suspendAnimationsForDocument(frame->document());
1148 void WebPage::resumeAnimations()
1150 Frame* mainFrame = m_page->mainFrame();
1154 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1155 frame->animation()->resumeAnimationsForDocument(frame->document());
1158 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
1159 void WebPage::suspendAnimationController()
1161 if (!m_suspendedAnimationController) {
1162 Frame* mainFrame = m_page->mainFrame();
1166 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1167 frame->document()->suspendScriptedAnimationControllerCallbacks();
1169 m_suspendedAnimationController = true;
1173 void WebPage::resumeAnimationController()
1175 if (m_suspendedAnimationController) {
1176 Frame* mainFrame = m_page->mainFrame();
1180 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1181 frame->document()->resumeScriptedAnimationControllerCallbacks();
1183 m_suspendedAnimationController = false;
1188 #if ENABLE(TIZEN_REMOTE_WEB_INSPECTOR)
1189 void WebPage::startInspectorServer(uint32_t port, uint32_t& allocatedPort)
1191 bool ret = WebInspectorServerTizen::server()->startServer(port);
1193 allocatedPort = WebInspectorServerTizen::server()->getServerPort();
1198 void WebPage::stopInspectorServer(bool& result)
1200 result = WebInspectorServerTizen::server()->stopServer();
1204 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1205 void WebPage::scrollOverflowWithTrajectoryVector(const WebCore::FloatPoint& trajectoryVector)
1207 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1210 frame->eventHandler()->scrollOverflow(trajectoryVector);
1214 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1215 void WebPage::scrollOverflow(const WebCore::FloatPoint& delta, bool& scrolled)
1217 scrolled = m_page->focusController()->focusedOrMainFrame()->eventHandler()->scrollOverflow(delta);
1220 void WebPage::setPressedNodeAtPoint(const IntPoint& point, bool checkOverflowLayer, bool& pressed, uint32_t& id)
1222 RenderObject* renderer = 0;
1224 pressed = m_page->mainFrame()->eventHandler()->setMousePressNodeAtPoint(point, checkOverflowLayer, renderer);
1225 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1226 if (pressed && renderer)
1227 id = toWebGraphicsLayer(renderer->enclosingLayer()->layerForScrollingContents())->id();
1232 void WebPage::executeEditCommandWithArgument(const String& commandName, const String& argument)
1234 executeEditingCommand(commandName, argument);
1237 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
1238 void WebPage::suspendPlugin()
1240 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1241 FrameView* view = frame->view();
1245 const HashSet<RefPtr<Widget> >* children = view->children();
1248 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1249 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1250 Widget* widget = (*it).get();
1251 if (widget->isPluginViewBase()) {
1252 PluginView* pluginView = static_cast<PluginView*>(widget);
1254 pluginView->suspendPlugin();
1260 void WebPage::resumePlugin()
1262 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1263 FrameView* view = frame->view();
1267 const HashSet<RefPtr<Widget> >* children = view->children();
1270 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1271 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1272 Widget* widget = (*it).get();
1273 if (widget->isPluginViewBase()) {
1274 PluginView* pluginView = static_cast<PluginView*>(widget);
1276 pluginView->resumePlugin();
1283 #if ENABLE(TIZEN_MULTIPLE_SELECT)
1284 void WebPage::didChangeSelectedIndexForActivePopupMenuMultiple(Vector<int32_t> newIndex)
1286 if (!m_activePopupMenu)
1289 m_activePopupMenu->client()->popupDidHide();
1291 size_t indexSize = newIndex.size();
1292 for (size_t i = 0; i < indexSize; i++)
1293 m_activePopupMenu->didChangeSelectedIndex(newIndex.at(i));
1298 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
1299 void WebPage::startOfflinePageSave(String subresourceFolderName)
1301 WebPageSerializerTizen::getSerializedPageContent(this, subresourceFolderName);
1305 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1306 void WebPage::selectClosestWord(const IntPoint& point, bool& result)
1310 Frame* mainFrame = m_page->mainFrame();
1311 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1313 HitTestResult hitTestResult = mainFrame->eventHandler()->hitTestResultAtPoint(m_page->mainFrame()->view()->windowToContents(point), false);
1315 Node* node = hitTestResult.innerNonSharedNode();
1319 Frame* newFocusFrame = node->document()->frame();
1320 if (focusedFrame != newFocusFrame) {
1321 m_page->focusController()->setFocusedFrame(newFocusFrame);
1322 focusedFrame = newFocusFrame;
1325 HTMLInputElement* inputElement = node->toInputElement();
1327 if (hitTestResult.isContentEditable()) {
1328 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1329 if (!inputElement || (inputElement
1330 && !inputElement->isDateField() && !inputElement->isDateTimeField() && !inputElement->isDateTimeLocalField()
1331 && !inputElement->isMonthField() && !inputElement->isTimeField() && !inputElement->isWeekField())) {
1332 result = setCaretPosition(point);
1336 result = setCaretPosition(point);
1341 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1342 if (!node->isTextNode() && !inputElement)
1344 if (!node->isTextNode())
1348 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1350 && (inputElement->isDateField() || inputElement->isDateTimeField() || inputElement->isDateTimeLocalField()
1351 || inputElement->isMonthField() || inputElement->isTimeField() || inputElement->isWeekField())) {
1352 if (inputElement->value().isEmpty())
1357 for (Node* node = hitTestResult.innerNonSharedNode(); node; node = node->parentNode()) {
1358 if (node->isFocusable()) {
1359 // Text selection shoud not be started when text of <button> tag is selected.
1360 if (node->hasTagName(HTMLNames::buttonTag))
1363 if (inputElement && inputElement->isTextButton())
1370 FrameSelection* frameSelection = focusedFrame->selection();
1372 VisiblePosition position = mainFrame->visiblePositionForPoint(point);
1373 VisibleSelection selection(position);
1375 // This changes just the 'start' and 'end' positions of the VisibleSelection
1376 selection.expandUsingGranularity(WordGranularity);
1378 FrameSelection::SetSelectionOptions options = FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | FrameSelection::DoNotSetFocus;
1379 frameSelection->setSelection(VisibleSelection(selection.start(), selection.end()), options);
1381 if (!frameSelection->isRange())
1384 // This changes just the 'start' and 'end' positions of the VisibleSelection
1385 // Find handlers positions
1386 IntRect leftRect, rightRect;
1387 getSelectionHandlers(leftRect, rightRect);
1388 if (leftRect.size().isZero() && rightRect.size().isZero()) {
1389 // Sometimes there is no selected text, but isNone() returns TRUE
1390 // in this case ewk_frame_selection_handlers_get() returns FALSE and handlers are invalid
1391 // Workaround - clear the selection.
1392 // Better solution would be to modify the ewk_frame_select_closest_word()
1393 // to not select anything in the first place (for example - don't call setSelection()
1394 // if there is nothing under the cursor).
1395 selectionClearAllSelection(m_page->mainFrame());
1402 void WebPage::setLeftSelection(const IntPoint& point, const int direction, int& result)
1404 result = HandleMovingDirectionNone;
1406 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1407 FrameSelection* frameSelection = focusedFrame->selection();
1408 if (!frameSelection->isRange())
1411 Node* selectionEndNode = frameSelection->end().deprecatedNode();
1412 if (!selectionEndNode || !selectionEndNode->renderer())
1415 FrameView* frameView = focusedFrame->view();
1419 IntPoint pos = frameView->windowToContents(point);
1420 IntRect leftRect, rightRect;
1421 getSelectionHandlers(leftRect, rightRect);
1423 if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) {
1424 const int boundariesWidth = 2;
1426 IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1427 // here we cheat input field that we actually are just inside of if
1428 if (pos.y() < rect.y() + boundariesWidth)
1429 pos.setY(rect.y() + boundariesWidth);
1430 else if (pos.y() >= rect.maxY() - boundariesWidth)
1431 pos.setY(rect.maxY() - boundariesWidth - 1);
1434 OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1435 Position base = frameSelection->base();
1436 Position extent = frameSelection->extent();
1438 Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
1440 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1441 // Check if the new position is before the extent's position
1442 if (newSelectionStartNode
1443 && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable()) {
1444 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1445 // We do it, because without this, the other modification of the selection
1446 // would destroy the 'start' and/or 'end' positions and set them to
1447 // the 'base'/'extent' positions accordingly
1448 VisibleSelection sel(frameSelection->start(), frameSelection->end());
1449 frameSelection->setSelection(sel);
1451 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1452 focusedFrame->view()->setProhibitsScrolling(true);
1454 if (direction == HandleMovingDirectionNormal) {
1455 if (comparePositions(position->deepEquivalent(), extent) < 0) {
1456 frameSelection->setBase(*position);
1457 result = HandleMovingDirectionNormal;
1458 } else if (comparePositions(position->deepEquivalent(), extent) > 0) {
1459 frameSelection->setExtent(*position);
1460 frameSelection->setBase(extent);
1461 result = HandleMovingDirectionReverse;
1463 } else if (direction == HandleMovingDirectionReverse) {
1464 if (comparePositions(position->deepEquivalent(), base) > 0) {
1465 frameSelection->setExtent(*position);
1466 result = HandleMovingDirectionReverse;
1467 } else if (comparePositions(position->deepEquivalent(), base) < 0) {
1468 frameSelection->setBase(*position);
1469 frameSelection->setExtent(base);
1470 result = HandleMovingDirectionNormal;
1474 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1475 // This forces webkit to show selection
1476 // m_coreFrame->invalidateSelection();
1480 void WebPage::setRightSelection(const IntPoint& point, const int direction, int& result)
1482 result = HandleMovingDirectionNone;
1484 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1485 FrameSelection* frameSelection = focusedFrame->selection();
1487 if (!frameSelection->isRange())
1490 Node* selectionStartNode = frameSelection->start().deprecatedNode();
1491 if (!selectionStartNode || !selectionStartNode->renderer())
1494 FrameView* frameView = focusedFrame->view();
1498 IntPoint pos = frameView->windowToContents(point);
1499 if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) {
1500 const int boundariesWidth = 2;
1502 IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1503 // here we cheat input field that we actually are just inside of if
1504 if (pos.y() < rect.y() + boundariesWidth)
1505 pos.setY(rect.y() + boundariesWidth);
1506 else if (pos.y() >= rect.maxY() - boundariesWidth)
1507 pos.setY(rect.maxY() - boundariesWidth - 1);
1510 OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1511 Position base = frameSelection->base();
1512 Position extent = frameSelection->extent();
1514 Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
1516 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1517 // Check if the new position is after the base's position
1518 if (newSelectionEndNode
1519 && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable()) {
1520 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1521 // We do it, because without this, the other modifications of the selection
1522 // would destroy the 'start' and/or 'end' positions and set them to
1523 // the 'base'/'extent' positions accordingly
1525 VisibleSelection sel(frameSelection->start(), frameSelection->end());
1526 frameSelection->setSelection(sel);
1528 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1529 focusedFrame->view()->setProhibitsScrolling(true);
1531 if (direction == HandleMovingDirectionNormal) {
1532 if (comparePositions(position->deepEquivalent(), base) > 0) {
1533 frameSelection->setExtent(*position);
1534 result = HandleMovingDirectionNormal;
1535 } else if (comparePositions(position->deepEquivalent(), base) < 0) {
1536 frameSelection->setBase(*position);
1537 frameSelection->setExtent(base);
1538 result = HandleMovingDirectionReverse;
1540 } else if (direction == HandleMovingDirectionReverse) {
1541 if (comparePositions(position->deepEquivalent(), extent) < 0) {
1542 frameSelection->setBase(*position);
1543 result = HandleMovingDirectionReverse;
1544 } else if (comparePositions(position->deepEquivalent(), extent) > 0) {
1545 frameSelection->setExtent(*position);
1546 frameSelection->setBase(extent);
1547 result = HandleMovingDirectionNormal;
1551 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1555 void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect)
1557 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1558 if (!focusedFrame->selection()->isRange())
1561 // Is this check necessary? Leaving it for safety.
1562 RenderView* root = focusedFrame->contentRenderer();
1566 RefPtr<Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
1568 Vector<IntRect> rects;
1569 selectedRange->boundingBoxEx(rects, true);
1571 unsigned size = rects.size();
1573 leftRect = rects[0];
1574 rightRect = rects[size-1];
1576 // If selection rect size is greater than editor rect size because of round operation,
1577 // selection rect size should be changed to editor rect size.
1579 Element* rootEditableElement = focusedFrame->selection()->rootEditableElement();
1580 if (rootEditableElement) {
1581 IntRect editorRect = nodeRect(rootEditableElement);
1583 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1584 if (m_editorState.editorRect != editorRect) {
1585 EditorState state = editorState();
1586 state.updateEditorRectOnly = true;
1587 setEditorState(state);
1588 send(Messages::WebPageProxy::EditorStateChanged(state));
1592 if (leftRect.maxY() > editorRect.maxY()) {
1593 leftRect.setY(editorRect.y());
1594 leftRect.setHeight(editorRect.height());
1597 if (rightRect.maxY() > editorRect.maxY()) {
1598 rightRect.setY(editorRect.y());
1599 rightRect.setHeight(editorRect.height());
1604 // prevent from selecting zero-length selection
1605 if (leftRect.x() == rightRect.x() + rightRect.width()
1606 && leftRect.y() == rightRect.y())
1609 FrameView* frameView = focusedFrame->view();
1613 leftRect = frameView->contentsToWindow(leftRect);
1614 rightRect = frameView->contentsToWindow(rightRect);
1618 void WebPage::getSelectionText(String& result)
1620 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1621 result = focusedFrame->editor()->selectedText();
1624 void WebPage::selectionRangeClear(bool& result)
1628 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1629 FrameSelection* frameSelection = focusedFrame->selection();
1630 if (frameSelection && frameSelection->isRange() && frameSelection->isContentEditable()) {
1631 VisiblePosition visiblePos(frameSelection->extent());
1632 if (visiblePos.isNull())
1635 focusedFrame->editor()->setIgnoreCompositionSelectionChange(true);
1636 frameSelection->setSelection(VisibleSelection(visiblePos), CharacterGranularity);
1637 focusedFrame->editor()->setIgnoreCompositionSelectionChange(false);
1639 frameSelection->setCaretBlinkingSuspended(false);
1641 selectionClearAllSelection(m_page->mainFrame());
1646 void WebPage::selectionClearAllSelection(Frame* frame)
1651 FrameSelection* frameSelection = frame->selection();
1653 frameSelection->clear();
1658 if (frame->tree()->childCount() > 0) {
1659 if (frame->tree()->firstChild())
1660 selectionClearAllSelection(frame->tree()->firstChild());
1661 } else if (frame->tree()->nextSibling())
1662 selectionClearAllSelection(frame->tree()->nextSibling());
1665 void WebPage::scrollContentByCharacter(const IntPoint&, int direction, bool& result)
1669 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1673 FrameSelection* frameSelection = focusedFrame->selection();
1674 if (!frameSelection)
1677 VisiblePosition currentPosition = frameSelection->selection().visibleStart();
1679 if (isStartOfLine(currentPosition))
1682 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionBackward, CharacterGranularity, UserTriggered);
1684 if (isEndOfLine(currentPosition))
1687 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity, UserTriggered);
1691 void WebPage::scrollContentByLine(const IntPoint&, int direction, bool& result)
1695 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1699 FrameSelection* frameSelection = focusedFrame->selection();
1700 if (!frameSelection)
1703 VisiblePosition currentPosition = frameSelection->selection().visibleStart();
1705 if (inSameLine(currentPosition, previousLinePosition(currentPosition, 0)))
1708 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionBackward, LineGranularity, UserTriggered);
1710 if (inSameLine(currentPosition, nextLinePosition(currentPosition, 0)))
1713 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, LineGranularity, UserTriggered);
1718 #if ENABLE(TIZEN_LINK_MAGNIFIER)
1719 void WebPage::getLinkMagnifierRect(const IntPoint& position, const IntSize& size)
1721 send(Messages::WebPageProxy::DidGetLinkMagnifierRect(position, LinkMagnifier::rect(this, position, size)));
1725 #if ENABLE(TIZEN_SCREEN_READER)
1726 static void sendScreenReaderFocusRect(WebPage* page, Node* node)
1728 bool isImage = false;
1729 if (node->isElementNode()) {
1730 Element* element = static_cast<Element*>(node);
1731 isImage = !element->getAttribute(element->imageSourceAttributeName()).isEmpty();
1734 page->send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(getNodeRect(node, node, isImage)));
1737 void WebPage::moveScreenReaderFocus(bool forward, bool& result)
1739 if (!m_screenReader)
1740 m_screenReader = ScreenReader::create(this);
1742 if (!m_screenReader->moveFocus(forward)) {
1744 send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(IntRect()));
1748 sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1752 void WebPage::moveScreenReaderFocusByPoint(const IntPoint& point)
1754 if (!m_screenReader)
1755 m_screenReader = ScreenReader::create(this);
1757 if (!m_screenReader->moveFocus(point))
1760 sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1763 void WebPage::clearScreenReaderFocus()
1765 if (!m_screenReader)
1768 m_screenReader->clearFocus();
1771 void WebPage::raiseTapEvent(const IntPoint& position, const IntPoint& globalPosition, bool& result)
1775 #if ENABLE(GESTURE_EVENTS)
1776 Frame* frame = m_page->mainFrame();
1780 Vector<WebPlatformTouchPoint> touchPoints;
1781 touchPoints.append(WebPlatformTouchPoint(0, WebPlatformTouchPoint::TouchPressed, globalPosition, position));
1783 WebTouchEvent touchStartEvent(WebEvent::TouchStart, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1784 bool handled = frame->eventHandler()->handleTouchEvent(platform(touchStartEvent));
1786 touchPoints.at(0).setState(WebPlatformTouchPoint::TouchReleased);
1788 WebTouchEvent touchEndEvent(WebEvent::TouchEnd, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1789 handled |= frame->eventHandler()->handleTouchEvent(platform(touchEndEvent));
1792 WebGestureEvent gestureEvent(WebEvent::GestureSingleTap, position, globalPosition, WebEvent::Modifiers(0), ecore_time_get());
1793 frame->eventHandler()->handleGestureEvent(platform(gestureEvent));
1799 void WebPage::adjustScreenReaderFocusedObjectValue(bool up)
1801 if (!m_screenReader || !m_screenReader->getFocusedNode() || !m_screenReader->getFocusedNode()->toInputElement())
1806 m_screenReader->getFocusedNode()->toInputElement()->stepUp(ec);
1808 m_screenReader->getFocusedNode()->toInputElement()->stepDown(ec);
1811 void WebPage::recalcScreenReaderFocusRect()
1813 if (!m_screenReader || !m_screenReader->getFocusedNode())
1816 sendScreenReaderFocusRect(this, m_screenReader->getFocusedNode());
1819 void WebPage::updateScreenReaderFocus(RenderObject* object)
1821 if (!m_screenReader)
1825 m_screenReader->clearFocus();
1826 else if (!m_screenReader->rendererWillBeDestroyed(object))
1829 send(Messages::WebPageProxy::DidScreenReaderFocusRectChanged(IntRect()));
1832 void WebPage::clearScreenReader()
1834 m_screenReader.clear();
1838 #if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1839 static LayoutRect rectToAbsoluteCoordinates(Frame* initialFrame, const LayoutRect& initialRect)
1841 LayoutRect rect = initialRect;
1842 for (Frame* frame = initialFrame; frame; frame = frame->tree()->parent()) {
1843 RenderBoxModelObject* renderer;
1844 if (frame->ownerElement() && (renderer = frame->ownerElement()->renderBoxModelObject())) {
1846 rect.move(renderer->offsetLeft(), renderer->offsetTop());
1847 } while ((renderer = renderer->offsetParent()));
1848 rect.move(-frame->view()->scrollOffset());
1854 IntRect WebPage::nodeRect(Node* node) const
1860 if (node->hasTagName(HTMLNames::areaTag)) {
1861 HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
1862 HTMLImageElement* image = area->imageElement();
1863 if (!image || !image->renderer())
1866 rect = rectToAbsoluteCoordinates(area->document()->frame(), area->computeRect(area->imageElement()->renderer()));
1867 } else if (node->renderer()) {
1868 if (node->isDocumentNode())
1869 rect = rectToAbsoluteCoordinates(static_cast<Document*>(node)->frame(), static_cast<Document*>(node)->frame()->view()->visibleContentRect());
1871 rect = node->getRect();
1872 rect.intersect(node->renderer()->absoluteClippedOverflowRect());
1873 rect = rectToAbsoluteCoordinates(node->document()->frame(), rect);
1875 rect.move(node->renderer()->style()->borderLeftWidth(), node->renderer()->style()->borderTopWidth());
1876 rect.setWidth(rect.width() - node->renderer()->style()->borderLeftWidth() - node->renderer()->style()->borderRightWidth());
1877 rect.setHeight(rect.height() - node->renderer()->style()->borderTopWidth() - node->renderer()->style()->borderBottomWidth());
1881 return pixelSnappedIntRect(rect);
1885 #if ENABLE(TIZEN_WEBKIT2_POPUP_INTERNAL)
1886 // FIXME: Currently with cached pages, hiding Popup list menu is not working correctly.
1887 // This patch is a fix allowing any popup list menu to get close for any page navigation.
1888 void WebPage::notifyTransitionToCommitted(bool forNewPage)
1890 if (m_activePopupMenu) {
1892 m_activePopupMenu->hide();
1893 m_activePopupMenu = 0;
1898 #if ENABLE(TIZEN_CSP)
1899 void WebPage::setContentSecurityPolicy(const String& policy, uint32_t headerType)
1901 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1905 Document* document = frame->document();
1909 document->contentSecurityPolicy()->didReceiveHeader(policy, static_cast<WebCore::ContentSecurityPolicy::HeaderType>(headerType));
1913 #if ENABLE(TIZEN_INDEXED_DATABASE)
1914 void WebPage::setIndexedDatabaseDirectory(const String& path)
1916 m_page->group().groupSettings()->setIndexedDBDatabasePath(path);
1920 #if ENABLE(TIZEN_WEB_STORAGE)
1921 void WebPage::setLocalStorageDirectory(const String& path)
1923 m_page->settings()->setLocalStorageDatabasePath(path);
1927 #if ENABLE(TIZEN_USE_SETTINGS_FONT)
1928 void WebPage::useSettingsFont()
1930 if (!WebCore::fontCache()->isFontFamliyTizen())
1933 FcInitReinitialize();
1934 WebCore::fontCache()->invalidate();
1936 FrameView* frameView = m_mainFrame->coreFrame()->view();
1940 frameView->forceLayout();
1944 void WebPage::didChangeContents(const IntRect& rect)
1949 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1950 if (!frame || !frame->view() || frame->view()->needsLayout())
1953 #if ENABLE(TIZEN_ISF_PORT) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1954 if (m_editorState.isContentEditable && rect.intersects(m_editorState.editorRect) && frame->selection()->rootEditableElement()) {
1955 IntRect currentEditorRect = nodeRect(frame->selection()->rootEditableElement());
1956 if (m_editorState.editorRect != currentEditorRect) {
1957 m_editorState.editorRect = currentEditorRect;
1958 m_editorState.updateEditorRectOnly = true;
1959 send(Messages::WebPageProxy::EditorStateChanged(m_editorState));
1964 #endif // #if OS(TIZEN)
1966 } // namespace WebKit