2 * Copyright (C) 2012 Samsung Electronics
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
28 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
29 #include "TextSelection.h"
31 #include "EditorState.h"
32 #include "EwkViewImpl.h"
33 #include "NativeWebMouseEvent.h"
35 #include <Elementary.h>
37 using namespace WebCore;
41 const int zIndexDefault = -999;
43 TextSelection::TextSelection(EwkViewImpl* viewImpl)
44 : m_viewImpl(viewImpl)
45 , m_isTextSelectionDowned(false)
46 , m_isTextSelectionMode(false)
49 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
52 , m_handleMovingDirection(HandleMovingDirectionNormal)
53 , m_isSelectionInScrollingMode(false)
54 , m_isAutoWordSelectionScheduled(false)
58 const Eina_List* defaultThemeList = elm_theme_list_get(0);
62 EINA_LIST_FOREACH(defaultThemeList, l, theme) {
63 char* themePath = elm_theme_list_item_path_get((const char*)theme, 0);
66 m_leftHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_left", true, this);
67 m_rightHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_right", false, this);
74 m_magnifier = new TextSelectionMagnifier(m_viewImpl);
75 m_zIndex.append(zIndexDefault);
76 m_zIndex.append(zIndexDefault);
77 m_zIndex.append(zIndexDefault);
78 evas_object_event_callback_add(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
81 TextSelection::~TextSelection()
92 ecore_animator_del(m_moveAnimator);
97 ecore_timer_del(m_showTimer);
100 evas_object_event_callback_del(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp);
103 void TextSelection::update()
105 EditorState editorState = m_viewImpl->page()->editorState();
106 if (editorState.updateEditorRectOnly)
109 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
110 if (!editorState.shouldIgnoreCompositionSelectionChange && ewk_settings_text_style_state_enabled_get(ewk_view_settings_get(m_viewImpl->view())))
111 informTextStyleState();
114 if (!editorState.shouldIgnoreCompositionSelectionChange && !editorState.hasComposition && m_isAutoWordSelectionScheduled)
115 setAutoWordSelection(m_scheduledAutoWordSelectionPosition);
117 if (isTextSelectionMode()) {
118 if (!editorState.selectionIsRange) {
119 if (editorState.isContentEditable && !evas_object_focus_get(m_viewImpl->view())) {
120 const EditorState& editor = m_viewImpl->page()->editorState();
122 if (!editor.selectionIsNone && !editor.selectionIsRange)
123 caretRect = editor.selectionRect;
125 if (!caretRect.isEmpty()) {
126 setIsTextSelectionMode(false);
130 WebCore::IntRect leftRect;
131 WebCore::IntRect rightRect;
132 int selectionDirection = LToR;
133 if (isTextSelectionDowned() || m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection))
136 setIsTextSelectionMode(false);
139 if (!isTextSelectionDowned() && !isTextSelectionHandleDowned()) {
146 // Auto selection happened from the JS through Editor command and update called from
147 // WebPageProxy::editorStateChanged(), so need to update the selection handler and context
148 // menu because focused node is currently active.
149 if (editorState.isContentEditable && !editorState.shouldIgnoreCompositionSelectionChange && editorState.selectionIsRange && !editorState.selectionRect.isEmpty() && m_viewImpl->page()
150 && m_viewImpl->page()->isLoadingFinished()) {
151 setIsTextSelectionMode(true);
157 void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
159 if (!isTextSelectionMode) {
162 initHandlesMouseDownedStatus();
163 setIsTextSelectionDowned(false);
166 m_isTextSelectionMode = isTextSelectionMode;
169 void TextSelection::clear()
171 EditorState editorState = m_viewImpl->page()->editorState();
172 if (!editorState.selectionIsRange)
175 m_zIndex[0] = zIndexDefault;
176 m_zIndex[1] = zIndexDefault;
177 m_zIndex[2] = zIndexDefault;
178 m_viewImpl->page()->selectionRangeClear();
181 void TextSelection::hide()
188 // int handle represents 0 - Left handle 1 - Right handle 2 - ContextMenu
189 bool TextSelection::shouldShowObject(WebCore::IntPoint handlePoint, int handle)
191 WebHitTestResult::Data hitrestatpoint;
192 hitrestatpoint = m_viewImpl->page()->hitTestResultAtPoint(m_viewImpl->transformFromScene().mapPoint(handlePoint), WebHitTestResult::HitTestModeNodeData);
193 if (m_zIndex[handle] < hitrestatpoint.nodeData.zIndex && m_zIndex[handle] != zIndexDefault)
196 if (m_zIndex[handle] > hitrestatpoint.nodeData.zIndex)
197 m_zIndex[handle] = zIndexDefault;
199 m_zIndex[handle] = hitrestatpoint.nodeData.zIndex;
204 void TextSelection::updateHandlers()
206 WebCore::IntRect leftRect, rightRect;
207 int selectionDirection = LToR;
208 if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection))
211 m_lastLeftHandleRect = m_viewImpl->transformToScene().mapRect(leftRect);
212 m_lastRightHandleRect = m_viewImpl->transformToScene().mapRect(rightRect);
214 AffineTransform toEvasTransform = m_viewImpl->transformToScene();
215 WebCore::IntPoint leftEvasPoint ;
216 WebCore::IntPoint rightEvasPoint ;
218 // Selection Direction 1 -> L2R, Selection is Left to Right
219 if (selectionDirection == LToR) {
220 leftEvasPoint = toEvasTransform.mapPoint(leftRect.minXMaxYCorner());
221 rightEvasPoint = toEvasTransform.mapPoint(rightRect.maxXMaxYCorner());
223 // Selection Direction 0 -> R2L, Selection is Right to Left
225 leftEvasPoint = toEvasTransform.mapPoint(leftRect.maxXMaxYCorner());
226 rightEvasPoint = toEvasTransform.mapPoint(rightRect.minXMaxYCorner());
228 TextSelectionHandle* shownLeftHandle = m_leftHandle;
229 TextSelectionHandle* shownRightHandle = m_rightHandle;
231 if (m_handleMovingDirection == HandleMovingDirectionReverse) {
232 shownLeftHandle = m_rightHandle;
233 shownRightHandle = m_leftHandle;
236 EditorState editorState = m_viewImpl->page()->editorState();
237 if (editorState.isContentEditable) {
238 shownLeftHandle->hide();
239 shownRightHandle->hide();
241 WebCore::IntRect editorRect = editorState.editorRect;
242 WebCore::IntPoint editorLeftEvasPoint = toEvasTransform.mapPoint(editorRect.location());
243 WebCore::IntPoint editorRightEvasPoint = toEvasTransform.mapPoint(editorRect.maxXMaxYCorner());
244 int webViewX, webViewY, webViewWidth, webViewHeight;
246 evas_object_geometry_get(m_viewImpl->view(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
247 if ((editorLeftEvasPoint.x() <= leftEvasPoint.x() && editorLeftEvasPoint.y() <= leftEvasPoint.y())
248 && (webViewX <= leftEvasPoint.x() && webViewY <= leftEvasPoint.y())) {
249 if (shouldShowObject(leftEvasPoint, 0)) {
250 shownLeftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect), (selectionDirection == LToR?true:false));
251 shownLeftHandle->show();
255 if ((editorRightEvasPoint.x() >= rightEvasPoint.x() && editorRightEvasPoint.y() >= rightEvasPoint.y())
256 && ((webViewX + webViewWidth) >= rightEvasPoint.x() && (webViewY <= rightEvasPoint.y() && (webViewY + webViewHeight) >= rightEvasPoint.y()))) {
257 if (shouldShowObject(rightEvasPoint, 1)) {
258 shownRightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect), (selectionDirection == LToR?true:false));
259 shownRightHandle->show();
263 if (shouldShowObject(leftEvasPoint, 0)) {
264 shownLeftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect), (selectionDirection == LToR?true:false));
265 shownLeftHandle->show();
267 if (shouldShowObject(rightEvasPoint, 1)) {
268 shownRightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect), (selectionDirection == LToR?true:false));
269 shownRightHandle->show();
274 void TextSelection::hideHandlers()
276 m_leftHandle->hide();
277 m_rightHandle->hide();
280 void TextSelection::showMagnifier()
285 void TextSelection::hideMagnifier()
290 void TextSelection::updateMagnifier(const IntPoint& position)
292 m_magnifier->update(position);
293 m_magnifier->move(position);
296 void TextSelection::showContextMenu()
301 EditorState editorState = m_viewImpl->page()->editorState();
302 if (!editorState.selectionIsRange && !editorState.isContentEditable)
305 WebCore::IntPoint point;
306 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
307 bool isPresentInViewPort = false;
309 if (editorState.selectionIsRange) {
310 WebCore::IntRect leftRect, rightRect;
311 int selectionDirection = LToR;
312 if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection))
315 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
316 // Checking if this point is in viewport area. If the calcualated
317 // point/Left/Right point are in view port then draw else do not draw the
318 // context menu. Only draw the selection points.
319 FloatRect unscaledRect = FloatRect(m_viewImpl->pageClient->visibleContentRect());
320 unscaledRect.scale(1 / m_viewImpl->pageClient->scaleFactor());
321 IntRect viewportRect = enclosingIntRect(unscaledRect);
323 WebCore::IntPoint visiblePoint = leftRect.center();
324 if (viewportRect.contains(visiblePoint)) {
325 // First check That the modified points are present in view port
326 point = visiblePoint;
327 isPresentInViewPort = true;
328 } else if (viewportRect.contains(leftRect.location())) {
329 // else if the calculated point is not in the view port area the
330 // draw context menu at left point if visible
331 point = leftRect.location();
332 isPresentInViewPort = true;
333 } else if (viewportRect.contains(rightRect.maxXMinYCorner())) {
334 // else if the calculated point is not in the view port area the
335 // draw context menu at right point if visible
336 point = rightRect.maxXMinYCorner();
337 isPresentInViewPort = true;
340 if (isPresentInViewPort && editorState.isContentEditable) {
341 // In case of single line editor box.
342 if (leftRect == rightRect) {
343 // draw context menu at center point of visible selection range in the editor box
344 IntRect editorRect = editorState.editorRect;
345 leftRect.intersect(editorRect);
346 if (!leftRect.isEmpty())
347 point = leftRect.center();
349 // not draw context menu if there is no visible selection range in the editor box
350 isPresentInViewPort = false;
355 point = leftRect.center();
357 } else if (editorState.isContentEditable) {
358 const EditorState& editor = m_viewImpl->page()->editorState();
360 if (!editor.selectionIsNone && !editor.selectionIsRange)
361 caretRect = editor.selectionRect;
363 if (caretRect.isEmpty())
366 point = caretRect.center();
367 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
368 isPresentInViewPort = true;
371 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
372 if (!isPresentInViewPort)
376 // show context menu if its in viewport else do not show the contextmenu
377 Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewImpl->view()));
378 if (!smartData || !smartData->api || !smartData->api->mouse_down || !smartData->api->mouse_up)
381 point = m_viewImpl->transformToScene().mapPoint(point);
382 Evas* evas = evas_object_evas_get(m_viewImpl->view());
384 if (editorState.selectionIsRange && !shouldShowObject(point,2))
388 Evas_Event_Mouse_Down mouseDown;
389 mouseDown.button = 3;
390 mouseDown.output.x = mouseDown.canvas.x = point.x();
391 mouseDown.output.y = mouseDown.canvas.y = point.y();
393 mouseDown.modifiers = const_cast<Evas_Modifier*>(evas_key_modifier_get(evas));
394 mouseDown.locks = const_cast<Evas_Lock*>(evas_key_lock_get(evas));
395 mouseDown.flags = EVAS_BUTTON_NONE;
396 mouseDown.timestamp = ecore_time_get() * 1000;
397 mouseDown.event_flags = EVAS_EVENT_FLAG_NONE;
399 smartData->api->mouse_down(smartData, &mouseDown);
402 Evas_Event_Mouse_Up mouseUp;
404 mouseUp.output.x = mouseUp.canvas.x = point.x();
405 mouseUp.output.y = mouseUp.canvas.y = point.y();
407 mouseUp.modifiers = const_cast<Evas_Modifier*>(evas_key_modifier_get(evas));
408 mouseUp.locks = const_cast<Evas_Lock*>(evas_key_lock_get(evas));
409 mouseUp.flags = EVAS_BUTTON_NONE;
410 mouseUp.timestamp = ecore_time_get() * 1000;
411 mouseUp.event_flags = EVAS_EVENT_FLAG_NONE;
413 smartData->api->mouse_up(smartData, &mouseUp);
416 void TextSelection::hideContextMenu()
421 m_viewImpl->page()->hideContextMenu();
424 void TextSelection::scrollContentWithSelectionIfRequired(const IntPoint& evasPoint)
426 // Content should get scroll irrespective whether content is editable or not.
427 setSelectionScrollingStatus(true);
428 IntRect unscaledVisibleContentRect = m_viewImpl->pageClient->visibleContentRect();
429 const int scrollClipValue = 50;
430 if (evasPoint.y() >= (unscaledVisibleContentRect.height() - scrollClipValue))
431 m_viewImpl->pageClient->scrollBy(IntSize(0, m_rightHandle->getHandleRect().height()));
432 else if (evasPoint.y() <= scrollClipValue) {
433 IntSize scrollSize(0, m_rightHandle->getHandleRect().height());
434 scrollSize.scale(-1);
435 m_viewImpl->pageClient->scrollBy(scrollSize);
438 if (evasPoint.x() >= (unscaledVisibleContentRect.width() - scrollClipValue))
439 m_viewImpl->pageClient->scrollBy(IntSize(m_rightHandle->getHandleRect().width(),0));
440 else if (evasPoint.x() <= scrollClipValue) {
441 IntSize scrollSize(m_rightHandle->getHandleRect().width(), 0);
442 scrollSize.scale(-1);
443 m_viewImpl->pageClient->scrollBy(scrollSize);
445 setSelectionScrollingStatus(false);
448 void TextSelection::setLeftSelectionToEvasPoint(const IntPoint& evasPoint)
450 scrollContentWithSelectionIfRequired(evasPoint);
451 int result = m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint), m_handleMovingDirection);
453 m_handleMovingDirection = result;
457 void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
459 scrollContentWithSelectionIfRequired(evasPoint);
460 int result = m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint), m_handleMovingDirection);
462 m_handleMovingDirection = result;
467 void TextSelection::handleMouseDown(TextSelectionHandle* handle, const IntPoint& /*position*/)
469 WebCore::IntPoint basePosition;
470 EditorState editorState = m_viewImpl->page()->editorState();
472 if (editorState.selectionIsRange) {
473 WebCore::IntRect leftRect, rightRect;
474 int selectionDirection = LToR, adjustValue = 2;
475 if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection)) {
479 (editorState.isOnlyImageSelection == true)?adjustValue = 1:adjustValue = 2;
480 if (handle->isLeft()) {
481 if (selectionDirection == LToR) {
482 basePosition.setX(leftRect.x());
483 basePosition.setY(leftRect.y() + (leftRect.height()/adjustValue));
485 basePosition.setX(leftRect.x() + leftRect.width());
486 basePosition.setY(leftRect.y() + (leftRect.height()/adjustValue));
489 if (selectionDirection == LToR) {
490 basePosition.setX(rightRect.x() + rightRect.width());
491 basePosition.setY(rightRect.y() + (rightRect.height()/adjustValue));
493 basePosition.setX(rightRect.x());
494 basePosition.setY(rightRect.y() + (rightRect.height()/adjustValue));
497 handle->setBasePositionForMove(m_viewImpl->transformToScene().mapPoint(basePosition));
502 updateMagnifier(handle->position());
506 void TextSelection::handleMouseMove(TextSelectionHandle* handle, const IntPoint& position)
508 if (handle->isLeft())
509 setLeftSelectionToEvasPoint(position);
511 setRightSelectionToEvasPoint(position);
513 updateMagnifier(handle->position());
516 void TextSelection::handleMouseUp(TextSelectionHandle* /* handle */, const IntPoint& /* position */)
518 m_handleMovingDirection = HandleMovingDirectionNormal;
525 bool TextSelection::isMagnifierVisible()
527 return m_magnifier->isVisible();
530 void TextSelection::updateHandlesAndContextMenu(bool isShow, bool isScrolling)
532 if (getSelectionScrollingStatus())
535 if (isTextSelectionDowned() && !isScrolling) {
540 if (m_viewImpl->gestureClient->isGestureWorking()) {
541 EditorState editorState = m_viewImpl->page()->editorState();
542 if (!editorState.selectionIsRange && editorState.isContentEditable)
543 setIsTextSelectionMode(false);
547 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
548 if (m_viewImpl->pageClient->isClipboardWindowOpened())
551 if (m_viewImpl->gestureClient->isGestureWorking())
564 if (isScrolling && isMagnifierVisible())
568 void TextSelection::startMoveAnimator()
570 if (!isEnabled() || !isTextSelectionDowned())
574 m_moveAnimator = ecore_animator_add(moveAnimatorCallback, this);
577 void TextSelection::stopMoveAnimator()
579 if (m_moveAnimator) {
580 ecore_animator_del(m_moveAnimator);
585 void TextSelection::onMouseUp(void* data, Evas*, Evas_Object*, void* eventInfo)
587 static_cast<TextSelection*>(data)->textSelectionUp(IntPoint());
590 Eina_Bool TextSelection::moveAnimatorCallback(void* data)
592 TextSelection* textSelection = static_cast<TextSelection*>(data);
594 Evas_Coord_Point point;
595 evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_viewImpl->view()), &point.x, &point.y);
596 textSelection->textSelectionMove(IntPoint(point.x, point.y));
598 return ECORE_CALLBACK_RENEW;
601 // 'return false' means text selection is not possible for point.
602 // 'return true' means text selection is possible.
603 bool TextSelection::textSelectionDown(const IntPoint& point)
605 // text selection should be ignored when longtap on handle from osp
606 if (!isEnabled() && isTextSelectionHandleDowned())
609 #if ENABLE(TIZEN_ISF_PORT)
610 m_viewImpl->inputMethodContext()->resetIMFContext();
612 setIsTextSelectionMode(false);
614 IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
615 bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, false);
619 if (isTextSelectionMode()) {
622 setIsTextSelectionMode(true);
624 setIsTextSelectionDowned(true);
626 updateMagnifier(point);
634 static int s_textSelectionMargin = 5;
636 void TextSelection::textSelectionMove(const IntPoint& point)
638 // text selection should be ignored when longtap on handle from osp
639 if (!isEnabled() && isTextSelectionHandleDowned())
642 if (!isTextSelectionMode()) {
647 WebCore::IntPoint viewPoint;
648 EditorState editorState = m_viewImpl->page()->editorState();
649 bool isInEditablePicker = false;
651 #if ENABLE(TIZEN_INPUT_TAG_EXTENSION)
652 if (editorState.isContentEditable) {
653 if (editorState.inputMethodHints == "date"
654 || editorState.inputMethodHints == "datetime"
655 || editorState.inputMethodHints == "datetime-local"
656 || editorState.inputMethodHints == "month"
657 || editorState.inputMethodHints == "time"
658 || editorState.inputMethodHints == "week")
659 isInEditablePicker = true;
663 if (editorState.isContentEditable && !isInEditablePicker) {
664 IntRect mapRect = m_viewImpl->transformToScene().mapRect(editorState.editorRect);
665 IntPoint updatedPoint = point;
666 bool scrolledY = false;
667 if (point.y() < mapRect.y()) {
668 updatedPoint.setY(mapRect.y() + s_textSelectionMargin);
669 if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionBackward)) {
671 updateMagnifier(updatedPoint);
673 } else if (point.y() > mapRect.maxY()) {
674 updatedPoint.setY(mapRect.maxY() - s_textSelectionMargin);
675 if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionForward)) {
677 updateMagnifier(updatedPoint);
681 bool scrolledX = false;
682 if (point.x() < mapRect.x()) {
683 updatedPoint.setX(mapRect.x() + s_textSelectionMargin);
684 if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward)) {
686 updateMagnifier(updatedPoint);
688 } else if (point.x() > mapRect.maxX()) {
689 updatedPoint.setX(mapRect.maxX() - s_textSelectionMargin);
690 if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward)) {
692 updateMagnifier(updatedPoint);
696 if (!scrolledX && !scrolledY) {
697 viewPoint = m_viewImpl->transformFromScene().mapPoint(updatedPoint);
698 m_viewImpl->page()->selectClosestWord(viewPoint, false);
699 updateMagnifier(updatedPoint);
702 viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
703 m_viewImpl->page()->selectClosestWord(viewPoint, false);
704 updateMagnifier(point);
709 void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSelectionFromOutside)
711 // text selection should be ignored when longtap on handle from osp
712 if (!isEnabled() && isTextSelectionHandleDowned())
717 if (!isTextSelectionMode() || !isTextSelectionDowned())
720 setIsTextSelectionDowned(false);
723 EditorState editorState = m_viewImpl->page()->editorState();
724 if (editorState.selectionIsRange || editorState.isContentEditable) {
725 if (editorState.selectionIsRange)
729 } else if (!isStartedTextSelectionFromOutside)
730 setIsTextSelectionMode(false);
733 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
734 TextSelectionHandle* TextSelection::getSelectedHandle(const IntPoint& position)
736 WebCore::IntRect leftHandleRect = m_leftHandle->getHandleRect();
737 if (!leftHandleRect.isEmpty() && leftHandleRect.contains(position))
740 WebCore::IntRect rightHandleRect = m_rightHandle->getHandleRect();
741 if (!rightHandleRect.isEmpty() && rightHandleRect.contains(position))
742 return m_rightHandle;
747 void TextSelection::textSelectionHandleDown(const IntPoint& position)
749 m_selectedHandle = getSelectedHandle(position);
750 if (m_selectedHandle)
751 m_selectedHandle->mouseDown(position);
753 initHandlesMouseDownedStatus();
756 void TextSelection::textSelectionHandleMove(const IntPoint& position)
758 if (m_selectedHandle && isTextSelectionHandleDowned())
759 m_selectedHandle->mouseMove(position);
762 void TextSelection::textSelectionHandleUp()
764 if (m_selectedHandle && isTextSelectionHandleDowned()) {
765 m_selectedHandle->mouseUp();
766 m_selectedHandle = 0;
771 bool TextSelection::isEnabled()
773 return ewk_settings_text_selection_enabled_get(ewk_view_settings_get(m_viewImpl->view()));
776 bool TextSelection::isAutomaticClearEnabled()
778 return ewk_settings_clear_text_selection_automatically_get(ewk_view_settings_get(m_viewImpl->view()));
781 void TextSelection::requestToShow()
783 EditorState editorState = m_viewImpl->page()->editorState();
784 if (!editorState.selectionIsRange && editorState.isContentEditable) {
785 setIsTextSelectionMode(false);
790 ecore_timer_del(m_showTimer);
791 m_showTimer = ecore_timer_loop_add((double)200.0/1000.0, showTimerCallback, this);
794 Eina_Bool TextSelection::showTimerCallback(void* data)
796 TextSelection* textSelection = static_cast<TextSelection*>(data);
797 textSelection->showHandlesAndContextMenu();
799 return ECORE_CALLBACK_RENEW;
802 void TextSelection::showHandlesAndContextMenu()
804 WebCore::IntRect leftRect, rightRect;
805 int selectionDirection = LToR;
806 if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection)) {
807 leftRect = m_viewImpl->transformToScene().mapRect(leftRect);
808 rightRect = m_viewImpl->transformToScene().mapRect(rightRect);
809 if ((leftRect == m_lastLeftHandleRect) && (rightRect == m_lastRightHandleRect)) {
811 ecore_timer_del(m_showTimer);
815 updateHandlesAndContextMenu(true);
818 m_lastLeftHandleRect = leftRect;
819 m_lastRightHandleRect = rightRect;
823 void TextSelection::initHandlesMouseDownedStatus()
825 m_leftHandle->setIsMouseDowned(false);
826 m_rightHandle->setIsMouseDowned(false);
829 void TextSelection::changeContextMenuPosition(WebCore::IntPoint& position)
831 if (m_leftHandle->isTop()) {
832 IntRect handleRect = m_leftHandle->getHandleRect();
833 position.setY(position.y() - handleRect.height());
837 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
838 void TextSelection::informTextStyleState()
840 WebCore::IntPoint startPoint, endPoint;
841 WebCore::IntRect leftRect, rightRect;
842 int selectionDirection = LToR;
844 const EditorState& editor = m_viewImpl->page()->editorState();
846 if (!editor.selectionIsNone && !editor.selectionIsRange)
847 caretRect = editor.selectionRect;
849 if (!caretRect.isEmpty()) {
850 startPoint.setX(caretRect.x());
851 startPoint.setY(caretRect.y() + caretRect.height());
853 endPoint.setX(caretRect.x() + caretRect.width());
854 endPoint.setY(caretRect.y() + caretRect.height());
856 else if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect, selectionDirection)) {
857 startPoint.setX(leftRect.x());
858 startPoint.setY(leftRect.y() + leftRect.height());
860 endPoint.setX(rightRect.x() + rightRect.width());
861 endPoint.setY(rightRect.y() + rightRect.height());
864 AffineTransform toEvasTransform = m_viewImpl->transformToScene();
865 WebCore::IntPoint startEvasPoint = toEvasTransform.mapPoint(startPoint);
866 WebCore::IntPoint endEvasPoint = toEvasTransform.mapPoint(endPoint);
868 ewkViewTextStyleState(m_viewImpl->view(), startEvasPoint, endEvasPoint);
872 void TextSelection::selectWordAutomatically(const IntPoint& point)
874 EditorState editorState = m_viewImpl->page()->editorState();
875 if (editorState.hasComposition) {
876 setAutoWordSelectionScheduled(true, point);
877 m_viewImpl->inputMethodContext()->resetIMFContext();
881 setAutoWordSelection(point);
884 void TextSelection::setAutoWordSelectionScheduled(bool scheduled, const IntPoint& position)
886 m_isAutoWordSelectionScheduled = scheduled;
887 m_scheduledAutoWordSelectionPosition = position;
890 void TextSelection::setAutoWordSelection(const IntPoint& point)
892 IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
894 setAutoWordSelectionScheduled(false, IntPoint(0, 0));
895 setIsTextSelectionMode(false);
897 bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, true);
901 setIsTextSelectionMode(true);
906 } // namespace WebKit
908 #endif // TIZEN_WEBKIT2_TEXT_SELECTION