[M108 Migration][Text Selection] Selection handles & Caret Selection
[platform/framework/web/chromium-efl.git] / tizen_src / chromium_impl / content / browser / selection / selection_magnifier_efl.cc
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.
4
5 #include "selection_magnifier_efl.h"
6
7 #include <Elementary.h>
8
9 #include "base/files/file_path.h"
10 #include "base/path_service.h"
11 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
12 #include "content/browser/selection/selection_controller_efl.h"
13 #include "content/common/paths_efl.h"
14 #include "content/public/browser/browser_thread.h"
15
16 namespace content {
17
18 // Inherited from WK2 w.r.t tizen style
19 const int kHeightOffset = 60;
20 const float kZoomScale = 0.66;
21
22 SelectionMagnifierEfl::SelectionMagnifierEfl(
23     content::SelectionControllerEfl* controller)
24     : controller_(controller), content_image_(0), shown_(false) {
25   base::FilePath edj_dir;
26   base::FilePath magnifier_edj;
27   base::PathService::Get(PathsEfl::EDJE_RESOURCE_DIR, &edj_dir);
28   magnifier_edj = edj_dir.Append(FILE_PATH_LITERAL("Magnifier.edj"));
29
30   container_ =
31       elm_layout_add(controller_->rwhva()->offscreen_helper()->content_image());
32   elm_layout_file_set(container_, magnifier_edj.AsUTF8Unsafe().c_str(), "magnifier");
33   edje_object_part_geometry_get(elm_layout_edje_get(container_), "bg", 0, 0, &width_, &height_);
34 }
35
36 SelectionMagnifierEfl::~SelectionMagnifierEfl() {
37   DisconnectCallbacks();
38   if (content_image_) {
39     evas_object_del(content_image_);
40     content_image_ = 0;
41   }
42   if (container_)
43     evas_object_del(container_);
44 }
45
46 void SelectionMagnifierEfl::HandleLongPress(const gfx::Point& touch_point) {
47   evas_object_event_callback_add(
48       controller_->rwhva()->offscreen_helper()->content_image(),
49       EVAS_CALLBACK_MOUSE_MOVE, OnAnimatorMove, this);
50   evas_object_event_callback_add(
51       controller_->rwhva()->offscreen_helper()->content_image(),
52       EVAS_CALLBACK_MOUSE_UP, OnAnimatorUp, this);
53   // Call OnAnimatorMove here, so that the magnifier widget
54   // gets properly placed. Other calls to it are expected to
55   // happen as a react to finger/mouse movements.
56   OnAnimatorMove();
57   Show();
58 }
59
60 void SelectionMagnifierEfl::DisconnectCallbacks() {
61   evas_object_event_callback_del(
62       controller_->rwhva()->offscreen_helper()->content_image(),
63       EVAS_CALLBACK_MOUSE_MOVE, OnAnimatorMove);
64   evas_object_event_callback_del(
65       controller_->rwhva()->offscreen_helper()->content_image(),
66       EVAS_CALLBACK_MOUSE_UP, OnAnimatorUp);
67 }
68
69 void SelectionMagnifierEfl::OnAnimatorMove(void* data, Evas*, Evas_Object*, void*) {
70   SelectionMagnifierEfl* magnifier_data = static_cast<SelectionMagnifierEfl*>(data);
71   DCHECK(magnifier_data);
72
73   if (magnifier_data)
74     magnifier_data->OnAnimatorMove();
75 }
76
77 void SelectionMagnifierEfl::OnAnimatorMove() {
78   Evas_Coord_Point point;
79   evas_pointer_canvas_xy_get(
80       evas_object_evas_get(
81           controller_->rwhva()->offscreen_helper()->content_image()),
82       &point.x, &point.y);
83   gfx::Point display_point(point.x, point.y);
84   controller_->HandleLongPressMoveEvent(display_point);
85   UpdateLocation(display_point);
86   Move(display_point);
87 }
88
89 void SelectionMagnifierEfl::OnAnimatorUp(void* data, Evas*, Evas_Object*, void*) {
90   SelectionMagnifierEfl* magnifier_data = static_cast<SelectionMagnifierEfl*>(data);
91   DCHECK(magnifier_data);
92
93   if (magnifier_data)
94     magnifier_data->OnAnimatorUp();
95 }
96
97 void SelectionMagnifierEfl::OnAnimatorUp() {
98   DisconnectCallbacks();
99   Hide();
100   controller_->HandleLongPressEndEvent();
101 }
102
103 void SelectionMagnifierEfl::MagnifierGetSnapshotCb(Evas_Object* image,
104                                                    void* user_data)
105 {
106   SelectionMagnifierEfl* selection_magnifier =
107       static_cast<SelectionMagnifierEfl*>(user_data);
108
109   if (selection_magnifier->content_image_) {
110     evas_object_del(selection_magnifier->content_image_);
111     selection_magnifier->content_image_ = 0;
112   }
113
114   selection_magnifier->content_image_ = image;
115   evas_object_show(selection_magnifier->content_image_);
116
117   elm_object_part_content_set(selection_magnifier->container_,
118       "swallow", selection_magnifier->content_image_);
119   evas_object_pass_events_set(selection_magnifier->content_image_, EINA_TRUE);
120   evas_object_clip_set(selection_magnifier->content_image_,
121       selection_magnifier->container_);
122
123   evas_object_layer_set(selection_magnifier->container_, EVAS_LAYER_MAX);
124   evas_object_layer_set(selection_magnifier->content_image_, EVAS_LAYER_MAX);
125 }
126
127 void SelectionMagnifierEfl::UpdateLocation(const gfx::Point& location) {
128   int device_x, device_y, device_width, device_height;
129   evas_object_geometry_get(
130       controller_->rwhva()->offscreen_helper()->content_image(), &device_x,
131       &device_y, &device_width, &device_height);
132
133   int zoomedWidth = width_ * kZoomScale;
134   int zoomedHeight = height_ * kZoomScale;
135
136   if (zoomedWidth > device_width)
137     zoomedWidth = device_width;
138
139   if (zoomedHeight > device_height)
140     zoomedHeight = device_height;
141
142   gfx::Rect content_rect(location.x() - zoomedWidth/2,
143       location.y() - zoomedHeight/2,  zoomedWidth, zoomedHeight);
144
145   // Adjustments for boundry conditions
146   if (content_rect.x() < device_x)
147     content_rect.set_x(device_x);
148   else if ((content_rect.x() + zoomedWidth) > device_x + device_width)
149     content_rect.set_x(device_x + device_width - zoomedWidth);
150
151   if (content_rect.y() < device_y) // Do not let location to be less then magnifier y value
152     content_rect.set_y(device_y);
153   else if (content_rect.y() > device_y + device_height - zoomedHeight)
154     content_rect.set_y(device_y + device_height - zoomedHeight);
155
156   Eina_Rectangle rect;
157   rect.x = content_rect.x();
158   rect.y = content_rect.y();
159   rect.w = content_rect.width();
160   rect.h = content_rect.height();
161 #if !defined(USE_AURA)
162   RenderWidgetHostViewEfl* rwhv =
163       static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
164   if (rwhv)
165     rwhv->RequestSnapshotAsync(rect, MagnifierGetSnapshotCb, this);
166 #endif
167 }
168
169 void SelectionMagnifierEfl::Move(const gfx::Point& location) {
170   int device_x, device_y, device_width, device_height;
171   evas_object_geometry_get(
172       controller_->rwhva()->offscreen_helper()->content_image(), &device_x,
173       &device_y, &device_width, &device_height);
174
175   int magnifier_x = location.x();
176   int magnifier_y = location.y() - height_ - kHeightOffset;
177
178   if (magnifier_y < device_y) // Do not let location to be out of screen
179     magnifier_y = device_y;
180   else if (magnifier_y > device_height + device_y - height_)
181     magnifier_y = device_height + device_y - height_;
182
183   if (magnifier_x < device_x + width_/2) // Do not let location to be out of screen
184     magnifier_x = device_x + width_/2;
185   else if (magnifier_x > device_width + device_x - width_/2)
186     magnifier_x = device_width + device_x - width_/2;
187
188   evas_object_move(container_, magnifier_x, magnifier_y);
189 }
190
191 void SelectionMagnifierEfl::Show() {
192   shown_ = true;
193   evas_object_show(container_);
194 #if !defined(USE_AURA)
195   RenderWidgetHostViewEfl* rwhv =
196       static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
197   if (rwhv)
198     rwhv->set_magnifier(true);
199 #endif
200   if (controller_->rwhva()->offscreen_helper()->ewk_view()) {
201     evas_object_smart_callback_call(
202         controller_->rwhva()->offscreen_helper()->ewk_view(), "magnifier,show",
203         nullptr);
204   }
205 }
206
207 void SelectionMagnifierEfl::Hide() {
208   shown_ = false;
209   evas_object_hide(content_image_);
210   evas_object_hide(container_);
211 #if !defined(USE_AURA)
212   RenderWidgetHostViewEfl* rwhv =
213       static_cast<RenderWidgetHostViewEfl*>(web_contents_.GetRenderWidgetHostView());
214   if (rwhv)
215     rwhv->set_magnifier(false);
216 #endif
217   if (controller_->rwhva()->offscreen_helper()->ewk_view()) {
218     evas_object_smart_callback_call(
219         controller_->rwhva()->offscreen_helper()->ewk_view(), "magnifier,hide",
220         nullptr);
221   }
222 }
223
224 }