Changed focus ring color
[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, bool immediately)
78 {
79     if (!m_imagePath.isNull())
80         return;
81
82     if (immediately) {
83         if (m_focusRingObject && evas_object_visible_get(m_focusRingObject))
84             return;
85         else {
86             if (m_showTimer) {
87                 ecore_timer_del(m_showTimer);
88                 m_showTimer = 0;
89             }
90
91             m_position = position;
92             show(IntRect());
93             return;
94         }
95     }
96
97     m_position = position;
98
99     if (m_showTimer)
100         ecore_timer_del(m_showTimer);
101     m_showTimer = ecore_timer_add((double)s_showTimerTime/1000.0, showTimerCallback, this);
102 }
103
104 void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
105 {
106     if (rect.isEmpty()) {
107         if (m_showTimer) {
108             ecore_timer_del(m_showTimer);
109             m_showTimer = 0;
110         }
111     }
112
113     PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
114     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
115
116     IntRect focusRingRect(rect);
117     Color focusRingColor;
118
119     if (rect.isEmpty()) {
120 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
121         IntPoint contentsPosition = m_viewImpl->transformFromScene().mapPoint(m_position);
122 #if ENABLE(TOUCH_ADJUSTMENT)
123         Evas_Coord size = elm_config_finger_size_get();
124         IntSize fingerSize = IntSize(size, size);
125 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
126         double scaleFactor = pageClientImpl->scaleFactor();
127         if (scaleFactor - 1 > numeric_limits<float>::epsilon())
128             fingerSize.scale(1 / scaleFactor, 1 / scaleFactor);
129 #endif
130         WebHitTestResult::Data hitTestResultData = m_viewImpl->page()->hitTestResultAtPoint(contentsPosition, WebHitTestResult::HitTestModeDefault, fingerSize);
131 #else
132         WebHitTestResult::Data hitTestResultData = m_viewImpl->page()->hitTestResultAtPoint(contentsPosition);
133 #endif
134         if (hitTestResultData.focusedRect.isEmpty())
135             return;
136
137         if (!hitTestResultData.absoluteImageURL.isEmpty() && hitTestResultData.absoluteLinkURL.isEmpty()) {
138             if (!includeOnlyImage)
139                 return;
140         }
141
142         focusRingRect = hitTestResultData.focusedRect;
143         focusRingColor = hitTestResultData.focusedColor;
144 #endif // #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
145     }
146
147     focusRingRect = m_viewImpl->transformToScene().mapRect(focusRingRect);
148
149     Evas_Coord_Rectangle viewGeometry;
150     evas_object_geometry_get(m_viewImpl->view(), &viewGeometry.x, &viewGeometry.y, &viewGeometry.w, &viewGeometry.h);
151     IntRect viewRect(viewGeometry.x, viewGeometry.y, viewGeometry.w, viewGeometry.h);
152     focusRingRect.intersect(viewRect);
153     if (focusRingRect.isEmpty()) {
154         hide(false);
155         return;
156     }
157
158     m_rect = focusRingRect;
159     m_rect.move(-viewGeometry.x, -viewGeometry.y);
160
161     if (m_focusRingObject)
162         evas_object_hide(m_focusRingObject);
163     else {
164         if (m_imagePath.isNull())
165             m_focusRingObject = evas_object_rectangle_add(evas_object_evas_get(m_viewImpl->view()));
166         else {
167             m_focusRingObject = evas_object_image_add(evas_object_evas_get(m_viewImpl->view()));
168             evas_object_image_file_set(m_focusRingObject, m_imagePath.utf8().data(), 0);
169             int border = m_imageOuterWidth + m_imageInnerWidth;
170             evas_object_image_border_set(m_focusRingObject, border, border, border, border);
171         }
172
173         evas_object_smart_member_add(m_focusRingObject, m_viewImpl->view());
174         evas_object_repeat_events_set(m_focusRingObject, true);
175     }
176
177     if (m_imagePath.isNull()) {
178         int r, g, b;
179         r = (focusRingColor.red() * focusRingColor.alpha()) / 255;
180         g = (focusRingColor.green() * focusRingColor.alpha()) / 255;
181         b = (focusRingColor.blue() * focusRingColor.alpha()) / 255;
182         evas_object_color_set(m_focusRingObject, r, g, b, focusRingColor.alpha());
183         evas_object_move(m_focusRingObject, focusRingRect.x(), focusRingRect.y());
184         evas_object_resize(m_focusRingObject, focusRingRect.width(), focusRingRect.height());
185     } else {
186         viewRect.inflate(-m_imageOuterWidth);
187
188         if (focusRingRect.intersects(viewRect))
189             focusRingRect.intersect(viewRect);
190         else {
191             if (viewRect.x() > focusRingRect.x()) {
192                 focusRingRect.setX(viewRect.x());
193                 focusRingRect.setWidth(1);
194             } else if (viewRect.maxX() < focusRingRect.maxX()) {
195                 focusRingRect.setX(viewRect.maxX());
196                 focusRingRect.setWidth(1);
197             }
198             if (viewRect.y() > focusRingRect.y()) {
199                 focusRingRect.setY(viewRect.y());
200                 focusRingRect.setHeight(1);
201             } else if (viewRect.maxY() < focusRingRect.maxY()) {
202                 focusRingRect.setY(viewRect.maxY());
203                 focusRingRect.setHeight(1);
204             }
205         }
206
207         evas_object_move(m_focusRingObject, focusRingRect.x() - m_imageOuterWidth, focusRingRect.y() - m_imageOuterWidth);
208
209         int width = focusRingRect.width() + m_imageOuterWidth * 2;
210         int height = focusRingRect.height() + m_imageOuterWidth * 2;
211         evas_object_image_fill_set(m_focusRingObject, 0, 0, width, height);
212         evas_object_resize(m_focusRingObject, width, height);
213     }
214
215     evas_object_show(m_focusRingObject);
216 }
217
218 void FocusRing::requestToHide(bool immediately)
219 {
220     if (immediately) {
221         hide();
222         return;
223     }
224
225     if (m_hideTimer)
226         ecore_timer_del(m_hideTimer);
227     m_hideTimer = ecore_timer_add((double)s_hideTimerTime/1000.0, hideTimerCallback, this);
228 }
229
230 Eina_Bool FocusRing::hideTimerCallback(void* data)
231 {
232     static_cast<FocusRing*>(data)->hide();
233     return ECORE_CALLBACK_CANCEL;
234 }
235
236 void FocusRing::hide(bool onlyColorDrawing)
237 {
238     if (!m_imagePath.isNull() && onlyColorDrawing)
239         return;
240
241     if (m_showTimer) {
242         ecore_timer_del(m_showTimer);
243         m_showTimer = 0;
244     }
245
246     if (m_hideTimer) {
247         ecore_timer_del(m_hideTimer);
248         m_hideTimer = 0;
249     }
250
251     if (m_focusRingObject && evas_object_visible_get(m_focusRingObject))
252         evas_object_hide(m_focusRingObject);
253
254     m_rect = IntRect();
255 }
256
257 void FocusRing::updateScrollAndScale(const WebCore::IntPoint& previousScrollPosition, float previousScale)
258 {
259 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
260     if (m_rect.isEmpty())
261         return;
262
263     FloatRect rect(m_rect);
264     rect.moveBy(previousScrollPosition);
265     rect.scale(1 / previousScale);
266
267     show(enclosingIntRect(rect));
268 #else
269     UNUSED_PARAM(previousScrollPosition);
270     UNUSED_PARAM(previousScale);
271 #endif
272 }
273
274 IntPoint FocusRing::centerPointInScreen()
275 {
276     if (m_rect.isEmpty())
277         return IntPoint(-1, -1);
278
279     IntPoint point(m_rect.center());
280     Evas_Coord x, y;
281     evas_object_geometry_get(m_viewImpl->view(), &x, &y, 0, 0);
282     point.move(x, y);
283
284     return point;
285 }
286
287 #endif // #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)