Fix the position of the magnifier for text selection
[framework/web/webkit-efl.git] / Source / WebKit2 / UIProcess / API / efl / tizen / TextSelectionMagnifier.cpp
1 /*
2  * Copyright (C) 2012 Samsung Electronics
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(TIZEN_WEBKIT2_TEXT_SELECTION)
29 #include "TextSelectionMagnifier.h"
30
31 #include "WebImage.h"
32 #include "ewk_util.h"
33 #include <Elementary.h>
34 #include <WebCore/IntRect.h>
35 #include <cairo.h>
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 TextSelectionMagnifier::TextSelectionMagnifier(EwkViewImpl* viewImpl)
42     : m_viewImpl(viewImpl)
43     , m_image(0)
44     , m_magnifier(0)
45     , m_width(0)
46     , m_height(0)
47     , m_edjeWidth(0)
48     , m_edjeHeight(0)
49 {
50 }
51
52 TextSelectionMagnifier::~TextSelectionMagnifier()
53 {
54     if (m_image)
55         evas_object_del(m_image);
56     evas_object_del(m_magnifier);
57 }
58
59 static float s_widtheOffset = 32;
60 static float s_heightOffset = 60;
61
62 void TextSelectionMagnifier::update(const IntPoint& point)
63 {
64     if (!m_magnifier) {
65         Evas_Object* topWidget = elm_object_top_widget_get(elm_object_parent_widget_get(m_viewImpl->view()));
66         if (!topWidget)
67             topWidget = m_viewImpl->view();
68
69         m_magnifier = elm_layout_add(topWidget);
70         elm_layout_file_set(m_magnifier, EDJE_DIR"/Magnifier.edj", "magnifier");
71
72         edje_object_part_geometry_get(elm_layout_edje_get(m_magnifier), "bg", 0, 0, &m_edjeWidth, &m_edjeHeight);
73
74         m_width = m_edjeWidth - s_widtheOffset;
75         m_height = m_edjeHeight - s_heightOffset;
76     }
77
78     int viewX, viewY, viewWidth, viewHeight;
79     evas_object_geometry_get(m_viewImpl->view(), &viewX, &viewY, &viewWidth, &viewHeight);
80
81     float zoomLevel = 1.5f;
82     IntRect rect(point.x() - viewX - (ceil(m_width/zoomLevel)/2), point.y() - viewY - (ceil(m_height/zoomLevel)/2), ceil(m_width/zoomLevel), ceil(m_height/zoomLevel));
83
84     if (rect.x() < 0)
85         rect.setX(0);
86     if (rect.y() < 0)
87         rect.setY(0);
88
89     int overSize = rect.maxX() - (viewX + viewWidth);
90     if (overSize > 0)
91         rect.setX(rect.x() - overSize);
92     overSize = rect.maxY() - (viewY + viewHeight);
93     if (overSize > 0)
94         rect.setY(rect.y() - overSize);
95
96     RefPtr<WebImage> webImage = m_viewImpl->page()->createSnapshot(rect, zoomLevel);
97     if (!webImage || !webImage->bitmap())
98         return;
99     RefPtr<cairo_surface_t> cairoSurface = webImage->bitmap()->createCairoSurface();
100     if (!cairoSurface)
101         return;
102
103     if (m_image)
104         evas_object_del(m_image);
105
106     m_image = ewk_util_image_from_cairo_surface_add(evas_object_evas_get(m_viewImpl->view()), cairoSurface.get());
107     evas_object_size_hint_min_set(m_image, m_width, m_height);
108     evas_object_resize(m_image, m_width, m_height);
109     evas_object_image_filled_set(m_image, true);
110     evas_object_show(m_image);
111
112     elm_object_part_content_set(m_magnifier, "swallow", m_image);
113     evas_object_pass_events_set(m_image, EINA_TRUE);
114     evas_object_clip_set(m_image, m_magnifier);
115
116     evas_object_layer_set(m_magnifier, EVAS_LAYER_MAX);
117     evas_object_layer_set(m_image, EVAS_LAYER_MAX);
118 }
119
120 void TextSelectionMagnifier::show()
121 {
122     if (isVisible())
123         return;
124
125     evas_object_show(m_magnifier);
126     evas_object_smart_callback_call(m_viewImpl->view(), "magnifier,show", 0);
127 }
128
129 void TextSelectionMagnifier::hide()
130 {
131     if (!isVisible())
132         return;
133
134     evas_object_hide(m_magnifier);
135     evas_object_smart_callback_call(m_viewImpl->view(), "magnifier,hide", 0);
136 }
137
138 static int s_magnifierMargin = 10;
139 static int s_magnifierOffsetY = 220;
140 static int s_defaultEdjeHeight = 177;
141
142 void TextSelectionMagnifier::move(const IntPoint& point)
143 {
144     int viewX, viewY, viewWidth, viewHeight;
145     evas_object_geometry_get(m_viewImpl->view(), &viewX, &viewY, &viewWidth, &viewHeight);
146
147     int xPosition = point.x();
148     if (xPosition < viewX + (m_width / 2))
149         xPosition = viewX + m_width / 2 + s_magnifierMargin;
150     if (xPosition > viewX + viewWidth - (m_width / 2))
151         xPosition = viewX + viewWidth - (m_width / 2) - s_magnifierMargin;
152
153     int yPosition = point.y() - ((float)s_magnifierOffsetY * ((float)m_edjeHeight / s_defaultEdjeHeight));
154     if (yPosition < viewY)
155         yPosition = viewY;
156     if (yPosition > viewY + viewHeight)
157         yPosition = viewY + viewHeight;
158
159     evas_object_move(m_magnifier, xPosition, yPosition);
160 }
161
162 bool TextSelectionMagnifier::isVisible()
163 {
164     return evas_object_visible_get(m_magnifier);
165 }
166
167 } // namespace WebKit
168
169 #endif // TIZEN_WEBKIT2_TEXT_SELECTION