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"
132 #include "RenderIFrame.h"
135 #if ENABLE(TIZEN_LINK_MAGNIFIER)
136 #include "LinkMagnifier.h"
139 #if ENABLE(TIZEN_SCREEN_READER)
140 #include "WebEventConversion.h"
143 #if ENABLE(TIZEN_SCREEN_READER) || ENABLE(TIZEN_FOCUS_UI) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
144 #include <WebCore/HTMLAreaElement.h>
147 #if ENABLE(TIZEN_CSP)
148 #include <WebCore/ContentSecurityPolicy.h>
151 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
152 #include "WebPageSerializerTizen.h"
155 #if ENABLE(TIZEN_USE_SETTINGS_FONT)
156 #include "fontconfig/fontconfig.h"
157 #include <WebCore/FontCache.h>
158 #include <WebCore/PageCache.h>
161 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
162 #include "visible_units.h"
164 #endif // #if OS(TIZEN)
166 using namespace WebCore;
170 void WebPage::platformInitialize()
172 #if ENABLE(TIZEN_DEVICE_ORIENTATION)
173 WebCore::provideDeviceMotionTo(m_page.get(), new DeviceMotionClientTizen);
174 WebCore::provideDeviceOrientationTo(m_page.get(), new DeviceOrientationClientTizen);
178 #if ENABLE(TIZEN_PREFERENCE)
179 void WebPage::platformPreferencesDidChange(const WebPreferencesStore& store)
181 Settings* settings = m_page->settings();
182 settings->setInteractiveFormValidationEnabled(store.getBoolValueForKey(WebPreferencesKey::interactiveFormValidationEnabledKey()));
183 settings->setUsesEncodingDetector(store.getBoolValueForKey(WebPreferencesKey::usesEncodingDetectorKey()));
184 #if ENABLE(TIZEN_LOAD_REMOTE_IMAGES)
185 settings->setLoadRemoteImages(store.getBoolValueForKey(WebPreferencesKey::loadRemoteImagesKey()));
187 #if ENABLE(TIZEN_LINK_EFFECT)
188 settings->setLinkEffectEnabled(store.getBoolValueForKey(WebPreferencesKey::linkEffectEnabledKey()));
190 #if ENABLE(TIZEN_ISF_PORT)
191 settings->setEnableDefaultKeypad(store.getBoolValueForKey(WebPreferencesKey::defaultKeypadEnabledKey()));
193 #if ENABLE(TIZEN_STYLE_SCOPED)
194 WebCore::RuntimeEnabledFeatures::setStyleScopedEnabled(store.getBoolValueForKey(WebPreferencesKey::styleScopedEnabledKey()));
196 #if ENABLE(TIZEN_WEB_AUDIO)
197 settings->setWebAudioEnabled(true);
201 void WebPage::platformPreferencesDidChange(const WebPreferencesStore&)
205 #endif // #if ENABLE(TIZEN_PREFERENCE)
207 static inline void scroll(Page* page, ScrollDirection direction, ScrollGranularity granularity)
209 page->focusController()->focusedOrMainFrame()->eventHandler()->scrollRecursively(direction, granularity);
212 bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent& keyboardEvent)
218 bool WebPage::platformHasLocalDataForURL(const KURL&)
224 String WebPage::cachedResponseMIMETypeForURL(const KURL&)
230 bool WebPage::platformCanHandleRequest(const ResourceRequest&)
236 String WebPage::cachedSuggestedFilenameForURL(const KURL&)
242 PassRefPtr<SharedBuffer> WebPage::cachedResponseDataForURL(const KURL&)
248 const char* WebPage::interpretKeyEvent(const KeyboardEvent* event)
250 ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
252 if (event->type() == eventNames().keydownEvent)
253 return getKeyDownCommandName(event);
255 return getKeyPressCommandName(event);
258 void WebPage::setThemePath(const String& themePath)
260 WebCore::RenderThemeEfl* theme = static_cast<WebCore::RenderThemeEfl*>(m_page->theme());
261 theme->setThemePath(themePath);
264 static Frame* targetFrameForEditing(WebPage* page)
266 Frame* frame = page->corePage()->focusController()->focusedOrMainFrame();
270 Editor* editor = frame->editor();
271 if (!editor->canEdit())
274 if (editor->hasComposition()) {
275 // We should verify the parent node of this IME composition node are
276 // editable because JavaScript may delete a parent node of the composition
277 // node. In this case, WebKit crashes while deleting texts from the parent
278 // node, which doesn't exist any longer.
279 if (PassRefPtr<Range> range = editor->compositionRange()) {
280 Node* node = range->startContainer();
281 if (!node || !node->isContentEditable())
289 void WebPage::confirmComposition(const String& compositionString)
291 Frame* targetFrame = targetFrameForEditing(this);
295 #if ENABLE(TIZEN_ISF_PORT)
296 if (m_prepareKeyDownEvent) {
297 m_keyPressCommands.append(adoptPtr(new ConfirmCompositionKeyPressCommand(compositionString)));
302 targetFrame->editor()->confirmComposition(compositionString);
304 #if ENABLE(TIZEN_ISF_PORT)
305 m_page->editorClient()->respondToChangedSelection(targetFrame);
309 void WebPage::setComposition(const String& compositionString, const Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition)
311 Frame* targetFrame = targetFrameForEditing(this);
315 #if ENABLE(TIZEN_ISF_PORT)
316 if (!targetFrame->editor()->hasComposition() && compositionString.isEmpty())
319 if (m_prepareKeyDownEvent) {
320 m_keyPressCommands.append(adoptPtr(new SetCompositionKeyPressCommand(compositionString, underlines, cursorPosition)));
324 if (targetFrame->selection()->rootEditableElement()) {
325 HTMLTextFormControlElement* textFormControl = toTextFormControl(targetFrame->selection()->rootEditableElement()->shadowAncestorNode());
326 if (textFormControl && textFormControl->maxLength() >= 0) {
327 unsigned availableLength = textFormControl->maxLength() - textFormControl->value().length();
328 if (targetFrame->editor()->hasComposition())
329 availableLength += (targetFrame->editor()->compositionEnd() - targetFrame->editor()->compositionStart());
330 if (!availableLength)
333 if (availableLength < compositionString.length()) {
334 String newCompositionString = compositionString.substring(0, availableLength);
335 Vector<CompositionUnderline> newUnderlines;
336 size_t numUnderlines = underlines.size();
337 for (size_t index = 0; index < numUnderlines; ++index) {
338 if (underlines[index].startOffset < availableLength) {
339 newUnderlines.append(underlines[index]);
340 if (newUnderlines.last().endOffset > availableLength)
341 newUnderlines.last().endOffset = availableLength;
345 m_page->editorClient()->lockRespondToChangedSelection();
346 targetFrame->editor()->setComposition(newCompositionString, newUnderlines, cursorPosition, 0);
347 m_page->editorClient()->unlockRespondToChangedSelection();
354 m_page->editorClient()->lockRespondToChangedSelection();
357 targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
359 #if ENABLE(TIZEN_ISF_PORT)
360 m_page->editorClient()->unlockRespondToChangedSelection();
364 void WebPage::cancelComposition()
366 Frame* frame = m_page->focusController()->focusedOrMainFrame();
370 frame->editor()->cancelComposition();
375 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
376 IntSize WebPage::contentsSize() const
378 FrameView* frameView = m_page->mainFrame()->view();
380 return IntSize(0, 0);
382 return frameView->contentsSize();
386 void WebPage::scrollMainFrameBy(const IntSize& scrollOffset)
388 m_page->mainFrame()->view()->scrollBy(scrollOffset);
391 void WebPage::scrollMainFrameTo(const IntPoint& scrollPosition)
393 m_page->mainFrame()->view()->setScrollPosition(scrollPosition);
396 void WebPage::createSnapshot(const IntRect rect, float scaleFactor, ShareableBitmap::Handle& snapshotHandle)
398 FrameView* frameView = m_mainFrame->coreFrame()->view();
402 RefPtr<WebImage> snapshotImage = scaledSnapshotInViewCoordinates(rect, scaleFactor, ImageOptionsShareable);
403 if (!snapshotImage || !snapshotImage->bitmap())
406 snapshotImage->bitmap()->createHandle(snapshotHandle);
409 void WebPage::requestUpdateFormNavigation()
411 Frame* frame = m_page->focusController()->focusedOrMainFrame();
415 Document* document = frame->document();
419 Node* focusedNode = document->focusedNode();
421 Vector<RefPtr<Node> > focusableNodes;
422 document->getFocusableNodes(focusableNodes);
424 int formElementCount = 0;
425 int currentNodeIndex = -1;
426 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
427 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
428 AtomicString nodeName = (*it).get()->nodeName();
429 if (equalIgnoringCase(nodeName, "SELECT")
430 || (equalIgnoringCase(nodeName, "INPUT")
431 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
432 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
433 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "SUBMIT")
436 if ((*it).get() == focusedNode)
437 currentNodeIndex = formElementCount;
442 if (currentNodeIndex == -1)
445 send(Messages::WebPageProxy::UpdateFormNavigation(formElementCount, currentNodeIndex));
448 void WebPage::moveFocus(int newIndex)
450 Frame* frame = m_page->focusController()->focusedOrMainFrame();
454 Document* document = frame->document();
458 Vector<RefPtr<Node> > focusableNodes;
459 document->getFocusableNodes(focusableNodes);
462 const Vector<RefPtr<Node> >::iterator end = focusableNodes.end();
463 for (Vector<RefPtr<Node> >::iterator it = focusableNodes.begin(); it != end; ++it) {
464 AtomicString nodeName = (*it).get()->nodeName();
465 if (equalIgnoringCase(nodeName, "SELECT")) {
466 if (index == newIndex) {
467 (*it).get()->setFocus();
468 LayoutPoint position = LayoutPoint(0, 0);
469 PlatformMouseEvent event(flooredIntPoint(position), flooredIntPoint(position), LeftButton, PlatformEvent::MouseMoved, 1, false, false, false, false, 0);
470 (*it).get()->dispatchMouseEvent(event, "mousedown", 0, 0);
473 } else if (equalIgnoringCase(nodeName, "INPUT")
474 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "CHECKBOX")
475 && !equalIgnoringCase((*it).get()->toInputElement()->type(), "RADIO")
477 if (index == newIndex) {
478 HTMLInputElement* elem = (*it).get()->toInputElement();
486 #if ENABLE(TIZEN_MOBILE_WEB_PRINT)
487 #define INCH_TO_MM 25.4
488 #define INCH_TO_POINTS 72.0
490 void WebPage::createPagesToPDF(const IntSize& surfaceSize, const IntSize& contentsSize, const String& fileName)
492 FrameView* frameView = m_mainFrame->coreFrame()->view();
496 RefPtr<WebImage> pageshotImage = WebImage::create(contentsSize, ImageOptionsShareable);
497 if (!pageshotImage->bitmap())
500 double pdfWidth = (double)surfaceSize.width() / INCH_TO_MM * INCH_TO_POINTS;
501 double pdfHeight = (double)surfaceSize.height() / INCH_TO_MM * INCH_TO_POINTS;
502 double scaleFactorPdf = 1.0;
503 if (contentsSize.width() > pdfWidth)
504 scaleFactorPdf = pdfWidth / (double)contentsSize.width();
506 OwnPtr<WebCore::GraphicsContext> graphicsContext = pageshotImage->bitmap()->createGraphicsContextForPdfSurface(fileName, pdfWidth, pdfHeight);
507 graphicsContext->scale(FloatSize(scaleFactorPdf, scaleFactorPdf));
509 frameView->updateLayoutAndStyleIfNeededRecursive();
511 int pageNumber = ((contentsSize.height() * scaleFactorPdf) / pdfHeight) + 1;
514 PaintBehavior oldBehavior = frameView->paintBehavior();
515 frameView->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);
516 for (int i = 0; i < pageNumber; i++) {
517 IntRect paintRect(0, (int)paintY, contentsSize.width(), (int)(pdfHeight / scaleFactorPdf));
519 frameView->paint(graphicsContext.get(), paintRect);
520 cairo_show_page(graphicsContext->platformContext()->cr());
521 graphicsContext->translate(0, -ceil(pdfHeight / scaleFactorPdf));
522 paintY += (pdfHeight / scaleFactorPdf);
524 frameView->setPaintBehavior(oldBehavior);
526 pageshotImage.release();
530 #if ENABLE(TIZEN_TEXT_CARET_HANDLING_WK2)
531 bool WebPage::setCaretPosition(const IntPoint& pos)
533 Frame* frame = m_page->focusController()->focusedOrMainFrame();
537 FrameSelection* controller = frame->selection();
541 FrameView* frameView = frame->view();
545 IntPoint point = m_page->mainFrame()->view()->windowToContents(pos);
546 HitTestResult result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
547 if (result.scrollbar())
550 Node* innerNode = result.innerNode();
552 if (!innerNode || !innerNode->renderer())
555 VisiblePosition visiblePos;
557 // we check if content is richly editable - because those input field behave other than plain text ones
558 // sometimes they may consists a node structure and they need special approach
559 if (innerNode->rendererIsRichlyEditable()) {
560 // point gets inner node local coordinates
561 point = flooredIntPoint(result.localPoint());
562 IntRect rect = innerNode->renderer()->absoluteBoundingBoxRect(true);
564 // it is not the best way to do this, but it is not as slow and it works - so maybe in the future someone
565 // will have a better idea how to solve it
566 // here we are getting innerNode from HitTestResult - unfortunately this is a kind of high level node
567 // in the code below I am trying to obtain low level node - #text - to get its coordinates and size
569 // all those getting nodes rects are needed to bypass WebCore's methods of positioning caret when user
570 // is clicking outside a node - and cheat WebCore telling it that actually we clicked into input field
571 // node, not outside of it
572 Node* deepInnerNode = innerNode->renderer()->positionForPoint(point).deepEquivalent().deprecatedNode();
574 if (!deepInnerNode || !deepInnerNode->renderer())
577 // so we get a base node rectange
578 IntRect deepNodeRect = deepInnerNode->renderer()->absoluteBoundingBoxRect(true);
580 // we modify our local point to adjust it to base node local coordinates
581 point.move(rect.x() - deepNodeRect.x(), rect.y() - deepNodeRect.y());
583 // if we are outside the rect we cheat, that we are just inside of it
586 else if (point.y() >= deepNodeRect.height())
587 point.setY(deepNodeRect.height() - 1);
589 // visible position created - caret ready to set
590 visiblePos = deepInnerNode->renderer()->positionForPoint(point);
591 if (visiblePos.isNull())
594 // for plain text input fields we can get only a caret bounding box
595 if (!controller->isCaret() || !controller->caretRenderer())
598 const Node* node = controller->start().deprecatedNode();
599 if (!node || !node->renderer())
602 Element* currentRootEditableElement = node->rootEditableElement();
603 Element* newRootEditableElement = innerNode->rootEditableElement();
604 if (currentRootEditableElement != newRootEditableElement)
607 IntRect rect = controller->caretRenderer()->absoluteBoundingBoxRect(true);
609 // The below wirtten code is not correct way to implement. Presntly the is no
610 // other working way. To be replaced by better logic
611 // here we also cheat input field that we actually are just inside of if
612 IntPoint focusedFramePoint = frame->view()->windowToContents(pos);
613 IntPoint oldFocusedFramePoint = focusedFramePoint;
615 const int boundariesWidth = 2;
616 if (focusedFramePoint.x() < rect.x())
617 focusedFramePoint.setX(rect.x());
618 else if (focusedFramePoint.x() > rect.maxX())
619 focusedFramePoint.setX(rect.maxX());
620 if (focusedFramePoint.y() < rect.y() + boundariesWidth)
621 focusedFramePoint.setY(rect.y() + boundariesWidth);
622 else if (focusedFramePoint.y() >= rect.maxY() - boundariesWidth)
623 focusedFramePoint.setY(rect.maxY() - boundariesWidth - 1);
625 int diffX = focusedFramePoint.x() - oldFocusedFramePoint.x();
626 int diffY = focusedFramePoint.y() - oldFocusedFramePoint.y();
627 point.setX((point.x())+diffX);
628 point.setY((point.y())+diffY);
630 // hit test with fake (adjusted) coordinates
631 IntPoint hitTestPoint = m_page->mainFrame()->view()->windowToContents(point);
632 HitTestResult newResult = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(hitTestPoint, /*allowShadowContent*/ true, /*ignoreClipping*/ true);
634 if (!newResult.isContentEditable())
637 Node* newInnerNode = newResult.innerNode();
639 if (!newInnerNode || !newInnerNode->renderer())
642 // visible position created
643 visiblePos = newInnerNode->renderer()->positionForPoint(newResult.localPoint());
644 if (visiblePos.isNull())
648 // create visible selection from visible position
649 VisibleSelection newSelection = VisibleSelection(visiblePos);
650 controller->setSelection(newSelection, CharacterGranularity);
651 // after setting selection caret blinking is suspended by default so we are unsuspedning it
652 controller->setCaretBlinkingSuspended(false);
658 #if ENABLE(TIZEN_ISF_PORT)
659 void WebPage::didCancelComposition(Node* valueChangedNode)
661 Frame* frame = m_page->focusController()->focusedOrMainFrame();
662 if (!frame || frame->editor()->ignoreCompositionSelectionChange() || !valueChangedNode->containsIncludingShadowDOM(frame->editor()->compositionNode()))
665 frame->editor()->cancelComposition();
666 send(Messages::WebPageProxy::DidCancelComposition());
669 void WebPage::prepareKeyDownEvent()
671 m_prepareKeyDownEvent = true;
674 void WebPage::swapKeyPressCommands(Vector<OwnPtr<KeyPressCommand> >& commands)
676 m_keyPressCommands.swap(commands);
679 void WebPage::deleteSurroundingText(int offset, int count)
681 Frame* frame = m_page->focusController()->focusedOrMainFrame();
682 if (!frame || !frame->editor()->canEdit())
685 if (m_prepareKeyDownEvent) {
686 m_keyPressCommands.append(adoptPtr(new DeleteTextKeyPressCommand(offset, count)));
690 Position base(frame->selection()->base());
691 offset += base.offsetInContainerNode();
692 base.moveToOffset(offset);
693 Position extent(base);
694 extent.moveToOffset(offset + count);
695 VisibleSelection selection(base, extent);
696 if (!selection.isRange())
699 frame->selection()->setSelection(selection);
700 frame->editor()->deleteWithDirection(DirectionBackward, CharacterGranularity, false, true);
703 bool WebPage::updateEditorStateRect(const Frame* frame, EditorState& state) const
705 ASSERT(frame->selection()->rootEditableElement());
707 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
708 Vector<IntRect> rects;
709 calcFocusedRects(frame->selection()->rootEditableElement(), rects);
710 IntRect rect = unionRect(rects);
711 if (state.editorRect == rect)
714 state.editorRect = rect;
717 if (frame->selection()->isCaret())
718 state.selectionRect = frame->view()->contentsToWindow(frame->selection()->absoluteCaretBounds());
719 else if (frame->selection()->isRange())
720 state.selectionRect = frame->view()->contentsToWindow(enclosingIntRect(frame->selection()->bounds(false)));
726 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION) || ENABLE(TIZEN_WEBKIT2_FORM_DATABASE)
727 void WebPage::setCurrentTargetInputElementValue(const String& inputValue)
729 Frame* frame = m_page->focusController()->focusedOrMainFrame();
730 if (!frame || !frame->document() || !frame->document()->currentTargetNode())
733 HTMLInputElement* inputElement = frame->document()->currentTargetNode()->toInputElement();
737 frame->document()->setCurrentTargetNode(0);
739 inputElement->toNode()->dispatchFocusEvent(0);
740 inputElement->setValue(inputValue, DispatchChangeEvent);
743 void WebPage::setFocusedInputElementValue(const String& inputValue)
745 Frame* frame = m_page->focusController()->focusedOrMainFrame();
746 if (!frame || !frame->document() || !frame->document()->focusedNode())
749 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
753 inputElement->toNode()->dispatchFocusEvent(0);
754 inputElement->setValue(inputValue, DispatchChangeEvent);
757 void WebPage::getFocusedInputElementValue(String& inputValue)
759 inputValue = String();
761 Frame* frame = m_page->focusController()->focusedOrMainFrame();
762 if (!frame || !frame->document() || !frame->document()->focusedNode())
765 HTMLInputElement* inputElement = frame->document()->focusedNode()->toInputElement();
769 inputValue = inputElement->value();
773 #if ENABLE(TIZEN_DATALIST_ELEMENT)
774 void WebPage::getFocusedInputElementDataList(Vector<String>& optionList)
776 Frame* frame = m_page->focusController()->focusedOrMainFrame();
777 if (!frame || !frame->document())
780 Node* node = frame->document()->focusedNode();
784 HTMLInputElement* input = node->toInputElement();
788 HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
792 RefPtr<HTMLCollection> options = static_cast<HTMLDataListElement*>(dataList)->options();
793 for (unsigned i = 0; Node* node = options->item(i); i++) {
794 HTMLOptionElement* optionElement = static_cast<HTMLOptionElement*>(node);
795 String value = optionElement->value();
796 optionList.append(value);
801 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
802 static IntRect getNodeRect(Node* node, Node* focusableNode, bool isImage)
808 IntRect imageNodeRect = pixelSnappedIntRect(node->getRect());
809 if (!focusableNode->renderRect(&isReplaced).isEmpty() && imageNodeRect.contains(pixelSnappedIntRect(focusableNode->getRect()))) {
810 // If render rect of focusableNode is empty and rect of imageNode include rect of focusableNode,
811 // we have to get rect of focusableNode.
812 // for example - The rect of google logo image in www.google.com pc site's search result page is bigger than rect of focusableNode.
813 // for example - The rect of category menu image in www.gmarket.co.kr pc site is bigger than rect of focusableNode.
814 rect = pixelSnappedIntRect(focusableNode->getRect());
817 // otherwise we have to get rect of imageNode.
818 // for example - The render rect of images in www.pudelek.pl is empty.
819 // 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.
820 rect = imageNodeRect;
821 focusableNode = node;
824 // If focusedNode have multiple child nodes, we have to unite rect of child nodes.
825 // for example - links in www.google.com's search result page.
827 for (Node* childNode = focusableNode->firstChild(); childNode; childNode = childNode->traverseNextNode(focusableNode)) {
829 if (focusableNode->renderRect(&isReplaced).contains(childNode->getRect()))
830 tempRect.unite(pixelSnappedIntRect(childNode->getRect()));
833 // If tempRect is empty or rect of focusableNode include tempRect,
834 // we have to get rect of focusableNode.
835 // for example - list menu item in m.naver.com.
836 // otherwise we have to get rect of tempRect.
837 // getRect API do not return correct rect if the node is a container node,
838 // hence using absoluteBoundingBoxRect to get the correct bounding rect.
839 LayoutRect renderRect = focusableNode->renderer() ? focusableNode->renderer()->absoluteBoundingBoxRect() : focusableNode->getRect();
840 if (tempRect.isEmpty() || renderRect.contains(tempRect))
841 rect = pixelSnappedIntRect(renderRect);
846 // We have to get render rect from ancestor node if current rect is empty.
847 // for example - The rect of naver logo image in www.naver.com pc site is empty.
849 for (Node* loopNode = focusableNode; loopNode && rect.isEmpty(); loopNode = loopNode->parentNode()) {
850 RenderObject* renderer = loopNode->renderer();
851 if (renderer && renderer->isRoot())
854 rect = pixelSnappedIntRect(loopNode->renderRect(&isReplaced));
857 Frame* nodeFrame = focusableNode->document()->frame();
859 while (nodeFrame && (owner = nodeFrame->ownerElement())) {
860 rect.moveBy(owner->getRect().pixelSnappedLocation());
861 nodeFrame = owner->document()->frame();
864 // The y position of tab menu item in www.google.com is negative value,
865 // so we do not want to draw focus ring in that case.
866 if ((rect.maxX() < 0) || (rect.maxY() < 0))
873 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
874 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
875 static bool isClickableOrFocusable(Node* focusableNode)
880 if (focusableNode->disabled())
882 if (!focusableNode->inDocument())
884 if (!focusableNode->renderer() || focusableNode->renderer()->style()->visibility() != VISIBLE)
886 if (focusableNode->isFocusable()) {
887 if (focusableNode->isLink()
888 || focusableNode->hasTagName(HTMLNames::inputTag)
889 || focusableNode->hasTagName(HTMLNames::selectTag)
890 || focusableNode->hasTagName(HTMLNames::buttonTag))
893 if (focusableNode->supportsFocus()
894 || focusableNode->hasEventListeners(eventNames().clickEvent)
895 || focusableNode->hasEventListeners(eventNames().mousedownEvent)
896 || focusableNode->hasEventListeners(eventNames().mouseupEvent)) {
902 #if ENABLE(TOUCH_ADJUSTMENT)
903 void WebPage::getFocusedRect(HitTestResult hitTestResult, Page* page, bool setFocus, Vector<IntRect>& rects, const IntPoint& point, const IntSize& area)
905 void WebPage::getFocusedRect(HitTestResult hitTestResult, Page* page, bool setFocus, Vector<IntRect>& rects)
908 Node* node = hitTestResult.innerNode();
909 #if ENABLE(TOUCH_ADJUSTMENT)
910 IntPoint adustedPoint;
911 Frame* mainFrame = page->mainFrame();
912 Node* adjustedNode = 0;
913 mainFrame->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adustedPoint, adjustedNode);
914 if (!isClickableOrFocusable(node))
915 mainFrame->eventHandler()->bestClickableNodeForTouchPoint(point, IntSize(area.width() / 2, area.height() / 2), adustedPoint, adjustedNode);
923 bool isFocusRingDrawable = false;
924 Node* focusableNode = node;
925 while (focusableNode) {
926 RenderObject* renderer = focusableNode->renderer();
927 if (renderer && (renderer->isBody() || renderer->isRenderView() || renderer->isRoot()))
930 if (isClickableOrFocusable(focusableNode)) {
931 isFocusRingDrawable = true;
935 focusableNode = focusableNode->parentNode();
938 // Don't draw focus ring if child is focusable or has trigger
939 if (focusableNode && focusableNode->isContainerNode() && !focusableNode->isLink()) {
940 WebCore::Node *child = static_cast<const ContainerNode*>(focusableNode)->firstChild();
942 if( child->supportsFocus()
943 || child->hasEventListeners(eventNames().clickEvent)
944 || child->hasEventListeners(eventNames().mousedownEvent)
945 || child->hasEventListeners(eventNames().mouseupEvent)) {
948 child = child->traverseNextNode(focusableNode);
952 if (!isFocusRingDrawable) {
953 if (!node->hasTagName(HTMLNames::imgTag))
955 focusableNode = node;
959 setFocusedNode(focusableNode);
961 calcFocusedRects(focusableNode, rects);
965 #if ENABLE(TOUCH_ADJUSTMENT)
966 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, const IntSize& area, WebHitTestResult::Data& hitTestResultData)
968 void WebPage::hitTestResultAtPoint(const IntPoint& point, int hitTestMode, WebHitTestResult::Data& hitTestResultData)
971 Frame* frame = m_page->mainFrame();
972 FrameView* frameView = frame->view();
976 HitTestResult hitTestResult = frame->eventHandler()->hitTestResultAtPoint(frameView->windowToContents(point), false);
977 hitTestResultData.absoluteImageURL = hitTestResult.absoluteImageURL().string();
978 hitTestResultData.absoluteLinkURL = hitTestResult.absoluteLinkURL().string();
979 hitTestResultData.absoluteMediaURL = hitTestResult.absoluteMediaURL().string();
980 hitTestResultData.linkLabel = hitTestResult.textContent();
981 hitTestResultData.linkTitle = hitTestResult.titleDisplayString();
982 hitTestResultData.isContentEditable = hitTestResult.isContentEditable();
983 #if ENABLE(TIZEN_DRAG_SUPPORT)
984 hitTestResultData.isDragSupport = hitTestResult.isDragSupport();
987 int context = WebHitTestResult::HitTestResultContextDocument;
989 if (!hitTestResult.absoluteLinkURL().isEmpty())
990 context |= WebHitTestResult::HitTestResultContextLink;
991 if (!hitTestResult.absoluteImageURL().isEmpty())
992 context |= WebHitTestResult::HitTestResultContextImage;
993 if (!hitTestResult.absoluteMediaURL().isEmpty())
994 context |= WebHitTestResult::HitTestResultContextMedia;
995 if (hitTestResult.isSelected())
996 context |= WebHitTestResult::HitTestResultContextSelection;
997 if (hitTestResult.isContentEditable())
998 context |= WebHitTestResult::HitTestResultContextEditable;
999 if (hitTestResult.innerNonSharedNode() && hitTestResult.innerNonSharedNode()->isTextNode())
1000 context |= WebHitTestResult::HitTestResultContextText;
1002 hitTestResultData.context = context;
1003 hitTestResultData.hitTestMode = hitTestMode;
1005 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
1006 bool setFocus = hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeSetFocus;
1007 #if ENABLE(TOUCH_ADJUSTMENT)
1008 getFocusedRect(hitTestResult, m_page.get(), setFocus, hitTestResultData.focusedRects, point, area);
1010 getFocusedRect(hitTestResult, m_page.get(), setFocus, hitTestResultData.focusedRects);
1013 // Don't display FocusRect if the size is too big..
1014 IntRect framerect = frameView->visibleContentRect(true);
1015 for (size_t i = 0; i < hitTestResultData.focusedRects.size(); ++i) {
1016 if (hitTestResultData.focusedRects[i].width() > (0.8 * framerect.width())
1017 && hitTestResultData.focusedRects[i].height() > (0.8 * framerect.height()))
1018 hitTestResultData.focusedRects.clear();
1021 if (hitTestResult.innerNode() && hitTestResult.innerNode()->renderer() && hitTestResult.innerNode()->renderer()->style()) {
1022 hitTestResultData.focusedColor = hitTestResult.innerNode()->renderer()->style()->tapHighlightColor();
1023 if (!hitTestResultData.focusedColor.hasAlpha())
1024 hitTestResultData.focusedColor = Color(hitTestResultData.focusedColor.red(), hitTestResultData.focusedColor.green(), hitTestResultData.focusedColor.blue(), RenderStyle::initialTapHighlightColor().alpha());
1028 if (hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeNodeData) {
1029 WebCore::Node* hitNode = hitTestResult.innerNonSharedNode();
1031 hitTestResultData.nodeData.nodeValue = hitNode->nodeValue();
1033 if ((hitTestResultData.context & WebHitTestResult::HitTestResultContextText) && hitNode->parentNode())
1034 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.
1036 if (hitNode->isElementNode()) {
1037 WebCore::Element* hitElement = static_cast<WebCore::Element*>(hitNode);
1039 hitTestResultData.nodeData.tagName = hitElement->tagName();
1043 WebCore::NamedNodeMap* namedNodeMap = hitNode->attributes();
1045 for (size_t i = 0; i < namedNodeMap->length(); i++) {
1046 const WebCore::Attribute* attribute = namedNodeMap->element()->attributeItem(i);
1047 String key = attribute->name().toString();
1048 String value = attribute->value();
1049 hitTestResultData.nodeData.attributeMap.add(key, value);
1052 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1053 hitTestResultData.nodeData.zIndex = 0;
1054 for (Node* node = hitNode; node; node = node->parentNode()) {
1055 RenderStyle* computedStyle = node->computedStyle();
1056 if (computedStyle && !(computedStyle->hasAutoZIndex()) && hitTestResultData.nodeData.zIndex < computedStyle->zIndex())
1057 hitTestResultData.nodeData.zIndex = computedStyle->zIndex();
1063 if ((hitTestResultData.hitTestMode & WebHitTestResult::HitTestModeImageData) && (hitTestResultData.context & WebHitTestResult::HitTestResultContextImage)) {
1064 WebCore::Image* hitImage = hitTestResult.image();
1065 if (hitImage && hitImage->data() && hitImage->data()->data()) {
1066 hitTestResultData.imageData.data.append(hitImage->data()->data(), hitImage->data()->size());
1067 hitTestResultData.imageData.fileNameExtension = hitImage->filenameExtension();
1073 #if ENABLE(TIZEN_WEB_STORAGE)
1074 void WebPage::getStorageQuotaBytes(uint64_t callbackID)
1076 uint32_t quota = m_page->group().groupSettings()->localStorageQuotaBytes();
1077 send(Messages::WebPageProxy::DidGetWebStorageQuotaBytes(quota, callbackID));
1080 void WebPage::setStorageQuotaBytes(uint32_t quota)
1082 m_page->group().groupSettings()->setLocalStorageQuotaBytes(quota);
1086 #if ENABLE(TIZEN_CLIPBOARD) || ENABLE(TIZEN_PASTEBOARD)
1087 void WebPage::setClipboardDataForPaste(const String& data, const String& type)
1089 #if ENABLE(TIZEN_PASTEBOARD)
1090 // FIXME: Should move to EditorClient like Clipboard
1091 Pasteboard::generalPasteboard()->setDataWithType(data, type);
1093 Frame* mainFrame = m_page->mainFrame();
1097 mainFrame->editor()->client()->setClipboardDataForPaste(data, type);
1102 void WebPage::suspendJavaScriptAndResources()
1104 Frame* mainFrame = m_page->mainFrame();
1108 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1109 frame->document()->suspendScheduledTasks(WebCore::ActiveDOMObject::PageWillBeSuspended);
1110 mainFrame->loader()->suspendAllLoaders();
1113 void WebPage::resumeJavaScriptAndResources()
1115 Frame* mainFrame = m_page->mainFrame();
1119 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1120 frame->document()->resumeScheduledTasks();
1121 mainFrame->loader()->resumeAllLoaders();
1124 void WebPage::suspendAnimations()
1126 Frame* mainFrame = m_page->mainFrame();
1130 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1131 frame->animation()->suspendAnimationsForDocument(frame->document());
1134 void WebPage::resumeAnimations()
1136 Frame* mainFrame = m_page->mainFrame();
1140 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1141 frame->animation()->resumeAnimationsForDocument(frame->document());
1144 #if ENABLE(TIZEN_SYNC_REQUEST_ANIMATION_FRAME)
1145 void WebPage::suspendAnimationController()
1147 if (!m_suspendedAnimationController) {
1148 Frame* mainFrame = m_page->mainFrame();
1152 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1153 frame->document()->suspendScriptedAnimationControllerCallbacks();
1155 m_suspendedAnimationController = true;
1159 void WebPage::resumeAnimationController()
1161 if (m_suspendedAnimationController) {
1162 Frame* mainFrame = m_page->mainFrame();
1166 for (Frame* frame = mainFrame; frame; frame = frame->tree()->traverseNext())
1167 frame->document()->resumeScriptedAnimationControllerCallbacks();
1169 m_suspendedAnimationController = false;
1174 #if ENABLE(TIZEN_REMOTE_WEB_INSPECTOR)
1175 void WebPage::startInspectorServer(uint32_t port, uint32_t& allocatedPort)
1177 bool ret = WebInspectorServerTizen::server()->startServer(port);
1179 allocatedPort = WebInspectorServerTizen::server()->getServerPort();
1184 void WebPage::stopInspectorServer(bool& result)
1186 result = WebInspectorServerTizen::server()->stopServer();
1190 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1191 void WebPage::scrollOverflowWithTrajectoryVector(const WebCore::FloatPoint& trajectoryVector)
1193 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1196 frame->eventHandler()->scrollOverflow(trajectoryVector);
1200 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION)
1201 void WebPage::scrollOverflow(const WebCore::FloatPoint& delta, bool& scrolled)
1203 scrolled = m_page->focusController()->focusedOrMainFrame()->eventHandler()->scrollOverflow(delta);
1206 void WebPage::setPressedNodeAtPoint(const IntPoint& point, bool checkOverflowLayer, bool& pressed, uint32_t& id)
1208 RenderObject* renderer = 0;
1210 pressed = m_page->mainFrame()->eventHandler()->setMousePressNodeAtPoint(point, checkOverflowLayer, renderer);
1211 #if ENABLE(TIZEN_CSS_OVERFLOW_SCROLL_ACCELERATION_ON_UI_SIDE)
1212 if (pressed && renderer)
1213 id = toWebGraphicsLayer(renderer->enclosingLayer()->layerForScrollingContents())->id();
1218 void WebPage::executeEditCommandWithArgument(const String& commandName, const String& argument)
1220 executeEditingCommand(commandName, argument);
1223 #if ENABLE(TIZEN_PLUGIN_SUSPEND_RESUME)
1224 void WebPage::suspendPlugin()
1226 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1227 FrameView* view = frame->view();
1231 const HashSet<RefPtr<Widget> >* children = view->children();
1234 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1235 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1236 Widget* widget = (*it).get();
1237 if (widget->isPluginViewBase()) {
1238 PluginView* pluginView = static_cast<PluginView*>(widget);
1240 pluginView->suspendPlugin();
1246 void WebPage::resumePlugin()
1248 for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree()->traverseNext()) {
1249 FrameView* view = frame->view();
1253 const HashSet<RefPtr<Widget> >* children = view->children();
1256 HashSet<RefPtr<Widget> >::const_iterator end = children->end();
1257 for (HashSet<RefPtr<Widget> >::const_iterator it = children->begin(); it != end; ++it) {
1258 Widget* widget = (*it).get();
1259 if (widget->isPluginViewBase()) {
1260 PluginView* pluginView = static_cast<PluginView*>(widget);
1262 pluginView->resumePlugin();
1269 #if ENABLE(TIZEN_MULTIPLE_SELECT)
1270 void WebPage::didChangeSelectedIndexForActivePopupMenuMultiple(Vector<int32_t> newIndex)
1272 if (!m_activePopupMenu)
1275 m_activePopupMenu->client()->popupDidHide();
1277 size_t indexSize = newIndex.size();
1278 for (size_t i = 0; i < indexSize; i++)
1279 m_activePopupMenu->didChangeSelectedIndex(newIndex.at(i));
1284 #if ENABLE(TIZEN_OFFLINE_PAGE_SAVE)
1285 void WebPage::startOfflinePageSave(String subresourceFolderName)
1287 WebPageSerializerTizen::getSerializedPageContent(this, subresourceFolderName);
1291 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1292 void WebPage::selectClosestWord(const IntPoint& point, bool isAutoWordSelection, bool& result)
1296 Frame* mainFrame = m_page->mainFrame();
1297 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1299 HitTestResult hitTestResult = mainFrame->eventHandler()->hitTestResultAtPoint(m_page->mainFrame()->view()->windowToContents(point), false);
1301 Node* node = hitTestResult.innerNonSharedNode();
1305 if (node->renderer() && node->renderer()->style() && (node->renderer()->style()->userSelect() == SELECT_NONE))
1308 Frame* newFocusFrame = node->document()->frame();
1309 if (focusedFrame != newFocusFrame) {
1310 m_page->focusController()->setFocusedFrame(newFocusFrame);
1311 focusedFrame = newFocusFrame;
1314 HTMLInputElement* inputElement = node->toInputElement();
1316 if (hitTestResult.isContentEditable()) {
1317 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1318 if (!inputElement || (inputElement
1319 && !inputElement->isDateField() && !inputElement->isDateTimeField() && !inputElement->isDateTimeLocalField()
1320 && !inputElement->isMonthField() && !inputElement->isTimeField() && !inputElement->isWeekField())) {
1321 result = setCaretPosition(point);
1322 if (!isAutoWordSelection)
1326 result = setCaretPosition(point);
1327 if (!isAutoWordSelection)
1332 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1333 if (!node->isTextNode() && !inputElement)
1335 if (!node->isTextNode())
1339 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
1341 && (inputElement->isDateField() || inputElement->isDateTimeField() || inputElement->isDateTimeLocalField()
1342 || inputElement->isMonthField() || inputElement->isTimeField() || inputElement->isWeekField())) {
1343 if (inputElement->value().isEmpty())
1348 for (Node* node = hitTestResult.innerNonSharedNode(); node; node = node->parentNode()) {
1349 if (node->isFocusable()) {
1350 // Text selection shoud not be started when text of <button> tag is selected.
1351 if (node->hasTagName(HTMLNames::buttonTag))
1354 if (inputElement && (inputElement->isTextButton() || inputElement->isCheckbox()))
1361 FrameSelection* frameSelection = focusedFrame->selection();
1363 VisiblePosition position = mainFrame->visiblePositionForPoint(point);
1364 VisibleSelection selection(position);
1366 // This changes just the 'start' and 'end' positions of the VisibleSelection
1367 selection.expandUsingGranularity(WordGranularity);
1369 FrameSelection::SetSelectionOptions options = FrameSelection::CloseTyping | FrameSelection::ClearTypingStyle | FrameSelection::DoNotSetFocus;
1370 frameSelection->setSelection(VisibleSelection(selection.start(), selection.end()), options);
1372 if (!frameSelection->isRange())
1375 // This changes just the 'start' and 'end' positions of the VisibleSelection
1376 // Find handlers positions
1377 IntRect leftRect, rightRect, updatedEditorRect;
1378 int selectionDirection = 0;
1379 getSelectionHandlers(leftRect, rightRect, selectionDirection, updatedEditorRect);
1380 if (leftRect.size().isZero() && rightRect.size().isZero()) {
1381 // Sometimes there is no selected text, but isNone() returns TRUE
1382 // in this case ewk_frame_selection_handlers_get() returns FALSE and handlers are invalid
1383 // Workaround - clear the selection.
1384 // Better solution would be to modify the ewk_frame_select_closest_word()
1385 // to not select anything in the first place (for example - don't call setSelection()
1386 // if there is nothing under the cursor).
1387 selectionClearAllSelection(m_page->mainFrame());
1394 void WebPage::setLeftSelection(const IntPoint& point, const int direction, int& result)
1396 result = HandleMovingDirectionNone;
1398 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1399 FrameSelection* frameSelection = focusedFrame->selection();
1400 if (!frameSelection->isRange())
1403 Node* selectionEndNode = frameSelection->end().deprecatedNode();
1404 if (!selectionEndNode || !selectionEndNode->renderer())
1407 FrameView* frameView = focusedFrame->view();
1411 IntPoint pos = frameView->windowToContents(point);
1412 IntRect leftRect, rightRect, updatedEditorRect;
1413 int selectionDirection = 0;
1414 getSelectionHandlers(leftRect, rightRect, selectionDirection, updatedEditorRect);
1416 if (selectionEndNode->rendererIsEditable() && !selectionEndNode->rendererIsRichlyEditable()) {
1417 const int boundariesWidth = 2;
1419 IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1420 // here we cheat input field that we actually are just inside of if
1421 if (pos.y() < rect.y() + boundariesWidth)
1422 pos.setY(rect.y() + boundariesWidth);
1423 else if (pos.y() >= rect.maxY() - boundariesWidth)
1424 pos.setY(rect.maxY() - boundariesWidth - 1);
1427 OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1428 Position base = frameSelection->base();
1429 Position extent = frameSelection->extent();
1431 Node* newSelectionStartNode = position->deepEquivalent().deprecatedNode();
1433 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1434 // Check if the new position is before the extent's position
1435 if (newSelectionStartNode
1436 && selectionEndNode->isContentEditable() == newSelectionStartNode->isContentEditable()) {
1437 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1438 // We do it, because without this, the other modification of the selection
1439 // would destroy the 'start' and/or 'end' positions and set them to
1440 // the 'base'/'extent' positions accordingly
1441 VisibleSelection sel(frameSelection->start(), frameSelection->end());
1442 frameSelection->setSelection(sel);
1444 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1445 focusedFrame->view()->setProhibitsScrolling(true);
1447 if (direction == HandleMovingDirectionNormal) {
1448 if (comparePositions(position->deepEquivalent(), extent) < 0) {
1449 frameSelection->setBase(*position);
1450 result = HandleMovingDirectionNormal;
1451 } else if (comparePositions(position->deepEquivalent(), extent) > 0) {
1452 frameSelection->setExtent(*position);
1453 frameSelection->setBase(extent);
1454 result = HandleMovingDirectionReverse;
1456 } else if (direction == HandleMovingDirectionReverse) {
1457 if (comparePositions(position->deepEquivalent(), base) > 0) {
1458 frameSelection->setExtent(*position);
1459 result = HandleMovingDirectionReverse;
1460 } else if (comparePositions(position->deepEquivalent(), base) < 0) {
1461 frameSelection->setBase(*position);
1462 frameSelection->setExtent(base);
1463 result = HandleMovingDirectionNormal;
1467 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1468 // This forces webkit to show selection
1469 // m_coreFrame->invalidateSelection();
1473 void WebPage::setRightSelection(const IntPoint& point, const int direction, int& result)
1475 result = HandleMovingDirectionNone;
1477 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1478 FrameSelection* frameSelection = focusedFrame->selection();
1480 if (!frameSelection->isRange())
1483 Node* selectionStartNode = frameSelection->start().deprecatedNode();
1484 if (!selectionStartNode || !selectionStartNode->renderer())
1487 FrameView* frameView = focusedFrame->view();
1491 IntPoint pos = frameView->windowToContents(point);
1492 if (selectionStartNode->rendererIsEditable() && !selectionStartNode->rendererIsRichlyEditable()) {
1493 const int boundariesWidth = 2;
1495 IntRect rect = frameSelection->caretRenderer()->absoluteBoundingBoxRect(true);
1496 // here we cheat input field that we actually are just inside of if
1497 if (pos.y() < rect.y() + boundariesWidth)
1498 pos.setY(rect.y() + boundariesWidth);
1499 else if (pos.y() >= rect.maxY() - boundariesWidth)
1500 pos.setY(rect.maxY() - boundariesWidth - 1);
1503 OwnPtr<VisiblePosition> position = adoptPtr(new VisiblePosition(focusedFrame->visiblePositionForPoint(pos)));
1504 Position base = frameSelection->base();
1505 Position extent = frameSelection->extent();
1507 Node* newSelectionEndNode = position->deepEquivalent().deprecatedNode();
1509 // both start and end nodes should be in the same area type: both should be editable or both should be not editable
1510 // Check if the new position is after the base's position
1511 if (newSelectionEndNode
1512 && selectionStartNode->isContentEditable() == newSelectionEndNode->isContentEditable()) {
1513 // Change the 'base' and 'extent' positions to 'start' and 'end' positions.
1514 // We do it, because without this, the other modifications of the selection
1515 // would destroy the 'start' and/or 'end' positions and set them to
1516 // the 'base'/'extent' positions accordingly
1518 VisibleSelection sel(frameSelection->start(), frameSelection->end());
1519 frameSelection->setSelection(sel);
1521 bool oldProhibitsScrolling = focusedFrame->view()->prohibitsScrolling();
1522 focusedFrame->view()->setProhibitsScrolling(true);
1524 if (direction == HandleMovingDirectionNormal) {
1525 if (comparePositions(position->deepEquivalent(), base) > 0) {
1526 frameSelection->setExtent(*position);
1527 result = HandleMovingDirectionNormal;
1528 } else if (comparePositions(position->deepEquivalent(), base) < 0) {
1529 frameSelection->setBase(*position);
1530 frameSelection->setExtent(base);
1531 result = HandleMovingDirectionReverse;
1533 } else if (direction == HandleMovingDirectionReverse) {
1534 if (comparePositions(position->deepEquivalent(), extent) < 0) {
1535 frameSelection->setBase(*position);
1536 result = HandleMovingDirectionReverse;
1537 } else if (comparePositions(position->deepEquivalent(), extent) > 0) {
1538 frameSelection->setExtent(*position);
1539 frameSelection->setBase(extent);
1540 result = HandleMovingDirectionNormal;
1544 focusedFrame->view()->setProhibitsScrolling(oldProhibitsScrolling);
1548 bool WebPage::isSelectionOnlyImage() const
1550 bool isImage = false;
1551 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1552 if (!focusedFrame->selection()->isRange())
1555 RefPtr<Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
1556 Vector<IntRect> rects;
1557 selectedRange->boundingBoxEx(rects, true);
1558 unsigned size = rects.size();
1560 Node* startNode = selectedRange->startContainer();
1561 Node* endNode = selectedRange->endContainer();
1562 if(startNode == endNode) {
1563 if(endNode && endNode->isContainerNode() && !(endNode->hasTagName(HTMLNames::imgTag))) {
1564 WebCore::Node *child = static_cast<const ContainerNode*>(endNode)->firstChild();
1566 if(child->hasTagName(HTMLNames::imgTag)) {
1570 child = child->traverseNextNode(endNode);
1574 if(endNode->hasTagName(HTMLNames::imgTag))
1582 void WebPage::getSelectionHandlers(IntRect& leftRect, IntRect& rightRect, int& selectionDirection, WebCore::IntRect& updatedEditorRect)
1584 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1585 updatedEditorRect = m_editorState.editorRect;
1586 if (!focusedFrame->selection()->isRange())
1589 // Is this check necessary? Leaving it for safety.
1590 RenderView* root = focusedFrame->contentRenderer();
1594 RefPtr<Range> selectedRange = focusedFrame->selection()->toNormalizedRange();
1596 Vector<IntRect> rects;
1597 selectedRange->boundingBoxEx(rects, true);
1599 unsigned size = rects.size();
1601 leftRect = rects[0];
1602 rightRect = rects[size-1];
1604 // If selection rect size is greater than editor rect size because of round operation,
1605 // selection rect size should be changed to editor rect size.
1607 Element* rootEditableElement = focusedFrame->selection()->rootEditableElement();
1608 if (rootEditableElement) {
1609 Vector<IntRect> rects;
1610 calcFocusedRects(rootEditableElement, rects);
1611 IntRect editorRect = unionRect(rects);
1613 if (m_editorState.editorRect != editorRect)
1614 updatedEditorRect = editorRect;
1615 if (leftRect.maxY() > editorRect.maxY()) {
1616 leftRect.setY(editorRect.y());
1617 leftRect.setHeight(editorRect.height());
1620 if (rightRect.maxY() > editorRect.maxY()) {
1621 rightRect.setY(editorRect.y());
1622 rightRect.setHeight(editorRect.height());
1626 // prevent from selecting zero-length selection
1627 if (leftRect.x() == rightRect.x() + rightRect.width()
1628 && leftRect.y() == rightRect.y())
1631 FrameView* frameView = focusedFrame->view();
1635 leftRect = frameView->contentsToWindow(leftRect);
1636 rightRect = frameView->contentsToWindow(rightRect);
1637 selectionDirection = focusedFrame->selection()->getSelectionTextDirection();
1641 void WebPage::getSelectionText(String& result)
1643 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1644 result = focusedFrame->editor()->selectedText();
1647 void WebPage::selectionRangeClear(bool& result)
1651 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1652 FrameSelection* frameSelection = focusedFrame->selection();
1653 if (frameSelection && frameSelection->isRange() && frameSelection->isContentEditable()) {
1654 VisiblePosition visiblePos(frameSelection->extent());
1655 if (visiblePos.isNull())
1658 focusedFrame->editor()->setIgnoreCompositionSelectionChange(true);
1659 frameSelection->setSelection(VisibleSelection(visiblePos), CharacterGranularity);
1660 focusedFrame->editor()->setIgnoreCompositionSelectionChange(false);
1662 frameSelection->setCaretBlinkingSuspended(false);
1664 selectionClearAllSelection(m_page->mainFrame());
1669 void WebPage::selectionClearAllSelection(Frame* frame)
1674 FrameSelection* frameSelection = frame->selection();
1676 frameSelection->clear();
1681 if (frame->tree()->childCount() > 0) {
1682 if (frame->tree()->firstChild())
1683 selectionClearAllSelection(frame->tree()->firstChild());
1684 } else if (frame->tree()->nextSibling())
1685 selectionClearAllSelection(frame->tree()->nextSibling());
1688 void WebPage::scrollContentByCharacter(const IntPoint&, int direction, bool& result)
1692 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1696 FrameSelection* frameSelection = focusedFrame->selection();
1697 if (!frameSelection)
1700 VisiblePosition currentPosition = frameSelection->selection().visibleStart();
1702 if (isStartOfLine(currentPosition))
1705 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionBackward, CharacterGranularity, UserTriggered);
1707 if (isEndOfLine(currentPosition))
1710 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, CharacterGranularity, UserTriggered);
1714 void WebPage::scrollContentByLine(const IntPoint&, int direction, bool& result)
1718 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1722 FrameSelection* frameSelection = focusedFrame->selection();
1723 if (!frameSelection)
1726 VisiblePosition currentPosition = frameSelection->selection().visibleStart();
1728 if (inSameLine(currentPosition, previousLinePosition(currentPosition, 0)))
1731 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionBackward, LineGranularity, UserTriggered);
1733 if (inSameLine(currentPosition, nextLinePosition(currentPosition, 0)))
1736 focusedFrame->selection()->modify(FrameSelection::AlterationMove, DirectionForward, LineGranularity, UserTriggered);
1740 void WebPage::getFocusedSubFrameRect(IntRect& focusedFrameRect, bool& isFocusedSubFrame)
1742 isFocusedSubFrame = false;
1744 Frame* focusedFrame = m_page->focusController()->focusedOrMainFrame();
1748 if (focusedFrame != m_page->mainFrame()) {
1749 FrameView* frameView = focusedFrame->view();
1750 HTMLFrameOwnerElement* ownerElement = focusedFrame->ownerElement();
1755 if (ownerElement && ownerElement->hasTagName(HTMLNames::iframeTag)){
1756 RenderIFrame* renderIframe = static_cast<RenderIFrame*>(ownerElement->renderer());
1758 focusedFrameRect = renderIframe->windowClipRect();
1759 isFocusedSubFrame = true;
1766 #if ENABLE(TIZEN_LINK_MAGNIFIER)
1767 void WebPage::getLinkMagnifierRect(const IntPoint& position, const IntSize& size)
1769 send(Messages::WebPageProxy::DidGetLinkMagnifierRect(position, LinkMagnifier::rect(this, position, size)));
1773 #if ENABLE(TIZEN_SCREEN_READER)
1774 void WebPage::moveScreenReaderFocus(bool forward, bool& result)
1776 if (!m_screenReader)
1777 m_screenReader = ScreenReader::create(this);
1779 result = m_screenReader->moveFocus(forward);
1782 void WebPage::moveScreenReaderFocusByPoint(const IntPoint& point)
1784 if (!m_screenReader)
1785 m_screenReader = ScreenReader::create(this);
1787 if (!m_screenReader->moveFocus(point))
1791 void WebPage::clearScreenReaderFocus()
1793 if (!m_screenReader)
1796 m_screenReader->clearFocus();
1799 void WebPage::raiseTapEvent(const IntPoint& position, const IntPoint& globalPosition, bool& result)
1803 #if ENABLE(GESTURE_EVENTS)
1804 Frame* frame = m_page->mainFrame();
1808 Vector<WebPlatformTouchPoint> touchPoints;
1809 touchPoints.append(WebPlatformTouchPoint(0, WebPlatformTouchPoint::TouchPressed, globalPosition, position));
1811 WebTouchEvent touchStartEvent(WebEvent::TouchStart, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1812 bool handled = frame->eventHandler()->handleTouchEvent(platform(touchStartEvent));
1814 touchPoints.at(0).setState(WebPlatformTouchPoint::TouchReleased);
1816 WebTouchEvent touchEndEvent(WebEvent::TouchEnd, touchPoints, WebEvent::Modifiers(0), ecore_time_get());
1817 handled |= frame->eventHandler()->handleTouchEvent(platform(touchEndEvent));
1820 WebGestureEvent gestureEvent(WebEvent::GestureSingleTap, position, globalPosition, WebEvent::Modifiers(0), ecore_time_get());
1821 frame->eventHandler()->handleGestureEvent(platform(gestureEvent));
1827 void WebPage::adjustScreenReaderFocusedObjectValue(bool up)
1829 if (!m_screenReader || !m_focusedNode || !m_focusedNode->toInputElement())
1834 m_focusedNode->toInputElement()->stepUp(ec);
1836 m_focusedNode->toInputElement()->stepDown(ec);
1839 void WebPage::updateScreenReaderFocus(RenderObject* object)
1841 if (!m_screenReader)
1845 m_screenReader->clearFocus();
1846 else if (!m_screenReader->rendererWillBeDestroyed(object))
1850 void WebPage::clearScreenReader()
1852 m_screenReader.clear();
1856 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
1857 static LayoutRect rectToAbsoluteCoordinates(Frame* initialFrame, const LayoutRect& initialRect)
1859 LayoutRect rect = initialRect;
1860 for (Frame* frame = initialFrame; frame; frame = frame->tree()->parent()) {
1861 RenderBoxModelObject* renderer;
1862 if (frame->ownerElement() && (renderer = frame->ownerElement()->renderBoxModelObject())) {
1864 rect.move(renderer->offsetLeft(), renderer->offsetTop());
1865 } while ((renderer = renderer->offsetParent()));
1866 rect.move(-frame->view()->scrollOffset());
1872 void WebPage::calcFocusedRects(Node* node, Vector<IntRect>& rects) const
1874 if (!node || !node->renderer())
1877 RenderObject* renderer = node->renderer();
1878 FrameView* view = node->document()->frame()->view();
1881 if (node->hasTagName(HTMLNames::areaTag)) {
1882 HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node);
1883 HTMLImageElement* image = area->imageElement();
1884 if (image && image->renderer())
1885 rect = rectToAbsoluteCoordinates(area->document()->frame(), area->computeRect(area->imageElement()->renderer()));
1886 } else if (node->renderer()) {
1887 if (node->isDocumentNode())
1888 rect = rectToAbsoluteCoordinates(static_cast<Document*>(node)->frame(), static_cast<Document*>(node)->frame()->view()->visibleContentRect());
1890 rect = rectToAbsoluteCoordinates(node->document()->frame(), node->renderer()->absoluteClippedOverflowRect());
1893 if (rect.pixelSnappedX() < 0)
1894 rect.shiftXEdgeTo(0);
1895 if (rect.pixelSnappedY() < 0)
1896 rect.shiftYEdgeTo(0);
1901 IntRect focusedNodeRect(pixelSnappedIntRect(rect));
1902 IntPoint absolutePoint;
1903 absolutePoint = view->convertToContainingWindow(view->convertFromRenderer(renderer, absolutePoint));
1904 Vector<IntRect> candidateRects;
1905 renderer->addFocusRingRects(candidateRects, absolutePoint);
1907 for (size_t i = 0; i < candidateRects.size(); ++i) {
1908 IntRect candidate(candidateRects[i]);
1909 candidate.intersect(focusedNodeRect);
1910 if (!candidate.isEmpty())
1911 rects.append(candidate);
1914 if (rects.isEmpty())
1915 rects.append(focusedNodeRect);
1919 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
1920 void WebPage::setFocusedNode(Node* node)
1922 m_focusedNode = node;
1923 didChangeFocusedRects();
1926 void WebPage::didChangeFocusedRects()
1928 Vector<IntRect> rects;
1929 calcFocusedRects(m_focusedNode.get(), rects);
1930 m_focusedRects = rects;
1931 send(Messages::WebPageProxy::DidChangeFocusedRects(m_focusedRects));
1934 void WebPage::recalcFocusedRects()
1939 didChangeFocusedRects();
1943 #if ENABLE(TIZEN_WEBKIT2_POPUP_INTERNAL)
1944 // FIXME: Currently with cached pages, hiding Popup list menu is not working correctly.
1945 // This patch is a fix allowing any popup list menu to get close for any page navigation.
1946 void WebPage::notifyTransitionToCommitted(bool forNewPage)
1948 if (m_activePopupMenu) {
1950 m_activePopupMenu->hide();
1951 m_activePopupMenu = 0;
1956 #if ENABLE(TIZEN_CSP)
1957 void WebPage::setContentSecurityPolicy(const String& policy, uint32_t headerType)
1959 Frame* frame = m_page->focusController()->focusedOrMainFrame();
1963 Document* document = frame->document();
1967 document->contentSecurityPolicy()->didReceiveHeader(policy, static_cast<WebCore::ContentSecurityPolicy::HeaderType>(headerType));
1971 #if ENABLE(TIZEN_INDEXED_DATABASE)
1972 void WebPage::setIndexedDatabaseDirectory(const String& path)
1974 m_page->group().groupSettings()->setIndexedDBDatabasePath(path);
1978 #if ENABLE(TIZEN_WEB_STORAGE)
1979 void WebPage::setLocalStorageDirectory(const String& path)
1981 m_page->settings()->setLocalStorageDatabasePath(path);
1985 #if ENABLE(TIZEN_USE_SETTINGS_FONT)
1986 void WebPage::useSettingsFont()
1988 if (!WebCore::fontCache()->isFontFamliyTizen())
1991 FcInitReinitialize();
1992 WebCore::fontCache()->invalidate();
1994 int pageCapacity = WebCore::pageCache()->capacity();
1995 // Setting size to 0, makes all pages be released.
1996 WebCore::pageCache()->setCapacity(0);
1997 WebCore::pageCache()->releaseAutoreleasedPagesNow();
1998 WebCore::pageCache()->setCapacity(pageCapacity);
2000 Frame* frame = m_mainFrame->coreFrame();
2004 if (frame->document())
2005 frame->document()->dispatchWindowEvent(Event::create(eventNames().resizeEvent, false, false));
2007 FrameView* frameView = frame->view();
2011 frameView->forceLayout();
2015 void WebPage::didChangeContents()
2020 Frame* frame = m_page->focusController()->focusedOrMainFrame();
2021 if (!frame || !frame->view() || frame->view()->needsLayout())
2024 #if ENABLE(TIZEN_ISF_PORT) || ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
2025 if (m_editorState.isContentEditable && frame->selection()->rootEditableElement() && updateEditorStateRect(frame, m_editorState)) {
2026 m_editorState.updateEditorRectOnly = true;
2027 send(Messages::WebPageProxy::EditorStateChanged(m_editorState));
2031 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
2032 didChangeFocusedRects();
2036 #if ENABLE(TIZEN_FOCUS_UI)
2037 void WebPage::setFocusUIEnabled(bool enabled)
2039 m_page->settings()->setSpatialNavigationEnabled(enabled);
2041 if (m_focusedNode && m_focusedNode->renderer())
2042 m_focusedNode->renderer()->repaint();
2045 Frame* frame = m_page->focusController()->focusedOrMainFrame();
2047 PlatformMouseEvent fakeMouseMove(IntPoint(-1, -1), IntPoint(-1, -1), NoButton, PlatformEvent::MouseMoved, 0, false, false, false, false, currentTime());
2048 frame->eventHandler()->mouseMoved(fakeMouseMove);
2050 setFocusedNode(frame && frame->document() ? frame->document()->focusedNode() : 0);
2055 #endif // #if OS(TIZEN)
2057 } // namespace WebKit