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