Implement that a text selection handle can be moved over another text selection handle.
[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 using namespace WebKit;
28 using namespace WebCore;
29
30 FocusRing::FocusRing(EwkViewImpl* viewImpl)
31     : m_viewImpl(viewImpl)
32     , m_focusRingObject(0)
33     , m_imageOuterWidth(0)
34     , m_imageInnerWidth(0)
35     , m_showTimer(0)
36 {
37 }
38
39 FocusRing::~FocusRing()
40 {
41     if (m_showTimer)
42         ecore_timer_del(m_showTimer);
43
44     if (m_focusRingObject)
45         evas_object_del(m_focusRingObject);
46 }
47
48 Eina_Bool FocusRing::showTimerCallback(void* data)
49 {
50     static_cast<FocusRing*>(data)->show(IntRect());
51     return ECORE_CALLBACK_CANCEL;
52 }
53
54 void FocusRing::setImage(const String& path, int outerWidth, int innerWidth)
55 {
56     if (m_imagePath == path && m_imageOuterWidth == outerWidth && m_imageInnerWidth == innerWidth)
57         return;
58
59     m_imagePath = path;
60     m_imageOuterWidth = outerWidth;
61     m_imageInnerWidth = innerWidth;
62
63     if (m_focusRingObject) {
64         evas_object_del(m_focusRingObject);
65         m_focusRingObject = 0;
66     }
67 }
68
69 void FocusRing::requestToShow(const IntPoint& position)
70 {
71     if (!m_imagePath.isNull())
72         return;
73
74     m_position = position;
75
76     if (m_showTimer)
77         ecore_timer_del(m_showTimer);
78     m_showTimer = ecore_timer_add((double)s_showTimerTime/1000.0, showTimerCallback, this);
79 }
80
81 void FocusRing::show(const IntRect& rect, const bool includeOnlyImage)
82 {
83     if (rect.isEmpty())
84         m_showTimer = 0;
85
86     PageClientImpl* pageClientImpl = m_viewImpl->pageClient.get();
87     EINA_SAFETY_ON_NULL_RETURN(pageClientImpl);
88
89     IntRect focusRingRect(rect);
90     Color focusRingColor;
91
92     if (rect.isEmpty()) {
93 #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
94         IntPoint contentsPosition = m_viewImpl->transformFromScene().mapPoint(m_position);
95         WebHitTestResult::Data hitTestResultData = m_viewImpl->page()->hitTestResultAtPoint(contentsPosition);
96         if (hitTestResultData.focusedRect.isEmpty())
97             return;
98
99         if (!hitTestResultData.absoluteImageURL.isEmpty() && hitTestResultData.absoluteLinkURL.isEmpty()) {
100             if (!includeOnlyImage)
101                 return;
102         }
103
104         focusRingRect = hitTestResultData.focusedRect;
105         focusRingColor = hitTestResultData.focusedColor;
106 #endif // #if ENABLE(TIZEN_WEBKIT2_HIT_TEST)
107     }
108
109     focusRingRect = m_viewImpl->transformToScene().mapRect(focusRingRect);
110
111     Evas_Coord_Rectangle viewGeometry;
112     evas_object_geometry_get(m_viewImpl->view(), &viewGeometry.x, &viewGeometry.y, &viewGeometry.w, &viewGeometry.h);
113     IntRect viewRect(viewGeometry.x, viewGeometry.y, viewGeometry.w, viewGeometry.h);
114     focusRingRect.intersect(viewRect);
115     if (focusRingRect.isEmpty()) {
116         hide(false);
117         return;
118     }
119
120     m_rect = focusRingRect;
121     m_rect.move(-viewGeometry.x, -viewGeometry.y);
122
123     if (m_focusRingObject)
124         evas_object_hide(m_focusRingObject);
125     else {
126         if (m_imagePath.isNull())
127             m_focusRingObject = evas_object_rectangle_add(evas_object_evas_get(m_viewImpl->view()));
128         else {
129             m_focusRingObject = evas_object_image_add(evas_object_evas_get(m_viewImpl->view()));
130             evas_object_image_file_set(m_focusRingObject, m_imagePath.utf8().data(), 0);
131             int border = m_imageOuterWidth + m_imageInnerWidth;
132             evas_object_image_border_set(m_focusRingObject, border, border, border, border);
133         }
134
135         evas_object_smart_member_add(m_focusRingObject, m_viewImpl->view());
136         evas_object_repeat_events_set(m_focusRingObject, true);
137     }
138
139     if (m_imagePath.isNull()) {
140         evas_object_color_set(m_focusRingObject, focusRingColor.red(), focusRingColor.green(), focusRingColor.blue(), focusRingColor.alpha());
141         evas_object_move(m_focusRingObject, focusRingRect.x(), focusRingRect.y());
142         evas_object_resize(m_focusRingObject, focusRingRect.width(), focusRingRect.height());
143     } else {
144         viewRect.inflate(-m_imageOuterWidth);
145
146         if (focusRingRect.intersects(viewRect))
147             focusRingRect.intersect(viewRect);
148         else {
149             if (viewRect.x() > focusRingRect.x()) {
150                 focusRingRect.setX(viewRect.x());
151                 focusRingRect.setWidth(1);
152             } else if (viewRect.maxX() < focusRingRect.maxX()) {
153                 focusRingRect.setX(viewRect.maxX());
154                 focusRingRect.setWidth(1);
155             }
156             if (viewRect.y() > focusRingRect.y()) {
157                 focusRingRect.setY(viewRect.y());
158                 focusRingRect.setHeight(1);
159             } else if (viewRect.maxY() < focusRingRect.maxY()) {
160                 focusRingRect.setY(viewRect.maxY());
161                 focusRingRect.setHeight(1);
162             }
163         }
164
165         evas_object_move(m_focusRingObject, focusRingRect.x() - m_imageOuterWidth, focusRingRect.y() - m_imageOuterWidth);
166
167         int width = focusRingRect.width() + m_imageOuterWidth * 2;
168         int height = focusRingRect.height() + m_imageOuterWidth * 2;
169         evas_object_image_fill_set(m_focusRingObject, 0, 0, width, height);
170         evas_object_resize(m_focusRingObject, width, height);
171     }
172
173     evas_object_show(m_focusRingObject);
174 }
175
176 void FocusRing::hide(bool onlyColorDrawing)
177 {
178     if (!m_imagePath.isNull() && onlyColorDrawing)
179         return;
180
181     if (m_showTimer) {
182         ecore_timer_del(m_showTimer);
183         m_showTimer = 0;
184     }
185
186     if (m_focusRingObject && evas_object_visible_get(m_focusRingObject))
187         evas_object_hide(m_focusRingObject);
188
189     m_rect = IntRect();
190 }
191
192 void FocusRing::updateScrollAndScale(const WebCore::IntPoint& previousScrollPosition, float previousScale)
193 {
194 #if ENABLE(TIZEN_WEBKIT2_TILED_BACKING_STORE)
195     if (m_rect.isEmpty())
196         return;
197
198     FloatRect rect(m_rect);
199     rect.moveBy(previousScrollPosition);
200     rect.scale(1 / previousScale);
201
202     show(enclosingIntRect(rect));
203 #else
204     UNUSED_PARAM(previousScrollPosition);
205     UNUSED_PARAM(previousScale);
206 #endif
207 }
208
209 IntPoint FocusRing::centerPointInScreen()
210 {
211     if (m_rect.isEmpty())
212         return IntPoint(-1, -1);
213
214     IntPoint point(m_rect.center());
215     Evas_Coord x, y;
216     evas_object_geometry_get(m_viewImpl->view(), &x, &y, 0, 0);
217     point.move(x, y);
218
219     return point;
220 }
221
222 #endif // #if ENABLE(TIZEN_WEBKIT2_FOCUS_RING)