cba19d720874dc1c7dd709f3ee167abc6ee9484a
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / FocusRing.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include "config.h"
21 #include "FocusRing.h"
22
23 #include "EwkViewImpl.h"
24 #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)
25 #include "PageClientImpl.h"
26
27 #if ENABLE(TOUCH_ADJUSTMENT)
28 #include <Elementary.h>
29 #endif
30
31 using namespace WebKit;
32 using namespace WebCore;
33
34 FocusRing::FocusRing(EwkViewImpl* viewImpl)
35     : m_viewImpl(viewImpl)
36     , m_focusRingObject(0)
37     , m_imageOuterWidth(0)
38     , m_imageInnerWidth(0)
39     , m_showTimer(0)
40     , m_hideTimer(0)
41 {
42 }
43
44 FocusRing::~FocusRing()
45 {
46     if (m_showTimer)
47         ecore_timer_del(m_showTimer);
48
49     if (m_hideTimer)
50         ecore_timer_del(m_hideTimer);
51
52     if (m_focusRingObject)
53         evas_object_del(m_focusRingObject);
54 }
55
56 Eina_Bool FocusRing::showTimerCallback(void* data)
57 {
58     static_cast<FocusRing*>(data)->show(IntRect());
59     return ECORE_CALLBACK_CANCEL;
60 }
61
62 void FocusRing::setImage(const String& path, int outerWidth, int innerWidth)
63 {
64     if (m_imagePath == path && m_imageOuterWidth == outerWidth && m_imageInnerWidth == innerWidth)
65         return;
66
67     m_imagePath = path;
68     m_imageOuterWidth = outerWidth;
69     m_imageInnerWidth = innerWidth;
70
71     if (m_focusRingObject) {
72         evas_object_del(m_focusRingObject);
73         m_focusRingObject = 0;
74     }
75 }
76
77 void FocusRing::requestToShow(const IntPoint& position)
78 {
79     if (!m_imagePath.isNull())
80         return;
81
82     m_position = position;
83
84     if (m_showTimer)
85         ecore_timer_del(m_showTimer);
86     m_showTimer = ecore_timer_add((double)s_showTimerTime/1000.0, showTimerCallback, this);
87 }
88
89 void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
90 {
91     if (rect.isEmpty()) {
92         if (m_showTimer) {
93             ecore_timer_del(m_showTimer);
94             m_showTimer = 0;
95         }
96     }
97
98     PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
99     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
100
101     IntRect focusRingRect(rect);
102     Color focusRingColor;
103
104     if (rect.isEmpty()) {
105 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
106         IntPoint contentsPosition = m_viewImpl->transformFromScene().mapPoint(m_position);
107 #if ENABLE(TOUCH_ADJUSTMENT)
108         Evas_Coord size = elm_config_finger_size_get();
109         IntSize fingerSize = IntSize(size, size);
110 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
111         double scaleFactor = pageClientImpl->scaleFactor();
112         if (scaleFactor - 1 > numeric_limits<float>::epsilon())
113             fingerSize.scale(1 / scaleFactor, 1 / scaleFactor);
114 #endif
115         WebHitTestResult::Data hitTestResultData = m_viewImpl->page()->hitTestResultAtPoint(contentsPosition, WebHitTestResult::HitTestModeDefault, fingerSize);
116 #else
117         WebHitTestResult::Data hitTestResultData = m_viewImpl->page()->hitTestResultAtPoint(contentsPosition);
118 #endif
119         if (hitTestResultData.focusedRect.isEmpty())
120             return;
121
122         if (!hitTestResultData.absoluteImageURL.isEmpty() && hitTestResultData.absoluteLinkURL.isEmpty()) {
123             if (!includeOnlyImage)
124                 return;
125         }
126
127         focusRingRect = hitTestResultData.focusedRect;
128         focusRingColor = hitTestResultData.focusedColor;
129 #endif // #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
130     }
131
132     focusRingRect = m_viewImpl->transformToScene().mapRect(focusRingRect);
133
134     Evas_Coord_Rectangle viewGeometry;
135     evas_object_geometry_get(m_viewImpl->view(), &viewGeometry.x, &viewGeometry.y, &viewGeometry.w, &viewGeometry.h);
136     IntRect viewRect(viewGeometry.x, viewGeometry.y, viewGeometry.w, viewGeometry.h);
137     focusRingRect.intersect(viewRect);
138     if (focusRingRect.isEmpty()) {
139         hide(false);
140         return;
141     }
142
143     m_rect = focusRingRect;
144     m_rect.move(-viewGeometry.x, -viewGeometry.y);
145
146     if (m_focusRingObject)
147         evas_object_hide(m_focusRingObject);
148     else {
149         if (m_imagePath.isNull())
150             m_focusRingObject = evas_object_rectangle_add(evas_object_evas_get(m_viewImpl->view()));
151         else {
152             m_focusRingObject = evas_object_image_add(evas_object_evas_get(m_viewImpl->view()));
153             evas_object_image_file_set(m_focusRingObject, m_imagePath.utf8().data(), 0);
154             int border = m_imageOuterWidth + m_imageInnerWidth;
155             evas_object_image_border_set(m_focusRingObject, border, border, border, border);
156         }
157
158         evas_object_smart_member_add(m_focusRingObject, m_viewImpl->view());
159         evas_object_repeat_events_set(m_focusRingObject, true);
160     }
161
162     if (m_imagePath.isNull()) {
163         evas_object_color_set(m_focusRingObject, focusRingColor.red(), focusRingColor.green(), focusRingColor.blue(), focusRingColor.alpha());
164         evas_object_move(m_focusRingObject, focusRingRect.x(), focusRingRect.y());
165         evas_object_resize(m_focusRingObject, focusRingRect.width(), focusRingRect.height());
166     } else {
167         viewRect.inflate(-m_imageOuterWidth);
168
169         if (focusRingRect.intersects(viewRect))
170             focusRingRect.intersect(viewRect);
171         else {
172             if (viewRect.x() > focusRingRect.x()) {
173                 focusRingRect.setX(viewRect.x());
174                 focusRingRect.setWidth(1);
175             } else if (viewRect.maxX() < focusRingRect.maxX()) {
176                 focusRingRect.setX(viewRect.maxX());
177                 focusRingRect.setWidth(1);
178             }
179             if (viewRect.y() > focusRingRect.y()) {
180                 focusRingRect.setY(viewRect.y());
181                 focusRingRect.setHeight(1);
182             } else if (viewRect.maxY() < focusRingRect.maxY()) {
183                 focusRingRect.setY(viewRect.maxY());
184                 focusRingRect.setHeight(1);
185             }
186         }
187
188         evas_object_move(m_focusRingObject, focusRingRect.x() - m_imageOuterWidth, focusRingRect.y() - m_imageOuterWidth);
189
190         int width = focusRingRect.width() + m_imageOuterWidth * 2;
191         int height = focusRingRect.height() + m_imageOuterWidth * 2;
192         evas_object_image_fill_set(m_focusRingObject, 0, 0, width, height);
193         evas_object_resize(m_focusRingObject, width, height);
194     }
195
196     evas_object_show(m_focusRingObject);
197 }
198
199 void FocusRing::requestToHide(bool immediately)
200 {
201     if (immediately) {
202         hide();
203         return;
204     }
205
206     if (m_hideTimer)
207         ecore_timer_del(m_hideTimer);
208     m_hideTimer = ecore_timer_add((double)s_hideTimerTime/1000.0, hideTimerCallback, this);
209 }
210
211 Eina_Bool FocusRing::hideTimerCallback(void* data)
212 {
213     static_cast<FocusRing*>(data)->hide();
214     return ECORE_CALLBACK_CANCEL;
215 }
216
217 void FocusRing::hide(bool onlyColorDrawing)
218 {
219     if (!m_imagePath.isNull() && onlyColorDrawing)
220         return;
221
222     if (m_showTimer) {
223         ecore_timer_del(m_showTimer);
224         m_showTimer = 0;
225     }
226
227     if (m_hideTimer) {
228         ecore_timer_del(m_hideTimer);
229         m_hideTimer = 0;
230     }
231
232     if (m_focusRingObject && evas_object_visible_get(m_focusRingObject))
233         evas_object_hide(m_focusRingObject);
234
235     m_rect = IntRect();
236 }
237
238 void FocusRing::updateScrollAndScale(const WebCore::IntPoint& previousScrollPosition, float previousScale)
239 {
240 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
241     if (m_rect.isEmpty())
242         return;
243
244     FloatRect rect(m_rect);
245     rect.moveBy(previousScrollPosition);
246     rect.scale(1 / previousScale);
247
248     show(enclosingIntRect(rect));
249 #else
250     UNUSED_PARAM(previousScrollPosition);
251     UNUSED_PARAM(previousScale);
252 #endif
253 }
254
255 IntPoint FocusRing::centerPointInScreen()
256 {
257     if (m_rect.isEmpty())
258         return IntPoint(-1, -1);
259
260     IntPoint point(m_rect.center());
261     Evas_Coord x, y;
262     evas_object_geometry_get(m_viewImpl->view(), &x, &y, 0, 0);
263     point.move(x, y);
264
265     return point;
266 }
267
268 #endif // #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)