1 // Copyright 2013 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "selection_controller_efl.h"
9 #include "content/browser/renderer_host/render_widget_host_view_efl.h"
10 #include "content/public/browser/web_contents.h"
11 #include "eweb_view.h"
12 #include "public/ewk_hit_test.h"
13 #include "ui/gfx/screen.h"
15 using namespace tizen_webview;
19 static const int menuHeight = 140;// The Height fo the context menu.
20 static const int menuPadding = 60;// This is padding for deciding when to modify context menu position.
21 static const int spacePadding = 0; // 24;// This is for making context menu closer to the handles.
22 static const int textSelectionScrollSize = 50;// Scroll step when selection handler is moving out of viewport.
24 static bool IsRectEmpty(const gfx::Rect& rect) {
25 return (rect.x() == 0 && rect.y() == 0 && rect.height() == 0 && rect.width() == 0);
28 SelectionControllerEfl::SelectionControllerEfl(EWebView* parent_view, WebContents& web_contents)
29 : parent_view_(parent_view),
32 show_after_scroll_(false),
34 expecting_update_(false),
35 long_mouse_press_(false),
36 caret_selection_(true),
37 selection_data_(new SelectionBoxEfl(parent_view)),
38 start_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_LEFT, parent_view->evas_object())),
39 end_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_RIGHT, parent_view->evas_object())),
40 input_handle_(new SelectionHandleEfl(*this, SelectionHandleEfl::HANDLE_TYPE_INPUT, parent_view->evas_object())),
42 magnifier_(new SelectionMagnifierEfl(this)),
43 is_selection_visible_(false),
44 show_only_large_handler_(false),
45 web_contents_(web_contents) {
46 evas_object_event_callback_add(parent_view_->evas_object(), EVAS_CALLBACK_MOVE, &EvasParentViewMoveCallback, this);
49 vconf_notify_key_changed(VCONFKEY_LANGSET, PlatformLanguageChanged, this);
53 void SelectionControllerEfl::SetSelectionStatus(bool enable) {
54 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__, "enable", enable);
55 selection_data_->SetStatus(enable);
58 bool SelectionControllerEfl::GetSelectionStatus() const {
59 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__,
60 "status", selection_data_->GetStatus());
61 return selection_data_->GetStatus();
65 void SelectionControllerEfl::PlatformLanguageChanged(keynode_t* keynode, void* data) {
66 SelectionControllerEfl* selection_controller = static_cast<SelectionControllerEfl*>(data);
67 if (!selection_controller)
70 if (selection_controller->GetSelectionStatus())
71 selection_controller->ClearSelectionViaEWebView();
72 selection_controller->HideHandleAndContextMenu();
76 void SelectionControllerEfl::SetSelectionEditable(bool enable) {
77 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__, "enable", enable);
78 selection_data_->SetEditable(enable);
81 bool SelectionControllerEfl::GetSelectionEditable() const {
82 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__,
83 "editable", selection_data_->GetEditable());
84 return selection_data_->GetEditable();
87 void SelectionControllerEfl::SetCaretSelectionStatus(const bool enable) {
88 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__, "caret selection", enable);
89 selection_data_->SetCaretSelectionStatus(enable);
92 bool SelectionControllerEfl::GetCaretSelectionStatus() const {
93 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__,
94 "caret selection", selection_data_->GetCaretSelectionStatus());
95 return selection_data_->GetCaretSelectionStatus();
98 void SelectionControllerEfl::SetScrollStatus(const bool enable) {
99 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__, "scroll status", enable);
102 Clear(IsAnyHandleVisible() || postponed_);
103 parent_view_->CancelContextMenu(0);
104 } else if (show_after_scroll_ || postponed_) {
105 ShowHandleAndContextMenuIfRequired();
109 bool SelectionControllerEfl::GetScrollStatus() {
110 TRACE_EVENT1("selection,efl", __PRETTY_FUNCTION__, "scroll status", scrolling_);
114 void SelectionControllerEfl::UpdateSelectionData(const base::string16& text) {
115 selection_data_->UpdateSelectStringData(text);
118 bool SelectionControllerEfl::ClearSelectionViaEWebView() {
119 if (GetSelectionStatus()) {
120 parent_view_->ExecuteEditCommand("Unselect", NULL);
127 bool SelectionControllerEfl::UpdateSelectionDataAndShow(
128 const gfx::Rect& left_rect,
129 const gfx::Rect& right_rect,
132 TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
134 if (!show && !IsSelectionValid(left_rect, right_rect)) {
135 if (!GetCaretSelectionStatus())
137 selection_data_->UpdateRectData(left_rect, right_rect);
141 RenderWidgetHostViewEfl* rwhv = static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
142 if (show_only_large_handler_ && GetCaretSelectionStatus() &&
143 (rwhv && !rwhv->IsLastAvailableTextEmpty())) {
144 selection_data_->UpdateRectData(left_rect, right_rect);
145 ShowHandleAndContextMenuIfRequired();
149 if ((selection_data_->UpdateRectData(left_rect, right_rect) &&
150 IsAnyHandleVisible()) || show || postponed_) {
151 show_only_large_handler_ = false;
152 if (selection_data_->GetEditable()) {
153 // In case we're selecting text in editable text field we've already sent
154 // swapped coordinates from OnMouseMove. No need to do it for the second
156 ShowHandleAndContextMenuIfRequired();
158 ShowHandleAndContextMenuIfRequired(left_rect < right_rect);
162 expecting_update_ = false;
170 HitTestContext(SelectionControllerEfl* ctrl, bool anchor)
172 , anchor_first(anchor) {
175 SelectionControllerEfl* GetOwner() const { return owner; }
176 bool GetAnchorFirst() const { return anchor_first; }
179 SelectionControllerEfl* owner;
184 void SelectionControllerEfl::ShowHandleAndContextMenuIfRequiredCallback(
185 Evas_Object* o, int x, int y, int mode, _Ewk_Hit_Test* hit_test,
187 HitTestContext* context = static_cast<HitTestContext*>(data);
189 DCHECK(context->GetOwner());
190 context->GetOwner()->ShowHandleAndContextMenuIfRequired(
191 o, x, y, mode, hit_test, context->GetAnchorFirst());
195 void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
196 Evas_Object* o, int x, int y, int /* mode*/,
197 _Ewk_Hit_Test* hit_test, bool anchor_first) {
201 if(!postponed_ && !show_after_scroll_)
204 gfx::Rect left, right;
206 left = selection_data_->GetLeftRect();
207 right = selection_data_->GetRightRect();
209 right = selection_data_->GetLeftRect();
210 left = selection_data_->GetRightRect();
214 // Is in edit field and no text is selected. show only single handle
215 if (selection_data_->IsInEditField() && left == right) {
218 !(hit_test->GetResultContext() & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE)) {
223 gfx::Rect left = selection_data_->GetLeftRect();
224 if(selection_data_->GetCaretSelectionStatus()) {
225 input_handle_->SetBasePosition(gfx::Point(left.x(), left.y()));
226 input_handle_->Move(left.bottom_right());
227 input_handle_->Show();
229 start_handle_->Hide();
231 parent_view_->QuerySelectionStyle();
233 if (!mouse_press_ && !show_only_large_handler_) {
234 parent_view_->ShowContextMenu(*(selection_data_->GetContextMenuParams()),
235 MENU_TYPE_SELECTION, false);
240 input_handle_->Hide();
243 if (left.x() == 0 && left.y() == 0 && right.x() == 0 && right.y() == 0) {
244 selection_data_->ClearRectData();
248 // The base position of start_handle should be set to the middle of the left
249 // rectangle. Otherwise the start_handle may be shifted up when the
250 // right_handle is moving
251 start_handle_->SetBasePosition(left.CenterPoint());
252 start_handle_->Move(left.bottom_left());
253 if (left.x() >= visibility_rect_.x() &&
254 left.x() <= visibility_rect_.right()) {
255 start_handle_->Show();
257 start_handle_->Hide();
261 // The base position of end_handle should be set to the middle of the right
262 // rectangle. Otherwise the end_handle may be shifted up when the left_handle
264 end_handle_->SetBasePosition(right.CenterPoint());
265 end_handle_->Move(right.bottom_right());
266 if (right.x() >= visibility_rect_.x() &&
267 right.x() <= visibility_rect_.right()) {
274 // Do not show the context menu during selection extend
276 parent_view_->ShowContextMenu(
277 *(selection_data_->GetContextMenuParams()),
282 parent_view_->QuerySelectionStyle();
285 void SelectionControllerEfl::ShowHandleAndContextMenuIfRequired(
287 TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
289 if (!selection_data_->GetStatus()) {
297 HitTestContext* ctx = new HitTestContext(this, anchor_first);
300 hitX = selection_data_->GetContextMenuParams()->x;
301 hitY = selection_data_->GetContextMenuParams()->y;
304 parent_view_->AsyncRequestHitTestDataAt(
307 EWK_HIT_TEST_MODE_DEFAULT,
308 ShowHandleAndContextMenuIfRequiredCallback,
312 void SelectionControllerEfl::HideHandles() {
313 SetCaretSelectionStatus(false);
317 void SelectionControllerEfl::HideHandleAndContextMenu() {
318 parent_view_->CancelContextMenu(0);
322 bool SelectionControllerEfl::IsAnyHandleVisible() const {
323 return (start_handle_->IsVisible() ||
324 end_handle_->IsVisible() ||
325 input_handle_->IsVisible());
328 void SelectionControllerEfl::Clear(bool show_after_scroll) {
329 show_after_scroll_ = show_after_scroll;
331 start_handle_->Hide();
333 input_handle_->Hide();
336 bool SelectionControllerEfl::IsShowingMagnifier() {
337 if(magnifier_->IsShowing())
342 void SelectionControllerEfl::OnMouseDown(const gfx::Point& touch_point,
343 SelectionHandleEfl::HandleType handle) {
344 // Hide context menu on mouse down
345 show_only_large_handler_ = false;
346 parent_view_->CancelContextMenu(0);
350 evas_object_geometry_get(parent_view_->evas_object(), &x, &y, 0, 0);
351 gfx::Point magnifier_point;
354 case SelectionHandleEfl::HANDLE_TYPE_INPUT:
355 magnifier_point.set_x(input_handle_->GetBasePosition().x() + x);
356 magnifier_point.set_y(input_handle_->GetBasePosition().y() + y);
359 case SelectionHandleEfl::HANDLE_TYPE_LEFT:
360 magnifier_point.set_x(start_handle_->GetBasePosition().x() + x);
361 magnifier_point.set_y(start_handle_->GetBasePosition().y() + y);
364 case SelectionHandleEfl::HANDLE_TYPE_RIGHT:
365 magnifier_point.set_x(end_handle_->GetBasePosition().x() + x);
366 magnifier_point.set_y(end_handle_->GetBasePosition().y() + y);
370 magnifier_->UpdateLocation(magnifier_point);
371 magnifier_->Move(magnifier_point);
374 ShowHandleAndContextMenuIfRequired();
377 void SelectionControllerEfl::OnMouseMove(const gfx::Point& touch_point,
378 SelectionHandleEfl::HandleType handle) {
379 show_only_large_handler_ = false;
380 // FIXME : Check the text Direction later
382 evas_object_geometry_get(parent_view_->evas_object(), &x, &y, 0, 0);
383 expecting_update_ = true;
384 gfx::Point magnifier_point;
385 gfx::Point start_point, end_point;
386 WebContentsImpl* wci = static_cast<WebContentsImpl*>(&web_contents_);
387 float device_scale_factor =
388 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().device_scale_factor();
391 case SelectionHandleEfl::HANDLE_TYPE_INPUT:
392 magnifier_point.set_x(input_handle_->GetBasePosition().x() + x);
393 magnifier_point.set_y(input_handle_->GetBasePosition().y() + y);
394 magnifier_->UpdateLocation(magnifier_point);
395 magnifier_->Move(magnifier_point);
396 parent_view_->MoveCaret(input_handle_->GetBasePosition());
398 case SelectionHandleEfl::HANDLE_TYPE_LEFT:
399 magnifier_point.set_x(start_handle_->GetBasePosition().x() + x);
400 magnifier_point.set_y(start_handle_->GetBasePosition().y() + y);
401 magnifier_->UpdateLocation(magnifier_point);
402 magnifier_->Move(magnifier_point);
404 start_point.set_x(start_handle_->GetBasePosition().x() / device_scale_factor);
405 start_point.set_y(start_handle_->GetBasePosition().y() / device_scale_factor);
406 end_point.set_x(end_handle_->GetBasePosition().x() / device_scale_factor);
407 end_point.set_y(end_handle_->GetBasePosition().y() / device_scale_factor);
408 if (GetSelectionEditable()) {
409 // Form elements only support scrolling of extent/end caret. To
410 // move the start element we need to swap the coordinates provided
411 // to SelectRange function.
412 wci->SelectRange(end_point, start_point);
415 wci->SelectRange(start_point, end_point);
418 case SelectionHandleEfl::HANDLE_TYPE_RIGHT:
419 magnifier_point.set_x(end_handle_->GetBasePosition().x() + x);
420 magnifier_point.set_y(end_handle_->GetBasePosition().y() + y);
421 magnifier_->UpdateLocation(magnifier_point);
422 magnifier_->Move(magnifier_point);
424 start_point.set_x(start_handle_->GetBasePosition().x() / device_scale_factor);
425 start_point.set_y(start_handle_->GetBasePosition().y() / device_scale_factor);
426 end_point.set_x(end_handle_->GetBasePosition().x() / device_scale_factor);
427 end_point.set_y(end_handle_->GetBasePosition().y() / device_scale_factor);
428 wci->SelectRange(start_point, end_point);
433 void SelectionControllerEfl::OnMouseUp(const gfx::Point& touch_point) {
434 show_only_large_handler_ = false;
435 mouse_press_ = false;
437 start_handle_->SetBasePosition(selection_data_->GetLeftRect().bottom_left());
438 end_handle_->SetBasePosition(selection_data_->GetRightRect().bottom_right());
439 ShowHandleAndContextMenuIfRequired();
442 void SelectionControllerEfl::GetSelectionBounds(gfx::Rect* left,
445 *left = selection_data_->GetLeftRect();
447 *right = selection_data_->GetRightRect();
450 void SelectionControllerEfl::HandleLongPressEvent(
451 const gfx::Point& touch_point, Ewk_Hit_Test_Result_Context context) {
452 if (context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE) {
453 SetSelectionStatus(true);
454 SetSelectionEditable(true);
455 HandleLongPressEventPrivate(touch_point);
456 } else if (!(context & EWK_HIT_TEST_RESULT_CONTEXT_LINK)
457 && !(context & EWK_HIT_TEST_RESULT_CONTEXT_IMAGE)
458 && !(context & EWK_HIT_TEST_RESULT_CONTEXT_MEDIA)
459 && context & EWK_HIT_TEST_RESULT_CONTEXT_TEXT) {
460 SetSelectionStatus(true);
461 HandleLongPressEventPrivate(touch_point);
462 LOG(INFO) << __PRETTY_FUNCTION__ << ":: link, !image, !media, text";
463 } else if (context & EWK_HIT_TEST_RESULT_CONTEXT_DOCUMENT) {
464 LOG(INFO) << __PRETTY_FUNCTION__ << ":: EWK_HIT_TEST_RESULT_CONTEXT_DOCUMENT";
465 } else if (context & EWK_HIT_TEST_RESULT_CONTEXT_IMAGE) {
466 LOG(INFO) << __PRETTY_FUNCTION__ << ":: EWK_HIT_TEST_RESULT_CONTEXT_IMAGE";
467 } else if (context & EWK_HIT_TEST_RESULT_CONTEXT_LINK) {
468 ClearSelectionViaEWebView();
469 LOG(INFO) << __PRETTY_FUNCTION__ << ":: EWK_HIT_TEST_RESULT_CONTEXT_LINK";
471 LOG(INFO) << __PRETTY_FUNCTION__ << ":: hit_test = " << context;
475 void SelectionControllerEfl::HandleLongPressEventPrivate(const gfx::Point& touch_point) {
476 show_only_large_handler_ = false;
477 long_mouse_press_ = true;
479 caret_selection_ = true;
480 if (selection_data_->IsInEditField())
481 SetCaretSelectionStatus(true);
482 if (caret_selection_) {
484 evas_object_geometry_get(parent_view_->evas_object(), &x, &y, 0, 0);
485 magnifier_->HandleLongPress(gfx::Point(touch_point.x() + x,
486 touch_point.y() + y));
488 long_mouse_press_ = false;
492 void SelectionControllerEfl::HandleLongPressMoveEvent(const gfx::Point& touch_point) {
494 if (selection_data_->IsInEditField()) {
496 evas_object_geometry_get(parent_view_->evas_object(), &x, &y, 0, 0);
497 parent_view_->MoveCaret(gfx::Point(touch_point.x() - x, touch_point.y() - y));
498 SetSelectionStatus(true);
500 parent_view_->SelectClosestWord(touch_point);
504 void SelectionControllerEfl::HandleLongPressEndEvent() {
505 long_mouse_press_ = false;
507 show_after_scroll_ = true;
508 if (selection_data_->GetCaretSelectionStatus()) {
509 SetSelectionStatus(true);
510 SetSelectionEditable(true);
512 ShowHandleAndContextMenuIfRequired();
515 void SelectionControllerEfl::HandleTapEvent(
516 const gfx::Point& touch_point, Ewk_Hit_Test_Result_Context context) {
517 if (context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE) {
518 LOG(INFO) << "DispatchPostponedGestureEvent :: EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE";
519 SetSelectionStatus(true);
520 if (GetSelectionEditable()){
521 SetCaretSelectionStatus(true);
522 UpdateSelectionDataAndShow(
523 GetLeftRect(), GetRightRect(), false /* unused */, false);
525 SetSelectionEditable(true);
528 if (context & EWK_HIT_TEST_RESULT_CONTEXT_DOCUMENT)
529 LOG(INFO) << __PRETTY_FUNCTION__ << " DOCUMENT";
530 if (context & EWK_HIT_TEST_RESULT_CONTEXT_TEXT)
531 LOG(INFO) << __PRETTY_FUNCTION__ << " TEXT";
533 SetSelectionEditable(false);
537 bool SelectionControllerEfl::IsSelectionValid(const gfx::Rect& left_rect,
538 const gfx::Rect& right_rect) {
539 TRACE_EVENT2("selection,efl", __PRETTY_FUNCTION__,
540 "left_rect", left_rect.ToString(),
541 "right_rect", right_rect.ToString());
542 // For all normal cases the widht will be 0 and we want to check empty which Implies
543 // x, y, h w all to be 0
544 if ((IsRectEmpty(left_rect) || IsRectEmpty(right_rect))) {
545 SetSelectionStatus(false);
549 // The most of sites return width of each rects as 0 when text is selected.
550 // However, some websites that have viewport attributes on meta tag v
551 // return width 0 right after they are loaded, even though text is not selected.
552 // Thus the width is not sufficient for checking selection condition.
553 // Further invesitigation showed left_rect and right_rect always have the same x,y values
554 // for such cases. So, the equality for x and y rather than width should be tested.
555 if (left_rect.x() == right_rect.x() && left_rect.y() == right_rect.y() &&
556 !selection_data_->IsInEditField() && !mouse_press_ &&
557 !expecting_update_) {
558 SetSelectionStatus(false);
562 if (!GetSelectionStatus())
563 SetSelectionStatus(true);
565 if ((left_rect.x() != right_rect.x() || left_rect.y() != right_rect.y()) &&
566 selection_data_->IsInEditField() && GetCaretSelectionStatus()) {
567 if (!long_mouse_press_)
568 SetCaretSelectionStatus(false);
574 void SelectionControllerEfl::ClearSelection() {
575 TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
577 selection_data_->SetStatus(false);
578 SetSelectionEditable(false);
579 SetCaretSelectionStatus(false);
582 void SelectionControllerEfl::OnParentParentViewMove() {
583 TRACE_EVENT0("selection,efl", __PRETTY_FUNCTION__);
584 start_handle_->Move(start_handle_->GetBasePosition());
585 end_handle_->Move(end_handle_->GetBasePosition());
588 gfx::Rect SelectionControllerEfl::GetLeftRect() {
589 return selection_data_->GetLeftRect();
592 gfx::Rect SelectionControllerEfl::GetRightRect() {
593 return selection_data_->GetRightRect();
596 void SelectionControllerEfl::ChangeContextMenuPosition(gfx::Point& position, int& drawDirection) {
597 drawDirection = DirectionNone; // Giving default Direction.
598 int handleHeight, webViewX, webViewY, webViewWidth, webViewHeight;
600 edje_object_part_geometry_get(input_handle_->evas_object(), "handle", 0, 0, 0, &handleHeight);
601 evas_object_geometry_get(GetParentView()->evas_object(), &webViewX, &webViewY, &webViewWidth, &webViewHeight);
602 gfx::Rect viewportRect = gfx::Rect(webViewX, webViewY, webViewWidth, webViewHeight);
604 RenderWidgetHostViewEfl* rwhv =
605 static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
606 if (rwhv && rwhv->IsIMEShow()) { // Get the Visible Rect .
607 imeRect = rwhv->GetIMERect();
608 if ((viewportRect.y() + viewportRect.height()) > imeRect.y())
609 viewportRect.set_height(imeRect.y() - viewportRect.y());
612 gfx::Rect leftHandleRect = selection_data_->GetLeftRect();
613 leftHandleRect.set_x(webViewX + leftHandleRect.x());
614 leftHandleRect.set_y(webViewY + leftHandleRect.y());
616 if (!GetCaretSelectionStatus()) {
617 gfx::Rect rightHandleRect = selection_data_->GetRightRect();
618 rightHandleRect.set_x(webViewX + rightHandleRect.x());
619 rightHandleRect.set_y(webViewY + rightHandleRect.y());
620 gfx::Rect oldLeftHandleRect = leftHandleRect;
621 gfx::Rect oldRightHandleRect = rightHandleRect;
622 gfx::Rect effectiveRect;
623 bool isEffecrtiveRectAvailable = false;
626 bool isRightHandle = false;
627 bool doConsiderRightHandle = false;
628 bool doNotConsiderMenuUpward = false;
630 //if (leftHandleRect.x() < 0)
631 // leftHandleRect.set_x(0);
632 //if (leftHandleRect.y() < 0)
633 // leftHandleRect.set_y(0);
635 // Giving first preference to left handle.
636 if (leftHandleRect.IsEmpty() && viewportRect.Contains(leftHandleRect.x(), leftHandleRect.y())) {
637 isTop = start_handle_->IsTop();
638 effectiveRect = leftHandleRect;
639 isEffecrtiveRectAvailable = true;
640 // Check whether Menu will overlap the right handle or not.
641 if (leftHandleRect != rightHandleRect) {
643 // If there is sufficient space above the handler that Menu can be placed. then shift context menu
644 // then no need to change effectiveRect from leftHandleRect to rightHandleRect.
645 bool directionUp = effectiveRect.y() - menuHeight > viewportRect.y() && (effectiveRect.y() - (viewportRect.y() + menuHeight) > menuPadding);
646 if (!directionUp && ((leftHandleRect.y() + leftHandleRect.height()) + menuHeight) > rightHandleRect.y()) {
647 doConsiderRightHandle = true;
648 doNotConsiderMenuUpward = true; // As if we draw the direction is UP it will overlap with left Handle.
653 doConsiderRightHandle = true;
656 if (doConsiderRightHandle && rightHandleRect.IsEmpty() && viewportRect.Contains(rightHandleRect.x(), rightHandleRect.y())) {
657 effectiveRect = rightHandleRect;
658 isEffecrtiveRectAvailable = true;
659 isTop = end_handle_->IsTop();
660 isRightHandle = true;
663 if (isEffecrtiveRectAvailable) {
664 //We will go for UpWard, DownWard, Left, Right directions.
665 if (effectiveRect.y() - menuHeight > viewportRect.y() && (effectiveRect.y() - (viewportRect.y() + menuHeight) > menuPadding) && !doNotConsiderMenuUpward) {
668 position.set_y(effectiveRect.y() - spacePadding - handleHeight);
670 position.set_y(effectiveRect.y() - spacePadding - handleHeight);
671 //position.set_y(position.y() - effectiveRect.height());
674 position.set_y(effectiveRect.y() - spacePadding);
676 drawDirection = DirectionUp;
677 } else if ((effectiveRect.y() + effectiveRect.height()) + menuHeight < (viewportRect.y() + viewportRect.height())) {
678 position.set_y((effectiveRect.y() + effectiveRect.height()) - spacePadding + handleHeight);
679 drawDirection = DirectionDown;
680 } else if (effectiveRect.x() < (viewportRect.x() + viewportRect.width()/2)) {
681 position.set_x((effectiveRect.x() + effectiveRect.width()) + spacePadding + handleHeight);
682 position.set_y(effectiveRect.CenterPoint().y());
683 drawDirection = DirectionLeft;
685 position.set_x(effectiveRect.x());
686 position.set_y(effectiveRect.CenterPoint().y());
687 drawDirection = DirectionRight;
690 if (oldLeftHandleRect.y() < viewportRect.y() && oldRightHandleRect.y() > (viewportRect.y() + viewportRect.height()) && viewportRect.height() <= webViewHeight) {
691 position.set_y(viewportRect.CenterPoint().y() - spacePadding);
693 position.set_y(position.y() + spacePadding + handleHeight);// This value is chosen based on the how much close the context menu arrow should come to word.
695 drawDirection = DirectionNone;
701 if (!selection_data_->IsInEditField())
704 position.set_y(leftHandleRect.y() - spacePadding);
706 if (input_handle_->IsTop()) {
707 position.set_y(position.y() - leftHandleRect.height() - handleHeight);
711 // The Width of the context menu is menuHeight so comapairing current position with the viewport point plus menuHeight.
712 // If position is less than this value then set new position for the contextmenu.
713 if ((position.y() <= (webViewY + menuHeight)) || ((position.y() - (webViewY + menuHeight)) <= menuPadding)) {
714 if (leftHandleRect.IsEmpty()) {
715 position.set_y(position.y() + spacePadding + handleHeight);// This value is chosen based on the how much close the context menu arrow should come to word.
716 drawDirection = DirectionDown;
720 position.set_y((leftHandleRect.y() + leftHandleRect.height()) - spacePadding + handleHeight);
721 drawDirection = DirectionDown;
728 bool SelectionControllerEfl::TextSelectionDown(int x, int y) {
730 * According to webkit-efl textSelectionDown is used on long press gesture, we already
731 * have implementation for handling this gesture in SelectionControllerEfl so we just
732 * fallback into it. Although I'm not totally sure that this is expected behaviour as there
733 * is no clear explanation what should this API do.
735 * Reference from webkit-efl:
736 * Source/WebKit2/UIProcess/API/efl/ewk_view.cpp line 614
738 if (!long_mouse_press_) {
739 HandleLongPressEventPrivate(gfx::Point(x, y));
746 bool SelectionControllerEfl::TextSelectionUp(int /*x*/, int /*y*/) {
748 * According to webkit-efl textSelectionUp is used when MouseUp event occurs. We already
749 * have implementation for handling MouseUp after long press in SelectionMagnifierEfl so we just
750 * fallback into it. Although I'm not totally sure that this is expected behaviour as there
751 * is no clear explanation what should this API do.
753 * Reference from webkit-efl:
754 * Source/WebKit2/UIProcess/API/efl/tizen/TextSelection.cpp line 807
757 if (long_mouse_press_) {
758 magnifier_->OnAnimatorUp();