Merge "[CherryPick] [WEBGL] Rename WEBKIT_WEBGL_lose_context to WEBGL_lose_context...
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / TextSelection.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
29 #include "TextSelection.h"
30
31 #include "EditorState.h"
32 #include "EwkViewImpl.h"
33 #include "NativeWebMouseEvent.h"
34 #include "ewk_view.h"
35 #include <Elementary.h>
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 TextSelection::TextSelection(EwkViewImpl* viewImpl)
42       : m_viewImpl(viewImpl)
43       , m_isTextSelectionDowned(false)
44       , m_isTextSelectionMode(false)
45       , m_moveAnimator(0)
46       , m_showTimer(0)
47 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
48       , m_selectedHandle(0)
49 #endif
50 {
51     ASSERT(viewWidget);
52
53     const Eina_List* defaultThemeList = elm_theme_list_get(0);
54
55     const Eina_List* l;
56     void* theme;
57     EINA_LIST_FOREACH(defaultThemeList, l, theme) {
58         char* themePath = elm_theme_list_item_path_get((const char*)theme, 0);
59
60         if (themePath) {
61             m_leftHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_left", true, this);
62             m_rightHandle = new TextSelectionHandle(m_viewImpl->view(), themePath, "elm/entry/selection/block_handle_right", false, this);
63
64             free(themePath);
65             break;
66         }
67     }
68
69     m_magnifier = new TextSelectionMagnifier(m_viewImpl);
70
71     evas_object_event_callback_add(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp, this);
72 }
73
74 TextSelection::~TextSelection()
75 {
76     if (m_leftHandle)
77         delete m_leftHandle;
78
79     if (m_rightHandle)
80         delete m_rightHandle;
81
82     delete m_magnifier;
83
84     if (m_moveAnimator) {
85         ecore_animator_del(m_moveAnimator);
86         m_moveAnimator = 0;
87     }
88
89     if (m_showTimer) {
90         ecore_timer_del(m_showTimer);
91         m_showTimer = 0;
92     }
93     evas_object_event_callback_del(m_viewImpl->view(), EVAS_CALLBACK_MOUSE_UP, onMouseUp);
94 }
95
96 void TextSelection::update()
97 {
98     EditorState editorState = m_viewImpl->page()->editorState();
99     if (editorState.updateEditorRectOnly)
100         return;
101
102 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
103     if (!editorState.shouldIgnoreCompositionSelectionChange)
104         informTextStyleState();
105 #endif
106
107     if (isTextSelectionMode()) {
108         if (!editorState.selectionIsRange) {
109             if (editorState.isContentEditable && !evas_object_focus_get(m_viewImpl->view())) {
110                 WebCore::IntRect caretRect;
111                 m_viewImpl->page()->getCaretPosition(caretRect);
112                 if (!caretRect.isEmpty())
113                     return;
114             } else {
115                 WebCore::IntRect leftRect;
116                 WebCore::IntRect rightRect;
117                 if (isTextSelectionDowned() || m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
118                     return;
119
120                 setIsTextSelectionMode(false);
121             }
122         } else {
123             if (!isTextSelectionDowned() && !isTextSelectionHandleDowned()) {
124                 updateHandlers();
125                 showContextMenu();
126             }
127         }
128     }
129 }
130
131 void TextSelection::setIsTextSelectionMode(bool isTextSelectionMode)
132 {
133     if (!isAutomaticClearEnabled())
134         return;
135
136     if (!isTextSelectionMode) {
137         hide();
138         clear();
139         initHandlesMouseDownedStatus();
140     }
141
142     m_isTextSelectionMode = isTextSelectionMode;
143 }
144
145 void TextSelection::clear()
146 {
147     EditorState editorState = m_viewImpl->page()->editorState();
148     if (!editorState.selectionIsRange)
149         return;
150
151     m_viewImpl->page()->selectionRangeClear();
152 }
153
154 void TextSelection::hide()
155 {
156     hideHandlers();
157     hideMagnifier();
158     hideContextMenu();
159 }
160
161 void TextSelection::updateHandlers()
162 {
163     WebCore::IntRect leftRect, rightRect;
164     if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
165         return;
166
167     m_lastLeftHandleRect = leftRect;
168     m_lastRightHandleRect = rightRect;
169
170     AffineTransform toEvasTransform = m_viewImpl->transformToScene();
171     WebCore::IntPoint leftEvasPoint = toEvasTransform.mapPoint(leftRect.minXMaxYCorner());
172     WebCore::IntPoint rightEvasPoint = toEvasTransform.mapPoint(rightRect.maxXMaxYCorner());
173
174     EditorState editorState = m_viewImpl->page()->editorState();
175     if (editorState.isContentEditable) {
176         m_leftHandle->hide();
177         m_rightHandle->hide();
178
179         WebCore::IntRect editorRect = editorState.editorRect;
180         WebCore::IntPoint editorLeftEvasPoint = toEvasTransform.mapPoint(editorRect.location());
181         WebCore::IntPoint editorRightEvasPoint = toEvasTransform.mapPoint(editorRect.maxXMaxYCorner());
182         int webViewX, webViewY, webViewWidth, webViewHeight;
183
184         evas_object_geometry_get(m_viewImpl->view(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
185         if ((editorLeftEvasPoint.x() <= leftEvasPoint.x() && editorLeftEvasPoint.y() <= leftEvasPoint.y())
186             && (webViewX <= leftEvasPoint.x() && webViewY <= leftEvasPoint.y())) {
187             m_leftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect));
188             m_leftHandle->show();
189         }
190
191         if ((editorRightEvasPoint.x() >= rightEvasPoint.x() && editorRightEvasPoint.y() >= rightEvasPoint.y())
192             && ((webViewX + webViewWidth) >= rightEvasPoint.x() && (webViewY <= rightEvasPoint.y() && (webViewY + webViewHeight) >= rightEvasPoint.y()))) {
193             m_rightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect));
194             m_rightHandle->show();
195         }
196     } else {
197         m_leftHandle->move(leftEvasPoint, m_viewImpl->transformToScene().mapRect(leftRect));
198         m_leftHandle->show();
199
200         m_rightHandle->move(rightEvasPoint, m_viewImpl->transformToScene().mapRect(rightRect));
201         m_rightHandle->show();
202     }
203 }
204
205 void TextSelection::hideHandlers()
206 {
207     m_leftHandle->hide();
208     m_rightHandle->hide();
209 }
210
211 void TextSelection::showMagnifier()
212 {
213     m_magnifier->show();
214 }
215
216 void TextSelection::hideMagnifier()
217 {
218     m_magnifier->hide();
219 }
220
221 void TextSelection::updateMagnifier(const IntPoint& position)
222 {
223     m_magnifier->update(position);
224     m_magnifier->move(position);
225 }
226
227 void TextSelection::showContextMenu()
228 {
229     if (!isEnabled())
230         return;
231
232     EditorState editorState = m_viewImpl->page()->editorState();
233     if (!editorState.selectionIsRange && !editorState.isContentEditable)
234         return;
235
236     WebCore::IntPoint point;
237 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
238     bool isPresentInViewPort = false;
239 #endif
240     if (editorState.selectionIsRange) {
241         WebCore::IntRect leftRect, rightRect;
242         if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect))
243             return;
244
245 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
246         // Checking if this point is in viewport area. If the calcualated
247         // point/Left/Right point are in view port then draw else do not draw the
248         // context menu. Only draw the selection points.
249         FloatRect unscaledRect = FloatRect(m_viewImpl->pageClient->visibleContentRect());
250         unscaledRect.scale(1 / m_viewImpl->pageClient->scaleFactor());
251         IntRect viewportRect = enclosingIntRect(unscaledRect);
252
253         WebCore::IntPoint visiblePoint = leftRect.center();
254         if (viewportRect.contains(visiblePoint)) {
255             // First check That the modified points are present in view port
256             point = visiblePoint;
257             isPresentInViewPort = true;
258         } else if (viewportRect.contains(leftRect.location())) {
259             // else if the calculated point is not in the view port area the
260             // draw context menu at left point if visible
261             point = leftRect.location();
262             isPresentInViewPort = true;
263         } else if (viewportRect.contains(rightRect.maxXMinYCorner())) {
264             // else if the calculated point is not in the view port area the
265             // draw context menu at right point if visible
266             point = rightRect.maxXMinYCorner();
267             isPresentInViewPort = true;
268         }
269
270         if (isPresentInViewPort && editorState.isContentEditable) {
271             // In case of single line editor box.
272             if (leftRect == rightRect) {
273                 // draw context menu at center point of visible selection range in the editor box
274                 IntRect editorRect = editorState.editorRect;
275                 leftRect.intersect(editorRect);
276                 if (!leftRect.isEmpty())
277                     point = leftRect.center();
278                 else {
279                     // not draw context menu if there is no visible selection range in the editor box
280                     isPresentInViewPort = false;
281                 }
282             }
283         }
284 #else
285         point = leftRect.center();
286 #endif
287     } else if (editorState.isContentEditable) {
288         WebCore::IntRect caretRect;
289         m_viewImpl->page()->getCaretPosition(caretRect);
290
291         if (caretRect.isEmpty())
292             return;
293
294         point = caretRect.center();
295 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
296         isPresentInViewPort = true;
297 #endif
298     }
299 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
300     if (!isPresentInViewPort)
301         return;
302 #endif
303
304     // show context menu if its in viewport else do not show the contextmenu
305
306     Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(m_viewImpl->view()));
307     if (!smartData || !smartData->api || !smartData->api->mouse_down || !smartData->api->mouse_up)
308         return;
309
310     point = m_viewImpl->transformToScene().mapPoint(point);
311     Evas* evas = evas_object_evas_get(m_viewImpl->view());
312
313     // send mouse down.
314     Evas_Event_Mouse_Down mouseDown;
315     mouseDown.button = 3;
316     mouseDown.output.x = mouseDown.canvas.x = point.x();
317     mouseDown.output.y = mouseDown.canvas.y = point.y();
318     mouseDown.data = 0;
319     mouseDown.modifiers = const_cast<Evas_Modifier*>(evas_key_modifier_get(evas));
320     mouseDown.locks = const_cast<Evas_Lock*>(evas_key_lock_get(evas));
321     mouseDown.flags = EVAS_BUTTON_NONE;
322     mouseDown.timestamp = ecore_time_get() * 1000;
323     mouseDown.event_flags = EVAS_EVENT_FLAG_NONE;
324     mouseDown.dev = 0;
325     smartData->api->mouse_down(smartData, &mouseDown);
326
327     // send mouse up.
328     Evas_Event_Mouse_Up mouseUp;
329     mouseUp.button = 3;
330     mouseUp.output.x = mouseUp.canvas.x = point.x();
331     mouseUp.output.y = mouseUp.canvas.y = point.y();
332     mouseUp.data = 0;
333     mouseUp.modifiers = const_cast<Evas_Modifier*>(evas_key_modifier_get(evas));
334     mouseUp.locks = const_cast<Evas_Lock*>(evas_key_lock_get(evas));
335     mouseUp.flags = EVAS_BUTTON_NONE;
336     mouseUp.timestamp = ecore_time_get() * 1000;
337     mouseUp.event_flags = EVAS_EVENT_FLAG_NONE;
338     mouseUp.dev = 0;
339     smartData->api->mouse_up(smartData, &mouseUp);
340 }
341
342 void TextSelection::hideContextMenu()
343 {
344     if (!isEnabled())
345         return;
346
347     m_viewImpl->page()->hideContextMenu();
348 }
349
350 void TextSelection::setLeftSelectionToEvasPoint(const IntPoint& evasPoint)
351 {
352     m_viewImpl->page()->setLeftSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
353     updateHandlers();
354 }
355
356 void TextSelection::setRightSelectionToEvasPoint(const IntPoint& evasPoint)
357 {
358     m_viewImpl->page()->setRightSelection(m_viewImpl->transformFromScene().mapPoint(evasPoint));
359     updateHandlers();
360 }
361
362 // handle callbacks
363 void TextSelection::handleMouseDown(TextSelectionHandle* handle, const IntPoint& /*position*/)
364 {
365     WebCore::IntPoint basePosition;
366     EditorState editorState = m_viewImpl->page()->editorState();
367
368     if (editorState.selectionIsRange) {
369         WebCore::IntRect leftRect, rightRect;
370         if (!m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
371             clear();
372             return;
373         }
374
375         if (handle->isLeft()) {
376             basePosition.setX(leftRect.x());
377             basePosition.setY(leftRect.y() + (leftRect.height()/2));
378         } else {
379             basePosition.setX(rightRect.x() + rightRect.width());
380             basePosition.setY(rightRect.y() + (rightRect.height()/2));
381         }
382
383         handle->setBasePositionForMove(m_viewImpl->transformToScene().mapPoint(basePosition));
384     } else
385         return;
386
387     hideContextMenu();
388     updateMagnifier(handle->position());
389     showMagnifier();
390 }
391
392 void TextSelection::handleMouseMove(TextSelectionHandle* handle, const IntPoint& position)
393 {
394     if (handle->isLeft())
395         setLeftSelectionToEvasPoint(position);
396     else
397         setRightSelectionToEvasPoint(position);
398
399     updateMagnifier(handle->position());
400 }
401
402 void TextSelection::handleMouseUp(TextSelectionHandle* /* handle */, const IntPoint& /* position */)
403 {
404     hideMagnifier();
405     showContextMenu();
406 }
407
408 bool TextSelection::isMagnifierVisible()
409 {
410     return m_magnifier->isVisible();
411 }
412
413 void TextSelection::updateHandlesAndContextMenu(bool isShow, bool isScrolling)
414 {
415     if (isTextSelectionDowned() && !isScrolling) {
416         showMagnifier();
417         return;
418     }
419
420     EditorState editorState = m_viewImpl->page()->editorState();
421     if (!editorState.selectionIsRange && editorState.isContentEditable)
422         setIsTextSelectionMode(false);
423
424     if (isShow) {
425 #if ENABLE(TIZEN_WEBKIT2_CONTEXT_MENU_CLIPBOARD)
426         if (m_viewImpl->pageClient->isClipboardWindowOpened())
427             return;
428 #endif
429         if (m_viewImpl->gestureClient->isGestureWorking())
430             return;
431
432         updateHandlers();
433         showContextMenu();
434     } else {
435         hideHandlers();
436         hideContextMenu();
437     }
438
439     if (isScrolling && isMagnifierVisible())
440         hideMagnifier();
441 }
442
443 void TextSelection::startMoveAnimator()
444 {
445     if (!isEnabled() || !isTextSelectionDowned())
446         return;
447
448     if (!m_moveAnimator)
449         m_moveAnimator = ecore_animator_add(moveAnimatorCallback, this);
450 }
451
452 void TextSelection::stopMoveAnimator()
453 {
454     if (m_moveAnimator) {
455         ecore_animator_del(m_moveAnimator);
456         m_moveAnimator = 0;
457     }
458 }
459
460 void TextSelection::onMouseUp(void* data, Evas*, Evas_Object*, void* eventInfo)
461 {
462     static_cast<TextSelection*>(data)->textSelectionUp(IntPoint());
463 }
464
465 Eina_Bool TextSelection::moveAnimatorCallback(void* data)
466 {
467     TextSelection* textSelection = static_cast<TextSelection*>(data);
468
469     Evas_Coord_Point point;
470     evas_pointer_canvas_xy_get(evas_object_evas_get(textSelection->m_viewImpl->view()), &point.x, &point.y);
471     textSelection->textSelectionMove(IntPoint(point.x, point.y));
472
473     return ECORE_CALLBACK_RENEW;
474 }
475
476 // 'return false' means text selection is not possible for point.
477 // 'return true' means text selection is possible.
478 bool TextSelection::textSelectionDown(const IntPoint& point, bool isStartedTextSelectionFromOutside)
479 {
480     // text selection should be ignored when longtap on handle from osp
481     if (!isEnabled() && isTextSelectionHandleDowned())
482         return false;
483
484 #if ENABLE(TIZEN_ISF_PORT)
485     m_viewImpl->inputMethodContext()->resetIMFContext();
486 #endif
487     setIsTextSelectionMode(false);
488
489     IntPoint contentsPoint = m_viewImpl->transformFromScene().mapPoint(point);
490     bool result = m_viewImpl->page()->selectClosestWord(contentsPoint, isStartedTextSelectionFromOutside);
491     if (!result)
492         return false;
493
494     if (isTextSelectionMode()) {
495         hide();
496     } else {
497         setIsTextSelectionMode(true);
498     }
499     setIsTextSelectionDowned(true);
500
501     updateMagnifier(point);
502     showMagnifier();
503
504     startMoveAnimator();
505
506     return true;
507 }
508
509 static int s_textSelectionMargin = 5;
510
511 void TextSelection::textSelectionMove(const IntPoint& point, bool isStartedTextSelectionFromOutside)
512 {
513     // text selection should be ignored when longtap on handle from osp
514     if (!isEnabled() && isTextSelectionHandleDowned())
515         return;
516
517     if (!isTextSelectionMode()) {
518         stopMoveAnimator();
519         return;
520     }
521
522     WebCore::IntPoint viewPoint;
523     EditorState editorState = m_viewImpl->page()->editorState();
524     if (editorState.isContentEditable) {
525         IntRect mapRect = m_viewImpl->transformToScene().mapRect(editorState.editorRect);
526         IntPoint updatedPoint = point;
527         bool scrolledY = false;
528         if (point.y() < mapRect.y()) {
529             updatedPoint.setY(mapRect.y() + s_textSelectionMargin);
530             if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionBackward)) {
531                 scrolledY = true;
532                 updateMagnifier(updatedPoint);
533             }
534         } else if (point.y() > mapRect.maxY()) {
535             updatedPoint.setY(mapRect.maxY() - s_textSelectionMargin);
536             if (m_viewImpl->page()->scrollContentByLine(point,WebCore::DirectionForward)) {
537                 scrolledY = true;
538                 updateMagnifier(updatedPoint);
539             }
540         }
541
542         bool scrolledX = false;
543         if (point.x() < mapRect.x()) {
544             updatedPoint.setX(mapRect.x() + s_textSelectionMargin);
545             if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionBackward)) {
546                 scrolledX = true;
547                 updateMagnifier(updatedPoint);
548             }
549         } else if (point.x() > mapRect.maxX()) {
550             updatedPoint.setX(mapRect.maxX() - s_textSelectionMargin);
551             if (m_viewImpl->page()->scrollContentByCharacter(point,WebCore::DirectionForward)) {
552                 scrolledX = true;
553                 updateMagnifier(updatedPoint);
554             }
555         }
556
557         if (!scrolledX && !scrolledY) {
558             viewPoint = m_viewImpl->transformFromScene().mapPoint(updatedPoint);
559             m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
560             updateMagnifier(updatedPoint);
561         }
562     } else {
563         viewPoint = m_viewImpl->transformFromScene().mapPoint(point);
564         m_viewImpl->page()->selectClosestWord(viewPoint, isStartedTextSelectionFromOutside);
565         updateMagnifier(point);
566     }
567     showMagnifier();
568 }
569
570 void TextSelection::textSelectionUp(const IntPoint& point, bool isStartedTextSelectionFromOutside)
571 {
572     // text selection should be ignored when longtap on handle from osp
573     if (!isEnabled() && isTextSelectionHandleDowned())
574         return;
575
576     stopMoveAnimator();
577
578     if (!isTextSelectionMode() || !isTextSelectionDowned())
579         return;
580
581     setIsTextSelectionDowned(false);
582     hideMagnifier();
583
584     EditorState editorState = m_viewImpl->page()->editorState();
585     if (editorState.selectionIsRange || editorState.isContentEditable) {
586         if (editorState.selectionIsRange)
587             updateHandlers();
588
589         showContextMenu();
590     } else if (!isStartedTextSelectionFromOutside)
591         setIsTextSelectionMode(false);
592 }
593
594 #if ENABLE(TIZEN_WEBKIT2_FOR_MOVING_TEXT_SELECTION_HANDLE_FROM_OSP)
595 TextSelectionHandle* TextSelection::getSelectedHandle(const IntPoint& position)
596 {
597     WebCore::IntRect leftHandleRect = m_leftHandle->getHandleRect();
598     if (!leftHandleRect.isEmpty() && leftHandleRect.contains(position))
599         return m_leftHandle;
600
601     WebCore::IntRect rightHandleRect = m_rightHandle->getHandleRect();
602     if (!rightHandleRect.isEmpty() && rightHandleRect.contains(position))
603         return m_rightHandle;
604
605     return 0;
606 }
607
608 void TextSelection::textSelectionHandleDown(const IntPoint& position)
609 {
610     m_selectedHandle = getSelectedHandle(position);
611     if (m_selectedHandle)
612         m_selectedHandle->mouseDown(position);
613     else
614         initHandlesMouseDownedStatus();
615 }
616
617 void TextSelection::textSelectionHandleMove(const IntPoint& position)
618 {
619     if (m_selectedHandle && isTextSelectionHandleDowned())
620         m_selectedHandle->mouseMove(position);
621 }
622
623 void TextSelection::textSelectionHandleUp()
624 {
625     if (m_selectedHandle && isTextSelectionHandleDowned()) {
626         m_selectedHandle->mouseUp();
627         m_selectedHandle = 0;
628     }
629 }
630 #endif
631
632 bool TextSelection::isEnabled()
633 {
634     return ewk_settings_text_selection_enabled_get(ewk_view_settings_get(m_viewImpl->view()));
635 }
636
637 bool TextSelection::isAutomaticClearEnabled()
638 {
639     return ewk_settings_clear_text_selection_automatically_get(ewk_view_settings_get(m_viewImpl->view()));
640 }
641
642 void TextSelection::requestToShow()
643 {
644     if (m_showTimer)
645         ecore_timer_del(m_showTimer);
646     m_showTimer = ecore_timer_loop_add((double)200.0/1000.0, showTimerCallback, this);
647 }
648
649 Eina_Bool TextSelection::showTimerCallback(void* data)
650 {
651     TextSelection* textSelection = static_cast<TextSelection*>(data);
652     textSelection->showHandlesAndContextMenu();
653
654     return ECORE_CALLBACK_RENEW;
655 }
656
657 void TextSelection::showHandlesAndContextMenu()
658 {
659     WebCore::IntRect leftRect, rightRect;
660     if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
661         if ((leftRect == m_lastLeftHandleRect) && (rightRect == m_lastRightHandleRect)) {
662             if (m_showTimer) {
663                 ecore_timer_del(m_showTimer);
664                 m_showTimer = 0;
665             }
666
667             updateHandlesAndContextMenu(true);
668         }
669
670         m_lastLeftHandleRect = leftRect;
671         m_lastRightHandleRect = rightRect;
672     }
673 }
674
675 void TextSelection::initHandlesMouseDownedStatus()
676 {
677     m_leftHandle->setIsMouseDowned(false);
678     m_rightHandle->setIsMouseDowned(false);
679 }
680
681 void TextSelection::changeContextMenuPosition(WebCore::IntPoint& position)
682 {
683     if (m_leftHandle->isTop()) {
684         IntRect handleRect = m_leftHandle->getHandleRect();
685         position.setY(position.y() - handleRect.height());
686     }
687 }
688
689 #if ENABLE(TIZEN_WEBKIT2_GET_TEXT_STYLE_FOR_SELECTION)
690 void TextSelection::informTextStyleState()
691 {
692     WebCore::IntPoint startPoint, endPoint;
693     WebCore::IntRect leftRect, rightRect;
694
695     WebCore::IntRect caretRect;
696     m_viewImpl->page()->getCaretPosition(caretRect);
697     if (!caretRect.isEmpty()) {
698         startPoint.setX(caretRect.x());
699         startPoint.setY(caretRect.y() + caretRect.height());
700
701         endPoint.setX(caretRect.x() + caretRect.width());
702         endPoint.setY(caretRect.y() + caretRect.height());
703     }
704     else if (m_viewImpl->page()->getSelectionHandlers(leftRect, rightRect)) {
705         startPoint.setX(leftRect.x());
706         startPoint.setY(leftRect.y() + leftRect.height());
707
708         endPoint.setX(rightRect.x() + rightRect.width());
709         endPoint.setY(rightRect.y() + rightRect.height());
710     }
711
712     AffineTransform toEvasTransform = m_viewImpl->transformToScene();
713     WebCore::IntPoint startEvasPoint = toEvasTransform.mapPoint(startPoint);
714     WebCore::IntPoint endEvasPoint = toEvasTransform.mapPoint(endPoint);
715
716     ewkViewTextStyleState(m_viewImpl->view(), startEvasPoint, endEvasPoint);
717 }
718 #endif
719 } // namespace WebKit
720
721 #endif // TIZEN_WEBKIT2_TEXT_SELECTION