18 * Description: |
18 * Description: |
19 * |
19 * |
20 */ |
20 */ |
21 |
21 |
22 #include "ScrollableWebContentView.h" |
22 #include "ScrollableWebContentView.h" |
23 |
|
24 #include "Gestures/GestureRecognizer.h" |
|
25 #include "Kinetics/KineticScroller.h" |
23 #include "Kinetics/KineticScroller.h" |
26 #include "ScrollableViewBase.h" |
24 #include "ScrollableViewBase.h" |
27 #include "ViewportMetaDataParser.h" |
25 #include "ViewportMetaDataParser.h" |
28 #include "WebContentAnimationItem.h" |
26 #include "WebView.h" |
|
27 #include "qstmgestureevent.h" |
|
28 #include "qstmfilelogger.h" |
|
29 #include "bedrockprovisioning.h" |
|
30 #include "ScrollHelper.h" |
29 |
31 |
30 #include <QApplication> |
32 #include <QApplication> |
31 #include <QGraphicsScene> |
33 #include <QGraphicsScene> |
32 #include <QGraphicsSceneMouseEvent> |
34 #include <QGraphicsSceneMouseEvent> |
33 #include <QGraphicsWebView> |
35 #include <QGraphicsWebView> |
|
36 #include <QStyleOptionGraphicsItem> |
34 #include <QWebElement> |
37 #include <QWebElement> |
35 #include <QWebHitTestResult> |
38 #include <QWebHitTestResult> |
36 |
39 #include <QWebPage> |
|
40 #include <QWebHistory> |
|
41 #include <QInputContext> |
|
42 |
|
43 #include "Gestures/GestureRecognizer.h" |
|
44 #ifdef ORBIT_UI |
|
45 #include <hbinputmethod.h> |
|
46 #endif // ORBIT_UI |
|
47 |
|
48 namespace GVA { |
37 //Kinetic scroll constants |
49 //Kinetic scroll constants |
38 static const int ScrollsPerSecond = 30; |
50 static const int ScrollsPerSecond = 30; |
39 static const int MinimumScrollVelocity = 10; |
51 static const int MinimumScrollVelocity = 10; |
40 static const qreal AxisLockThreshold = .8; |
52 static const qreal AxisLockThreshold = .8; |
41 |
53 |
42 |
|
43 //Zooming constants |
54 //Zooming constants |
44 static const int ZoomAnimationDuration = 300; //ms. Zooming transition duration |
55 const int ZoomAnimationDuration = 600; //ms. Zooming transition duration |
|
56 const int MaxZoomAnimationDuration = 2000; //ms. Zooming transition duration |
45 static const qreal ZoomStep = .5; //Incremental zoom step |
57 static const qreal ZoomStep = .5; //Incremental zoom step |
46 const int TileUpdateEnableDelay = 500; //Wait duration before tiling updates are enabled. |
58 #ifdef Q_WS_MAEMO_5 |
47 |
59 const int TileUpdateEnableDelay = 10; //Wait duration before tiling updates are enabled. |
48 namespace GVA { |
60 #else |
49 |
61 const int TileUpdateEnableDelay = 150; //Wait duration before tiling updates are enabled. |
50 ScrollableWebContentView::ScrollableWebContentView(WebContentAnimationItem* webAnimationItem, QGraphicsItem* parent) |
62 #endif |
|
63 static const int MinDoubleClickZoomTargetWidth = 100; //Target block width for applying double tap zoom |
|
64 static const int ZoomCommitDuration = 60; //Timeout before commiting zoom |
|
65 static const qreal ZoomableContentMinWidth = 300.; |
|
66 |
|
67 static const qreal InvalidCoord = 1e10; |
|
68 static const int TouchDownTimeout = 200; |
|
69 static const int HoverTimeout = 100; |
|
70 |
|
71 #undef USE_KINETIC_SCROLLER |
|
72 using namespace qstmGesture; |
|
73 |
|
74 ScrollableWebContentView::ScrollableWebContentView(WebView* scrolledWidget, QGraphicsItem* parent) |
51 : ScrollableViewBase(parent) |
75 : ScrollableViewBase(parent) |
52 , m_gestureRecognizer(this) |
76 , m_gestureRecognizer(this) |
|
77 , m_isInputOn(false) |
|
78 , m_ignoreNextRelease(false) |
53 { |
79 { |
54 m_viewportMetaData = new ViewportMetaData(); |
80 m_viewportMetaData = new ViewportMetaData(); |
55 |
81 |
|
82 scrolledWidget->installEventFilter(this); |
|
83 |
56 //Kinetic scroller settings |
84 //Kinetic scroller settings |
57 //Sets the number of scrolls (frames) per second to sps. |
85 //Sets the number of scrolls (frames) per second to sps. |
58 m_kineticScroller->setScrollsPerSecond(ScrollsPerSecond); |
86 m_kineticScroller->setScrollsPerSecond(ScrollsPerSecond); |
59 //For elastic scroll in page edges |
87 //For elastic scroll in page edges |
60 m_kineticScroller->setOvershootPolicy(KineticScroller::OvershootWhenScrollable); |
88 m_kineticScroller->setOvershootPolicy(KineticScroller::OvershootWhenScrollable); |
61 |
89 |
|
90 setWidget(scrolledWidget); |
|
91 |
|
92 m_tileUpdateEnableTimer.setSingleShot(true); |
|
93 connect(&m_tileUpdateEnableTimer, SIGNAL(timeout()), this, SLOT(enableContentUpdates())); |
|
94 m_zoomCommitTimer.setSingleShot(true); |
|
95 connect(&m_zoomCommitTimer, SIGNAL(timeout()),this,SLOT(commitZoom())); |
|
96 |
|
97 //Setup zooming animator |
|
98 m_zoomAnimator = new QPropertyAnimation(this, "viewableRect"); |
|
99 //m_zoomAnimator->setDuration(ZoomAnimationDuration); |
|
100 connect(m_zoomAnimator, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), |
|
101 this, SLOT(zoomAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State))); |
|
102 |
|
103 m_isSuperPage = false; |
|
104 m_gesturesEnabled = true; |
|
105 m_isLoading = false; |
|
106 m_touchDownTimer = UiTimer::New(); |
|
107 m_touchDownTimer->setTimerCallback((char*)"touchDownCallback"); |
|
108 |
|
109 m_hoverTimer = UiTimer::New(); |
|
110 m_hoverTimer->setTimerCallback((char*)"hoverCallback"); |
|
111 |
|
112 m_touchDownTimer->setPriority(150); |
|
113 m_pinchFinishTime = QTime::currentTime(); |
|
114 // ScrollHelper |
|
115 m_scrollHelper = new ScrollHelper(this); |
|
116 initScrollHelper(); |
|
117 |
62 //Gesture settings |
118 //Gesture settings |
63 //For detecting scroll direction |
119 //For detecting scroll direction |
64 m_gestureRecognizer.setAxisLockThreshold(AxisLockThreshold); |
120 m_gestureRecognizer.setAxisLockThreshold(AxisLockThreshold); |
65 //To enable touch and drag scrolling |
121 //To enable touch and drag scrolling |
66 m_gestureRecognizer.setMinimumVelocity(MinimumScrollVelocity); |
122 m_gestureRecognizer.setMinimumVelocity(MinimumScrollVelocity); |
67 |
123 |
68 setWidget(webAnimationItem); |
124 grabGesture(QStm_Gesture::assignedType()); |
69 //FIX ME : Revisit this code. Duplicate info sharing! |
125 connect(this, SIGNAL(viewScrolled(QPoint&, QPoint&)), scrolledWidget, SLOT(viewScrolled(QPoint&, QPoint&))); |
70 webAnimationItem->setViewportMetaData(m_viewportMetaData); |
126 installEventFilter(this); |
71 |
127 } |
72 |
128 |
73 m_tileUpdateEnableTimer.setSingleShot(true); |
129 void ScrollableWebContentView::initScrollHelper() |
74 connect(&m_tileUpdateEnableTimer, SIGNAL(timeout()), webAnimationItem, SLOT(enableContentUpdates())); |
130 { |
75 |
131 qreal decel = BedrockSettings->value("KineticDeceleration").toDouble(); |
76 //Setup zooming animator |
132 m_scrollHelper->setDeceleration(decel); |
77 m_zoomAnimator = new QPropertyAnimation(webAnimationItem, "geometry"); |
133 |
78 m_zoomAnimator->setDuration(ZoomAnimationDuration); |
134 qreal maxFlickKoef = BedrockSettings->value("MaxFlickInViewportUnits").toDouble(); |
79 connect(m_zoomAnimator, SIGNAL(stateChanged(QAbstractAnimation::State,QAbstractAnimation::State)), this, SLOT(zoomAnimationStateChanged(QAbstractAnimation::State,QAbstractAnimation::State))); |
135 qreal minFlickKoef = BedrockSettings->value("MinFlickInViewportUnits").toDouble(); |
|
136 qreal midFlickKoef = BedrockSettings->value("MidFlickInViewportUnits").toDouble(); |
|
137 m_scrollHelper->setFlickLimits(minFlickKoef, midFlickKoef, maxFlickKoef); |
|
138 |
|
139 qreal maxFlickSpeed = BedrockSettings->value("MaxFlickSpeed").toDouble(); |
|
140 qreal minFlickSpeed = BedrockSettings->value("MinFlickSpeed").toDouble(); |
|
141 qreal midFlickSpeed = BedrockSettings->value("MidFlickSpeed").toDouble(); |
|
142 m_scrollHelper->setFlickSpeedLimits(minFlickSpeed, midFlickSpeed, maxFlickSpeed); |
|
143 |
|
144 int maxFlickDuration = BedrockSettings->value("MaxFlickDuration").toInt(); |
|
145 int minFlickDuration = BedrockSettings->value("MinFlickDuration").toInt(); |
|
146 int midFlickDuration = BedrockSettings->value("MidFlickDuration").toInt(); |
|
147 m_scrollHelper->setFlickDurationLimits(minFlickDuration, midFlickDuration, maxFlickDuration); |
|
148 |
|
149 connect(m_scrollHelper, SIGNAL(scrollFinished()), this, SLOT(stopScrolling())); |
80 |
150 |
81 m_gesturesEnabled = true; |
151 m_gesturesEnabled = true; |
82 } |
152 } |
83 |
153 |
84 ScrollableWebContentView::~ScrollableWebContentView() |
154 ScrollableWebContentView::~ScrollableWebContentView() |
85 { |
155 { |
86 delete m_viewportMetaData; |
156 delete m_viewportMetaData; |
87 delete m_kineticScroller; |
|
88 |
|
89 if(m_zoomAnimator) { |
157 if(m_zoomAnimator) { |
90 m_zoomAnimator->stop(); |
158 m_zoomAnimator->stop(); |
91 delete m_zoomAnimator; |
159 delete m_zoomAnimator; |
92 } |
160 } |
93 } |
161 |
94 |
162 m_touchDownTimer->stop(); |
95 WebContentAnimationItem* ScrollableWebContentView::viewportWidget() const |
163 delete m_touchDownTimer; |
96 { |
164 |
97 return qobject_cast<WebContentAnimationItem*>(scrollWidget()); |
165 m_hoverTimer->stop(); |
98 } |
166 delete m_hoverTimer; |
99 |
167 |
100 void ScrollableWebContentView::zoomToScreenCenter(bool zoomIn) |
168 } |
|
169 |
|
170 void ScrollableWebContentView::stepZoom(bool zoomIn) |
101 { |
171 { |
102 //If viewport metadata has user scalable false. |
172 //If viewport metadata has user scalable false. |
103 //Do not zoom. |
173 //Do not zoom. |
104 if (!m_viewportMetaData->m_userScalable) |
174 if (!m_viewportMetaData->m_userScalable) |
105 return; |
175 return; |
106 |
176 |
|
177 if (isZooming()) { |
|
178 stopZoomAnimation(); |
|
179 return; |
|
180 } |
|
181 |
107 qreal scale = 1; |
182 qreal scale = 1; |
108 scale += ZoomStep; |
183 scale += ZoomStep; |
109 |
184 |
110 if (!zoomIn) |
185 if (!zoomIn) |
111 scale = 1/scale; |
186 scale = 1/scale; |
112 |
187 |
113 qreal curScale = viewportWidget()->zoomScale(); |
188 qreal curScale = scrollWidget()->scale(); |
114 |
189 qreal destScale = curScale * scale; |
115 if (zoomIn && (curScale * scale > m_viewportMetaData->m_maximumScale)) |
190 |
116 scale = m_viewportMetaData->m_maximumScale / curScale; |
191 if (zoomIn && (destScale > m_viewportMetaData->m_maximumScale)) |
117 else if (!zoomIn && (curScale * scale < m_viewportMetaData->m_minimumScale)) |
192 destScale = m_viewportMetaData->m_maximumScale; |
118 scale = m_viewportMetaData->m_minimumScale / curScale; |
193 else if (!zoomIn && (destScale < m_viewportMetaData->m_minimumScale)) |
119 |
194 destScale = m_viewportMetaData->m_minimumScale; |
120 if(scale == 1.) |
195 |
|
196 if(destScale == curScale) |
121 return; |
197 return; |
122 |
198 |
123 //Screen center |
199 //Screen center |
124 QPointF scrCenter(size().width()/2, size().height()/2); |
200 //QPointF zoomHotSpot(size().width()/2, size().height()/2); //center zoom looks ugly in some cases |
125 //Map screen center to document |
201 QPointF zoomHotSpot(0, 0); |
126 QPointF docPoint(viewportWidget()->mapFromScene(scrCenter)); |
202 |
127 //Maintain that spot in the same point on the viewport |
203 startZoomAnimationToHotSpot(zoomHotSpot, destScale); |
128 QPointF docPointInScr(viewportWidget()->mapToParent(docPoint)); |
204 } |
129 startZoomAnimToItemHotspot(docPoint, docPointInScr, scale); |
205 |
130 } |
206 |
131 |
207 int ScrollableWebContentView::zoomAnimationTime(bool zoomIn, qreal targetScale) |
132 ZoomMetaData ScrollableWebContentView::currentPageInfo() |
208 { |
133 { |
209 qreal curScale = zoomScale(); |
134 ZoomMetaData data; |
210 qreal scaleRatio = zoomIn ? (targetScale / curScale) : |
135 |
211 1.2 * (curScale / targetScale); |
|
212 qreal fullScaleRatio = (m_viewportMetaData->m_maximumScale / m_viewportMetaData->m_minimumScale); |
|
213 return MaxZoomAnimationDuration * scaleRatio / fullScaleRatio; |
|
214 } |
|
215 |
|
216 void ScrollableWebContentView::toggleZoom(bool zoomIn) |
|
217 { |
|
218 m_scrollHelper->stopScrollNoSignal(); |
|
219 if (isZooming()) { |
|
220 stopZoomAnimation(); |
|
221 commitZoom(); |
|
222 return; |
|
223 } |
|
224 qreal scale = zoomIn ? m_viewportMetaData->m_maximumScale : m_viewportMetaData->m_minimumScale; |
|
225 int t = zoomAnimationTime(zoomIn, scale); |
|
226 QPointF zoomHotSpot(0, 0); |
|
227 startZoomAnimationToHotSpot(zoomHotSpot, scale, t); |
|
228 } |
|
229 |
|
230 QRectF ScrollableWebContentView::viewportRectInPageCoord(const QPointF& viewportHotSpot, |
|
231 const qreal destScale) |
|
232 { |
|
233 QSizeF vpSize = size(); |
|
234 QSizeF contentSize = webView()->size(); |
|
235 QSizeF scaleVpSize(vpSize.width() / destScale, vpSize.height() / destScale); |
|
236 QPointF contentHotSpot = webView()->mapFromParent(viewportHotSpot); |
|
237 QPointF scaledHotSpot = viewportHotSpot / destScale; |
|
238 QRectF destViewRect( contentHotSpot - scaledHotSpot, scaleVpSize); |
|
239 return destViewRect; |
|
240 } |
|
241 |
|
242 void ScrollableWebContentView::startZoomAnimationToHotSpot(const QPointF& viewportHotSpot, |
|
243 const qreal destScale, int animTime) |
|
244 { |
|
245 QRectF destViewRect = viewportRectInPageCoord(viewportHotSpot, destScale); |
|
246 startZoomAnimation(destViewRect, animTime); |
|
247 } |
|
248 |
|
249 void ScrollableWebContentView::zoomToHotSpot(const QPointF& viewportHotSpot, const qreal destScale) |
|
250 { |
|
251 QRectF destViewRect = viewportRectInPageCoord(viewportHotSpot, destScale); |
|
252 destViewRect = validateViewportRect(destViewRect); |
|
253 setViewableRect(destViewRect); |
|
254 } |
|
255 |
|
256 WebPageData ScrollableWebContentView::pageDataFromViewportInfo() |
|
257 { |
|
258 if(!m_viewportMetaData->m_isValid) return WebPageData(); |
|
259 |
|
260 // No viewport data saving or restoring for superpages |
|
261 if(isSuperPage()) return WebPageData(); |
|
262 |
|
263 // invalidate viewport meta data after saving to history |
|
264 // cannot do it earlier because loadStarted event comes earlier than save to history |
|
265 if(m_isLoading) |
|
266 m_viewportMetaData->m_isValid = false; |
|
267 |
|
268 bool fitToScreen = qFuzzyCompare(m_viewportMetaData->m_width / webView()->size().width(), zoomScale()); |
|
269 |
|
270 return WebPageData(m_viewportMetaData->m_maximumScale, m_viewportMetaData->m_minimumScale, |
|
271 m_viewportMetaData->m_userScalable, m_viewportMetaData->m_initialScale, |
|
272 geometry(), webView()->geometry(), scrollWidget()->scale(), size(), |
|
273 m_viewportMetaData->m_specifiedData.m_width, m_viewportMetaData->m_specifiedData.m_height, |
|
274 fitToScreen); |
|
275 } |
|
276 |
|
277 QSizeF ScrollableWebContentView::parentSize() const |
|
278 { |
|
279 return static_cast<QGraphicsWidget*>(parentItem())->size(); |
|
280 } |
|
281 |
|
282 void ScrollableWebContentView::setPageDataToViewportInfo(const WebPageData& data) |
|
283 { |
|
284 if(!data.isValid()) return; |
|
285 |
|
286 // No viewport data saving or restoring for superpages |
|
287 if(isSuperPage()) return; |
|
288 |
|
289 m_viewportMetaData->m_initialScale = data.initialScale; |
|
290 m_viewportMetaData->m_minimumScale = data.minScale; |
|
291 m_viewportMetaData->m_maximumScale = data.maxScale; |
|
292 m_viewportMetaData->m_userScalable = data.userScalable; |
|
293 m_viewportMetaData->m_specifiedData.m_width = data.specifiedWidth; |
|
294 m_viewportMetaData->m_specifiedData.m_height = data.specifiedHeight; |
|
295 m_viewportMetaData->m_isValid = true; |
|
296 m_viewportMetaData->m_width = data.viewportSize.width(); |
|
297 m_viewportMetaData->m_height = data.viewportSize.height(); |
|
298 |
|
299 |
|
300 if(m_viewportMetaData->m_width < 0 || |
|
301 m_viewportMetaData->m_width < 0) { |
|
302 m_viewportMetaData->m_isValid = false; |
|
303 reset(); |
|
304 return; |
|
305 } |
|
306 |
|
307 QSizeF newSize = parentSize(); |
|
308 if(newSize.isEmpty()) |
|
309 newSize = data.viewportSize; |
|
310 |
|
311 disableContentUpdates(); |
|
312 // updateViewportMetaDataFromPageTag(); |
|
313 |
|
314 |
|
315 QSizeF vpSz(m_viewportMetaData->m_width, m_viewportMetaData->m_height); |
|
316 if(vpSz.isEmpty()) |
|
317 vpSz = newSize; |
|
318 |
|
319 // sometimes on load from history webpage doesn't resize webView |
|
320 // set correct size of webView here |
|
321 webView()->setGeometry(QRectF( QPointF(0, 0), |
|
322 QSizeF(webView()->page()->mainFrame()->contentsSize()))); |
|
323 |
|
324 qreal sc = data.scale; //qBound(m_viewportMetaData->m_minimumScale,data.scale,m_viewportMetaData->m_maximumScale); |
|
325 webView()->setScale(sc); |
|
326 |
|
327 // qreal fitToScreenScale = data.viewportSize.width() / webView()->size().width(); |
|
328 // bool isFitToScreen = qFuzzyCompare(zoomScale(), fitToScreenScale); |
|
329 adjustViewportSize(data.viewportSize, newSize); |
|
330 m_viewportMetaData->adjustZoomValues(webView()->size()); |
|
331 if(data.fitToScreen && newSize.width() != vpSz.width()) { |
|
332 qreal fitToScreenScale = size().width() / webView()->size().width(); |
|
333 fitToScreenScale = qBound(m_viewportMetaData->m_minimumScale, |
|
334 fitToScreenScale,m_viewportMetaData->m_minimumScale); |
|
335 webView()->setScale(fitToScreenScale); |
|
336 } |
|
337 // else |
|
338 // updatePreferredContentSize(); |
|
339 |
|
340 if (newSize.width() != m_viewportMetaData->m_width || |
|
341 newSize.height() != m_viewportMetaData->m_height) { |
|
342 //setGeometry(0, 0, m_viewportMetaData->m_width, m_viewportMetaData->m_height); |
|
343 m_scrollHelper->setViewportSize(size()); |
|
344 } |
|
345 |
|
346 |
|
347 if (data.webViewRect.isValid()) { |
|
348 QPointF webViewPos = data.webViewRect.topLeft(); |
|
349 qreal newSc = webView()->scale(); // might be adjust by fitToScreen |
|
350 webViewPos = webViewPos / sc * newSc; // recalc pos if scale changed by fitToScreen |
|
351 QSizeF ss = webView()->size() * newSc; |
|
352 if(!ss.isEmpty()) { |
|
353 webViewPos.setX(qBound((qreal)m_viewportMetaData->m_width - (qreal)ss.width(), (qreal)webViewPos.x(), (qreal)0.0)); |
|
354 webViewPos.setY(qBound((qreal)m_viewportMetaData->m_height - (qreal)ss.height(), (qreal)webViewPos.y(), (qreal)0.0)); |
|
355 if(ss.width() < m_viewportMetaData->m_width) webViewPos.setX(0); |
|
356 if(ss.height() < m_viewportMetaData->m_height) webViewPos.setY(0); |
|
357 } |
|
358 setScrollWidgetPos(webViewPos); |
|
359 } |
|
360 enableContentUpdates(); |
|
361 // updatePreferredContentSize(); |
|
362 |
|
363 |
|
364 // emit scrolled event to hide/show url bar |
|
365 |
|
366 QPoint p(0, 0); |
|
367 if(!m_isLoading) { |
|
368 p = scrollPosition(); |
|
369 } |
|
370 QPoint d(0, 0); |
|
371 emit viewScrolled(p, d); |
|
372 |
|
373 } |
|
374 |
|
375 WebPageData ScrollableWebContentView::defaultZoomData() |
|
376 { |
|
377 WebPageData data; |
|
378 |
|
379 data.magic = 0; |
136 data.initialScale = m_viewportMetaData->m_initialScale; |
380 data.initialScale = m_viewportMetaData->m_initialScale; |
137 data.minScale = m_viewportMetaData->m_minimumScale; |
381 data.minScale = m_viewportMetaData->m_minimumScale; |
138 data.maxScale = m_viewportMetaData->m_maximumScale; |
382 data.maxScale = m_viewportMetaData->m_maximumScale; |
139 data.userScalable = m_viewportMetaData->m_userScalable; |
383 data.userScalable = m_viewportMetaData->m_userScalable; |
140 data.m_specifiedWidth = m_viewportMetaData->m_specifiedData.m_width; |
384 |
141 data.m_specifiedHeight= m_viewportMetaData->m_specifiedData.m_height; |
385 data.scale = 1.0; |
142 |
386 data.rect = rect(); |
143 data.rect = viewportWidget()->geometry(); |
387 data.webViewRect = webView()->rect(); |
144 data.scale = viewportWidget()->zoomScale(); |
388 data.viewportSize = QSizeF(m_viewportMetaData->m_width, m_viewportMetaData->m_height); |
145 data.webViewSize = viewportWidget()->webView()->geometry(); |
|
146 data.viewportSize = size(); |
|
147 |
389 |
148 return data; |
390 return data; |
149 } |
391 } |
150 |
392 |
151 void ScrollableWebContentView::setCurrentPageInfo(ZoomMetaData data) |
|
152 { |
|
153 m_viewportMetaData->m_initialScale = data.initialScale; |
|
154 m_viewportMetaData->m_minimumScale = data.minScale; |
|
155 m_viewportMetaData->m_maximumScale = data.maxScale; |
|
156 m_viewportMetaData->m_userScalable = data.userScalable; |
|
157 m_viewportMetaData->m_specifiedData.m_width = data.m_specifiedWidth; |
|
158 m_viewportMetaData->m_specifiedData.m_height = data.m_specifiedHeight; |
|
159 m_viewportMetaData->m_isValid = true; |
|
160 |
|
161 m_viewportMetaData->m_width = data.webViewSize.width(); |
|
162 m_viewportMetaData->m_height = data.webViewSize.height(); |
|
163 |
|
164 viewportWidget()->webView()->setGeometry(data.webViewSize); |
|
165 viewportWidget()->setZoomScale(data.scale, true); |
|
166 viewportWidget()->setGeometry(data.rect); |
|
167 |
|
168 if (data.viewportSize.width() != size().width()) |
|
169 adjustViewportSize(data.viewportSize, size()); |
|
170 } |
|
171 |
|
172 ZoomMetaData ScrollableWebContentView::defaultZoomData() |
|
173 { |
|
174 ZoomMetaData data; |
|
175 |
|
176 data.initialScale = m_viewportMetaData->m_initialScale; |
|
177 data.minScale = m_viewportMetaData->m_minimumScale; |
|
178 data.maxScale = m_viewportMetaData->m_maximumScale; |
|
179 data.userScalable = m_viewportMetaData->m_userScalable; |
|
180 |
|
181 data.scale = 1.0; |
|
182 data.rect = QRectF(); |
|
183 data.webViewSize = QRectF(); |
|
184 data.viewportSize = QSizeF(); |
|
185 |
|
186 return data; |
|
187 } |
|
188 |
|
189 void ScrollableWebContentView::updatePreferredContentSize() |
393 void ScrollableWebContentView::updatePreferredContentSize() |
190 { |
394 { |
191 viewportWidget()->updatePreferredContentSize(QSize(m_viewportMetaData->m_width |
395 #ifdef VIEWPORT_ALWAYS_ALLOW_ZOOMING |
192 , m_viewportMetaData->m_height)); |
396 // Don't call updatePreferredContentSize() if we've over-ridden user-scalable because it |
|
397 // resets the content size and zoom factor. |
|
398 if(m_viewportMetaData->m_userScalableOverRidden) |
|
399 return; |
|
400 #endif |
|
401 QSize s = m_viewportMetaData->getSpecifiedSize(); |
|
402 /* if (!isSuperPage()) { |
|
403 prefferedHeight = qMax(m_viewportMetaData->m_width, m_viewportMetaData->m_height); |
|
404 prefferedWidth = m_viewportMetaData->m_width; |
|
405 if(m_viewportMetaData->m_width * 1.5 < prefferedHeight) { |
|
406 // If the screen sides ratio is less than 3:2, than vertical width is |
|
407 // too narrow for normal page layout, but setting preffered width to the biggest side |
|
408 // makes page too scaled. Because of this set the page to the average of 2 viewport sides. |
|
409 prefferedWidth = (m_viewportMetaData->m_width + prefferedHeight) / 2; |
|
410 } |
|
411 } |
|
412 |
|
413 // if(m_viewportMetaData->m_specifiedData.) |
|
414 */ |
|
415 webView()->page()->setPreferredContentsSize(s); |
|
416 } |
|
417 |
|
418 void ScrollableWebContentView::setPage(QWebPage* page) |
|
419 { |
|
420 m_isSuperPage = false; |
|
421 m_gesturesEnabled = true; |
|
422 webView()->setPage(page); |
193 } |
423 } |
194 |
424 |
195 void ScrollableWebContentView::setSuperPage() |
425 void ScrollableWebContentView::setSuperPage() |
196 { |
426 { |
|
427 m_isSuperPage = true; |
197 m_viewportMetaData->m_initialScale = 1.; |
428 m_viewportMetaData->m_initialScale = 1.; |
198 m_viewportMetaData->m_minimumScale = 1.; |
429 m_viewportMetaData->m_minimumScale = 1.; |
199 m_viewportMetaData->m_maximumScale = 1.; |
430 m_viewportMetaData->m_maximumScale = 1.; |
200 m_viewportMetaData->m_specifiedData.m_width = "device-width"; |
431 m_viewportMetaData->m_specifiedData.m_width = "device-width"; |
201 m_viewportMetaData->m_specifiedData.m_height = "device-height"; |
432 m_viewportMetaData->m_specifiedData.m_height = "device-height"; |
202 m_viewportMetaData->m_userScalable = false; |
433 m_viewportMetaData->m_userScalable = false; |
203 |
434 |
204 QSize contentSize = viewportWidget()->contentsSize(); |
435 disableContentUpdates(); |
205 QRect webViewRect(0, 0, size().width(), contentSize.height()); |
436 webView()->setScale(1.); |
206 viewportWidget()->webView()->setGeometry(webViewRect); |
437 //QSize contentSize = (webView()->size() * zoomScale()).toSize(); |
207 viewportWidget()->setZoomScale(1., true); |
438 //QRect webViewRect(0, 0, size().width(), contentSize.height()); |
208 viewportWidget()->setGeometry(webViewRect); |
439 //webView()->setGeometry(webViewRect); |
|
440 setScrollWidgetPos(QPointF(0, 0)); |
209 |
441 |
210 m_viewportMetaData->m_width = size().width(); |
442 m_viewportMetaData->m_width = size().width(); |
211 m_viewportMetaData->m_height = size().height(); |
443 m_viewportMetaData->m_height = size().height(); |
212 m_viewportMetaData->m_isValid = true; |
444 m_viewportMetaData->m_isValid = true; |
213 |
445 enableContentUpdates(); |
|
446 #ifdef VIEWPORT_ALWAYS_ALLOW_ZOOMING |
214 updatePreferredContentSize(); |
447 updatePreferredContentSize(); |
|
448 //viewportWidget()->updatePreferredContentSize(QSize(m_viewportMetaData->m_width |
|
449 // , m_viewportMetaData->m_height)); |
|
450 #else |
|
451 updatePreferredContentSize(); |
|
452 #endif |
|
453 } |
|
454 |
|
455 void ScrollableWebContentView::updateViewportMetaDataFromPageTag() |
|
456 { |
|
457 QWebPage* page = webView()->page(); |
|
458 if (!page) |
|
459 return; |
|
460 |
|
461 QWebFrame* frame = page->mainFrame(); |
|
462 QMap<QString, QString> metaData = frame->metaData(); |
|
463 QString viewportTag = metaData.value("viewport"); |
|
464 |
|
465 QRect clientRect = geometry().toAlignedRect(); |
|
466 ViewportMetaDataParser parser(clientRect); |
|
467 parser.parse(viewportTag, *m_viewportMetaData); |
|
468 |
|
469 m_viewportMetaData->adjustZoomValues(webView()->size()); |
215 } |
470 } |
216 |
471 |
217 void ScrollableWebContentView::reset() |
472 void ScrollableWebContentView::reset() |
218 { |
473 { |
219 // TODO: INVESTIGATE: In the case of multiple windows loading pages simultaneously, it is possible |
474 // TODO: INVESTIGATE: In the case of multiple windows loading pages simultaneously, it is possible |
220 // to be calling this slot on a signal from a frame that is not |
475 // to be calling this slot on a signal from a frame that is not |
221 // the frame of the page saved here. It might be better to use 'sender' instead of |
476 // the frame of the page saved here. It might be better to use 'sender' instead of |
222 // page->mainFrame() to get the metaData so that we use the meta data of the corresponding |
477 // page->mainFrame() to get the metaData so that we use the meta data of the corresponding |
223 // frame |
478 // frame |
224 |
479 |
225 QWebPage* page = viewportWidget()->webView()->page(); |
480 QWebPage* page = webView()->page(); |
226 if (!page) |
481 if (!page) |
227 return; |
482 return; |
|
483 // if(m_viewportMetaData->m_isValid) return; |
228 |
484 |
229 //Initialize viewport metadata |
485 //Initialize viewport metadata |
230 m_viewportMetaData->reset(); |
486 m_viewportMetaData->reset(); |
231 |
487 |
232 QWebFrame* frame = page->mainFrame(); |
488 disableContentUpdates(); |
233 QMap<QString, QString> metaData = frame->metaData(); |
489 |
234 QString viewportTag = metaData.value("viewport"); |
490 webView()->setScale(1); |
235 |
491 |
236 QRect clientRect = geometry().toAlignedRect(); |
492 // sometimes on load from history webpage doesn't resize webView |
237 ViewportMetaDataParser parser(clientRect); |
493 // set correct size of webView here |
238 *m_viewportMetaData = parser.parse(viewportTag); |
494 webView()->setGeometry(QRectF( QPointF(0, 0), |
239 |
495 QSizeF(webView()->page()->mainFrame()->contentsSize()))); |
|
496 |
|
497 updateViewportMetaDataFromPageTag(); |
|
498 |
|
499 //setViewportWidgetGeometry(QRectF(QPointF(), |
|
500 // QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height))); |
|
501 |
|
502 static const QPoint nullP(0,0); |
|
503 setScrollPosition(nullP,nullP); |
|
504 |
|
505 QSizeF sz(m_viewportMetaData->m_width, m_viewportMetaData->m_height); |
|
506 adjustViewportSize(sz, size()); |
|
507 |
|
508 qreal initScale = m_viewportMetaData->m_initialScale > 0 ? m_viewportMetaData->m_initialScale : |
|
509 m_viewportMetaData->m_width / webView()->size().width(); |
|
510 // m_viewportMetaData->m_initialScale = m_viewportMetaData->m_width / webView()->size().width(); |
|
511 webView()->setScale(initScale); |
|
512 |
|
513 enableContentUpdates(); |
|
514 |
|
515 m_scrollHelper->setViewportSize(size()); |
|
516 |
|
517 // Update corrected viewport data back to webpage metadata |
|
518 emit viewPortChanged(); |
|
519 } |
|
520 |
|
521 void ScrollableWebContentView::contentsSizeChanged(const QSize& newContentSize) |
|
522 { |
|
523 m_viewportMetaData->adjustZoomValues(newContentSize); |
|
524 qreal sc = zoomScale(); |
|
525 sc = qBound(m_viewportMetaData->m_minimumScale, sc, m_viewportMetaData->m_maximumScale); |
|
526 if(!qFuzzyCompare(sc, zoomScale())) |
|
527 webView()->setScale(sc); |
|
528 emit viewPortChanged(); |
|
529 } |
|
530 |
|
531 void ScrollableWebContentView::pageLoadStarted() |
|
532 { |
|
533 m_isLoading = true; |
|
534 // m_viewportMetaData->m_isValid = false; |
|
535 } |
|
536 |
|
537 void ScrollableWebContentView::pageLoadProgress(int progress) |
|
538 { |
|
539 } |
|
540 |
|
541 void ScrollableWebContentView::pageLoadFinished(bool ok) |
|
542 { |
|
543 Q_UNUSED(ok); |
|
544 m_isLoading = false; |
|
545 if(!m_viewportMetaData->m_isValid) |
|
546 m_viewportMetadataResetTimer.singleShot(0,this,SLOT(reset())); |
|
547 else { |
|
548 QSize contentSize = scrollWidget()->size().toSize(); |
|
549 m_viewportMetaData->adjustZoomValues(contentSize); |
|
550 } |
|
551 |
|
552 // report scroll position to hide url bar if necessary |
|
553 QPoint p = scrollPosition(); |
|
554 QPoint d(0, 0); |
|
555 emit viewScrolled(p, d); |
|
556 |
|
557 webView()->update(); // invalidate the view to force tiles update |
|
558 } |
|
559 |
|
560 |
|
561 void ScrollableWebContentView::zoomAtPoint(QPointF touchPoint) |
|
562 { |
|
563 QRectF target; |
|
564 |
|
565 //Get the focusable element rect from current touch position |
|
566 if(isZoomedIn()) { |
|
567 startZoomAnimationToHotSpot(touchPoint,size().width() / webView()->size().width()); |
|
568 return; |
|
569 } |
|
570 |
|
571 //Pass all events to recognizer |
|
572 QRectF zoomRect = findZoomableRectForPoint(touchPoint); |
|
573 |
|
574 if (!zoomRect.isValid()) { |
|
575 //FIX ME: Add an event ignore animation |
|
576 return; |
|
577 } |
|
578 |
|
579 startZoomAnimation(zoomRect); |
|
580 } |
|
581 |
|
582 |
|
583 void ScrollableWebContentView::setViewportWidgetGeometry(const QRectF& r) |
|
584 { |
|
585 if(r != geometry()) { |
|
586 setGeometry(r); |
|
587 emit viewPortChanged(); |
|
588 } |
|
589 } |
|
590 |
|
591 |
|
592 bool ScrollableWebContentView::isZoomedIn() const |
|
593 { |
|
594 qreal vpWidth = size().width(); |
|
595 qreal scaledContentWidth = scrollWidget()->size().width() * zoomScale(); |
|
596 qreal diff = scaledContentWidth - vpWidth; |
|
597 return diff > 0.01f; |
|
598 } |
|
599 |
|
600 void ScrollableWebContentView::stateChanged(KineticScrollable::State oldState, |
|
601 KineticScrollable::State newState) |
|
602 { |
|
603 ScrollableViewBase::stateChanged(oldState, newState); |
|
604 |
|
605 switch(newState) { |
|
606 case KineticScrollable::Pushing : |
|
607 case KineticScrollable::AutoScrolling : |
|
608 m_tileUpdateEnableTimer.stop(); |
|
609 //disableContentUpdates(); |
|
610 break; |
|
611 case KineticScrollable::Inactive : |
|
612 m_tileUpdateEnableTimer.start(TileUpdateEnableDelay); |
|
613 break; |
|
614 } |
|
615 } |
|
616 |
|
617 QRectF ScrollableWebContentView::validateViewportRect(const QRectF& rect) |
|
618 { |
|
619 QRectF ret(rect); |
|
620 |
|
621 if(ret.right() > webView()->size().width()) |
|
622 ret.moveLeft(webView()->size().width() - ret.width()); |
|
623 if(ret.bottom() > webView()->size().height()) |
|
624 ret.moveTop(webView()->size().height() - ret.height()); |
|
625 if(ret.x() < 0) ret.moveLeft(0); |
|
626 if(ret.y() < 0) ret.moveTop(0); |
|
627 // if(ret.width() > webView()->size().width()) ret.setWidth(webView()->size().width()); |
|
628 if(ret.width() > webView()->size().width()) |
|
629 ret.moveLeft(0); // do not center! ret.moveLeft(webView()->size().width() / 2 - ret.width() / 2); |
|
630 if(ret.height() > webView()->size().height()) |
|
631 ret.moveTop(0); // do not center! ret.moveTop(webView()->size().height() / 2 - ret.height() / 2); |
|
632 |
|
633 return ret; |
|
634 } |
|
635 |
|
636 QRectF ScrollableWebContentView::viewableRect() |
|
637 { |
|
638 return webView()->mapRectFromParent(geometry()); |
|
639 } |
|
640 |
|
641 void ScrollableWebContentView::setViewableRect(const QRectF& rect) |
|
642 { |
|
643 qreal scale = size().width() / rect.width(); |
|
644 qstmDebug() << "setViewableRect: rect: " << rect << ", scale: " << scale << "\n"; |
|
645 setZoomScale(scale, false); |
|
646 m_isScrolling = true; |
|
647 scrollPageTo(rect.topLeft()); |
|
648 m_isScrolling = false; |
|
649 } |
|
650 |
|
651 void ScrollableWebContentView::startZoomAnimation(const QRectF& destViewRect, int animTime) |
|
652 { |
|
653 if (webView()->geometry().isValid()) { |
|
654 m_zoomAnimator->setDuration(animTime); |
|
655 m_zoomAnimator->setStartValue(webView()->mapRectFromParent(geometry())); |
|
656 m_animationEndRect = validateViewportRect(destViewRect); |
|
657 m_zoomAnimator->setEndValue(m_animationEndRect); |
|
658 m_zoomAnimator->start(); |
|
659 } |
|
660 } |
|
661 |
|
662 void ScrollableWebContentView::stopZoomAnimation() |
|
663 { |
|
664 m_zoomAnimator->stop(); |
|
665 } |
|
666 |
|
667 void ScrollableWebContentView::zoomAnimationStateChanged(QAbstractAnimation::State newState,QAbstractAnimation::State) |
|
668 { |
|
669 switch (newState) { |
|
670 case QAbstractAnimation::Stopped: |
|
671 commitZoom(); |
|
672 break; |
|
673 case QAbstractAnimation::Running: |
|
674 disableContentUpdates(); |
|
675 break; |
|
676 default: |
|
677 break; |
|
678 } |
|
679 } |
|
680 |
|
681 void ScrollableWebContentView::resizeEvent(QGraphicsSceneResizeEvent* event) |
|
682 { |
|
683 //Ignore resize when chrome is being still setup |
|
684 if (event->oldSize().width()) { |
|
685 |
|
686 qreal fitToScreenScale = event->oldSize().width() / webView()->size().width(); |
|
687 bool isFitToScreen = qFuzzyCompare(zoomScale(), fitToScreenScale); |
|
688 QGraphicsWidget::resizeEvent(event); |
|
689 adjustViewportSize(event->oldSize(), event->newSize()); |
|
690 if (isFitToScreen && !isSuperPage()) { |
|
691 QPointF docViewTopLeft(webView()->mapFromParent(QPointF(0,0))); |
|
692 fitToScreenScale = size().width() / webView()->size().width(); |
|
693 zoomToHotSpot(docViewTopLeft, fitToScreenScale); |
|
694 m_zoomCommitTimer.start(ZoomCommitDuration); |
|
695 } else { |
|
696 QRectF viewRect = mapRectToItem(webView(), QRectF(QPointF(0,0), size())); |
|
697 QRectF validRect = validateViewportRect(viewRect); |
|
698 if(validRect != viewRect) |
|
699 setViewableRect(validRect); |
|
700 } |
|
701 m_scrollHelper->setViewportSize(size()); |
|
702 } |
|
703 |
|
704 #ifdef OWN_BACKING_STORE |
|
705 webView()->viewportUpdated(); |
|
706 #endif // OWN_BACKING_STORE |
|
707 } |
|
708 |
|
709 bool ScrollableWebContentView::isChangedToPortrait(QSizeF oldSize, QSizeF newSize) |
|
710 { |
|
711 return (oldSize.width() > oldSize.height()) && |
|
712 (newSize.width() < newSize.height()); |
|
713 } |
|
714 |
|
715 bool ScrollableWebContentView::isChangedToLandscape(QSizeF oldSize, QSizeF newSize) |
|
716 { |
|
717 return (oldSize.width() < oldSize.height()) && |
|
718 (newSize.width() > newSize.height()); |
|
719 emit mouseEvent(QEvent::GraphicsSceneMouseRelease); |
|
720 } |
|
721 |
|
722 bool ScrollableWebContentView::isOrientationChanged(QSizeF oldSize, QSizeF newSize) |
|
723 { |
|
724 return isChangedToPortrait(oldSize, newSize) || |
|
725 isChangedToLandscape(oldSize, newSize); |
|
726 } |
|
727 |
|
728 |
|
729 void ScrollableWebContentView::adjustViewportSize(QSizeF oldSize, QSizeF newSize) |
|
730 { |
|
731 if(newSize.isNull()) return; |
|
732 |
|
733 if (isOrientationChanged(oldSize, newSize)) { |
|
734 m_viewportMetaData->orientationChanged(oldSize); |
|
735 } |
|
736 m_viewportMetaData->adjustViewportData(newSize); |
240 updatePreferredContentSize(); |
737 updatePreferredContentSize(); |
241 setViewportWidgetGeometry(QRectF(QPointF(), |
738 return; |
242 QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height) |
739 } |
243 * m_viewportMetaData->m_initialScale)); |
740 |
244 } |
741 void ScrollableWebContentView::sendEventToWebKit(QEvent::Type type, const QPointF& scenePos, bool select) |
245 |
742 { |
246 void ScrollableWebContentView::contentsSizeChanged(const QSize& newContentSize) |
743 QGraphicsSceneMouseEvent event(type); |
247 { |
744 qstmSetGraphicsSceneMouseEvent(scenePos, webView(), event, select); |
248 QRect clientRect = geometry().toAlignedRect(); |
745 webView()->page()->event(&event); |
249 m_viewportMetaData->updateViewportData(newContentSize, clientRect); |
746 } |
250 viewportWidget()->resize(QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height) |
747 |
251 * m_viewportMetaData->m_initialScale); |
748 void ScrollableWebContentView::disableContentUpdates() |
252 } |
749 { |
253 |
750 if (m_zoomCommitTimer.isActive()) { |
254 void ScrollableWebContentView::pageLoadFinished(bool ok) |
751 m_zoomCommitTimer.stop(); |
255 { |
752 } |
256 Q_UNUSED(ok); |
753 webView()->setTiledBackingStoreFrozen(true); |
257 QSize contentSize = viewportWidget()->contentsSize(); |
754 } |
258 QRect clientRect = geometry().toAlignedRect(); |
755 |
259 m_viewportMetaData->updateViewportData(contentSize, clientRect); |
756 void ScrollableWebContentView::enableContentUpdates() |
260 |
757 { |
261 viewportWidget()->resize(QSize(m_viewportMetaData->m_width, m_viewportMetaData->m_height) |
758 webView()->setTiledBackingStoreFrozen(false); |
262 * m_viewportMetaData->m_initialScale); |
759 } |
263 viewportWidget()->setZoomScale(m_viewportMetaData->m_initialScale, true); |
760 |
264 } |
761 void ScrollableWebContentView::commitZoom() |
|
762 { |
|
763 m_zoomCommitTimer.stop(); |
|
764 notifyZoomActions(zoomScale()); |
|
765 enableContentUpdates(); |
|
766 emit scaleChanged(zoomScale()); |
|
767 } |
|
768 |
|
769 WebView* ScrollableWebContentView::webView() const |
|
770 { |
|
771 return static_cast<WebView*>(scrollWidget()); |
|
772 } |
|
773 |
|
774 void ScrollableWebContentView::setZoomScale(qreal value, bool immediateCommit) |
|
775 { |
|
776 value = qBound(m_viewportMetaData->m_minimumScale, value, m_viewportMetaData->m_maximumScale); |
|
777 qreal curZoomScale = zoomScale(); |
|
778 |
|
779 if (qFuzzyCompare(value, curZoomScale)) { |
|
780 notifyZoomActions(curZoomScale); |
|
781 return; |
|
782 } |
|
783 |
|
784 if (!immediateCommit) |
|
785 disableContentUpdates(); |
|
786 |
|
787 webView()->setScale(value); |
|
788 |
|
789 if (immediateCommit) |
|
790 commitZoom(); |
|
791 // else |
|
792 // m_zoomCommitTimer.start(ZoomCommitDuration); |
|
793 } |
|
794 |
|
795 qreal ScrollableWebContentView::zoomScale() const |
|
796 { |
|
797 if (!webView()) |
|
798 return 1.; |
|
799 |
|
800 return webView()->scale(); |
|
801 } |
|
802 |
|
803 QRectF ScrollableWebContentView::findZoomableRectForPoint(const QPointF& point) |
|
804 { |
|
805 QPointF zoomPoint = webView()->mapFromParent(point); |
|
806 |
|
807 QWebHitTestResult hitResult = webView()->page()->mainFrame()->hitTestContent(zoomPoint.toPoint()); |
|
808 QWebElement targetElement = hitResult.enclosingBlockElement(); |
|
809 |
|
810 while (!targetElement.isNull() && targetElement.geometry().width() < MinDoubleClickZoomTargetWidth) |
|
811 targetElement = targetElement.parent(); |
|
812 |
|
813 if (!targetElement.isNull()) { |
|
814 QRectF elementRect = targetElement.geometry(); |
|
815 qreal overMinWidth = elementRect.width() - ZoomableContentMinWidth; |
|
816 if (overMinWidth < 0) |
|
817 elementRect.adjust(overMinWidth / 2, 0, -overMinWidth / 2, 0); |
|
818 qreal destScale = size().width() / elementRect.width(); |
|
819 QPointF rectPoint(elementRect.x(),zoomPoint.y() - point.y() / destScale); |
|
820 return QRectF(rectPoint, elementRect.size()); |
|
821 } |
|
822 return QRectF(); |
|
823 } |
|
824 |
|
825 void ScrollableWebContentView::notifyZoomActions(qreal newScale) |
|
826 { |
|
827 bool enableZoomIn = false; |
|
828 bool enableZoomOut = false; |
|
829 |
|
830 if (m_viewportMetaData->m_userScalable) { |
|
831 |
|
832 if (newScale > m_viewportMetaData->m_minimumScale) |
|
833 enableZoomOut = true; |
|
834 else |
|
835 enableZoomOut = false; |
|
836 |
|
837 if (newScale < m_viewportMetaData->m_maximumScale) |
|
838 enableZoomIn = true; |
|
839 else |
|
840 enableZoomIn = false; |
|
841 } |
|
842 |
|
843 emit updateZoomActions(enableZoomIn, enableZoomOut); |
|
844 } |
|
845 |
|
846 |
|
847 |
|
848 bool ScrollableWebContentView::eventFilter(QObject* o, QEvent* e) |
|
849 { |
|
850 if (o != scrollWidget()) return false; |
|
851 bool ret = false; |
|
852 |
|
853 if (m_gesturesEnabled) { |
|
854 ret = QStm_GestureEventFilter::instance()->eventFilter(o, e); |
|
855 } |
|
856 |
|
857 // Superpages should never receive contextmenu events |
|
858 if (isSuperPage() && (e->type() == QEvent::GraphicsSceneContextMenu || e->type() == QEvent::ContextMenu)) |
|
859 ret = true; |
|
860 |
|
861 return ret; |
|
862 } |
|
863 |
|
864 bool ScrollableWebContentView::event(QEvent * e) |
|
865 { |
|
866 if (e->type() == QEvent::Gesture && m_gesturesEnabled) { |
|
867 QStm_Gesture* gesture = getQStmGesture(e); |
|
868 if (gesture) { |
|
869 bool ret = handleQStmGesture(gesture); |
|
870 if (gesture->getGestureStmType() == QStmTouchGestureType) |
|
871 e->accept(); |
|
872 return ret; |
|
873 } |
|
874 } |
|
875 return QGraphicsWidget::event(e); |
|
876 } |
|
877 |
|
878 |
|
879 |
|
880 bool ScrollableWebContentView::handleQStmGesture(QStm_Gesture* gesture) |
|
881 { |
|
882 #ifdef OWN_BACKING_STORE |
|
883 // Signal tiling to minimize tile update activity while user does something |
|
884 webView()->userActivity(); |
|
885 #endif |
|
886 QStm_GestureType type = gesture->getGestureStmType(); |
|
887 bool ret = false; |
|
888 switch (type) { |
|
889 case QStmTapGestureType: |
|
890 { |
|
891 ret = doTap(gesture); |
|
892 break; |
|
893 } |
|
894 |
|
895 case QStmMaybeTapGestureType: |
|
896 { |
|
897 ret = doMaybeTap(gesture); |
|
898 break; |
|
899 } |
|
900 |
|
901 case QStmReleaseGestureType: |
|
902 { |
|
903 ret = doRelease(gesture); |
|
904 break; |
|
905 } |
|
906 case QStmLeftRightGestureType: |
|
907 { |
|
908 ret = doLeftRight(gesture); |
|
909 break; |
|
910 } |
|
911 case QStmUpDownGestureType: |
|
912 { |
|
913 ret = doUpDown(gesture); |
|
914 break; |
|
915 } |
|
916 case QStmPanGestureType: |
|
917 { |
|
918 ret = doPan(gesture); |
|
919 break; |
|
920 } |
|
921 case QStmFlickGestureType: |
|
922 { |
|
923 ret = doFlick(gesture); |
|
924 break; |
|
925 } |
|
926 case QStmDoubleTapGestureType: |
|
927 { |
|
928 ret = doDoubleTap(gesture); |
|
929 break; |
|
930 } |
|
931 case QStmTouchGestureType: |
|
932 { |
|
933 ret = doTouch(gesture); |
|
934 break; |
|
935 } |
|
936 case QStmPinchGestureType: |
|
937 { |
|
938 ret = doPinch(gesture); |
|
939 break; |
|
940 } |
|
941 case QStmLongPressGestureType: |
|
942 { |
|
943 ret = doLongPress(gesture); |
|
944 break; |
|
945 } |
|
946 |
|
947 default: |
|
948 { |
|
949 ret = true; |
|
950 } |
|
951 } |
|
952 |
|
953 return ret; |
|
954 } |
|
955 |
|
956 QWebHitTestResult ScrollableWebContentView::hitTest(const QPointF& scenePos) |
|
957 { |
|
958 QPointF contextPt = webView()->mapFromScene(scenePos); |
|
959 QWebPage* page = webView()->page(); |
|
960 return page->currentFrame()->hitTestContent(contextPt.toPoint()); |
|
961 } |
|
962 |
|
963 |
|
964 |
|
965 bool ScrollableWebContentView::toggleVkb() |
|
966 { |
|
967 bool inputEnabled = false; |
|
968 QInputContext *ic = qApp->inputContext(); |
|
969 if (m_hitTest.isContentEditable()) { |
|
970 QEvent sipe(QEvent::RequestSoftwareInputPanel); |
|
971 ic->filterEvent(&sipe); |
|
972 inputEnabled = true; |
|
973 } |
|
974 else { |
|
975 QEvent sipe(QEvent::CloseSoftwareInputPanel); |
|
976 ic->filterEvent(&sipe); |
|
977 |
|
978 } |
|
979 m_isInputOn = inputEnabled; |
|
980 return inputEnabled; |
|
981 } |
|
982 |
|
983 bool ScrollableWebContentView::toggleInputMethod(bool on) |
|
984 { |
|
985 QGraphicsView* gv = qstmGetGraphicsView(webView()); |
|
986 bool oldInputEnabled = false; |
|
987 if (gv != NULL) { |
|
988 gv->testAttribute(Qt::WA_InputMethodEnabled); |
|
989 gv->setAttribute(Qt::WA_InputMethodEnabled, on); |
|
990 } |
|
991 m_isInputOn = on; |
|
992 return oldInputEnabled; |
|
993 } |
|
994 |
|
995 bool ScrollableWebContentView::inputMethodEnabled() |
|
996 { |
|
997 #ifdef ORBIT_UI |
|
998 HbInputMethod* im = HbInputMethod::activeInputMethod(); |
|
999 |
|
1000 QGraphicsView* gv = qstmGetGraphicsView(webView()); |
|
1001 bool enabled = false; |
|
1002 if (gv) { |
|
1003 enabled = gv->testAttribute(Qt::WA_InputMethodEnabled); |
|
1004 } |
|
1005 return enabled; |
|
1006 #else |
|
1007 return false; |
|
1008 #endif // ORBIT_UI |
|
1009 } |
|
1010 |
|
1011 bool ScrollableWebContentView::doLongPress(QStm_Gesture* gesture) |
|
1012 { |
|
1013 bool willHandle = m_gesturesEnabled && !isSuperPage(); |
|
1014 if (willHandle) { |
|
1015 // QWebPage* page = webView()->page(); |
|
1016 QPoint gpos = gesture->position(); |
|
1017 QPointF pos = qstmMapToScene(gpos, this); |
|
1018 // QPointF contextPt = webView()->mapFromScene(pos); |
|
1019 //QWebHitTestResult result = page->currentFrame()->hitTestContent(contextPt.toPoint()); |
|
1020 //Notify context menu observers |
|
1021 emit contextEventObject(&m_hitTest, pos); |
|
1022 m_ignoreNextRelease = true; |
|
1023 } |
|
1024 return willHandle; |
|
1025 } |
|
1026 |
|
1027 |
|
1028 |
|
1029 bool ScrollableWebContentView::doTouch(QStm_Gesture* gesture) |
|
1030 { |
|
1031 bool willHandle = m_gesturesEnabled; |
|
1032 m_scrollHelper->stopScrollNoSignal(); |
|
1033 m_touchDownPos = gesture->scenePosition(this); |
|
1034 if (!isSuperPage()) { |
|
1035 m_hitTest = hitTest(m_touchDownPos); |
|
1036 //toggleInputMethod(false); |
|
1037 qreal scale = zoomScale(); |
|
1038 |
|
1039 m_hoverTimer->stop(); |
|
1040 m_hoverTimer->setSingleShot(true); |
|
1041 |
|
1042 m_touchDownTimer->stop(); |
|
1043 m_touchDownTimer->setSingleShot(true); |
|
1044 |
|
1045 m_touchDownTimer->start(TouchDownTimeout, this); |
|
1046 m_hoverTimer->start(HoverTimeout, this); |
|
1047 } |
|
1048 else { |
|
1049 sendEventToWebKit(QEvent::GraphicsSceneMousePress, m_touchDownPos); |
|
1050 } |
|
1051 return willHandle; |
|
1052 } |
|
1053 |
|
1054 void ScrollableWebContentView::touchDownCallback() |
|
1055 { |
|
1056 m_touchDownTimer->stop(); |
|
1057 if (m_gesturesEnabled) { |
|
1058 sendEventToWebKit(QEvent::GraphicsSceneMousePress, m_touchDownPos); |
|
1059 } |
|
1060 } |
|
1061 |
|
1062 void ScrollableWebContentView::hoverCallback() |
|
1063 { |
|
1064 m_hoverTimer->stop(); |
|
1065 if (m_gesturesEnabled && !isSuperPage()) { |
|
1066 sendEventToWebKit(QEvent::GraphicsSceneMouseMove, m_touchDownPos); |
|
1067 } |
|
1068 } |
|
1069 |
|
1070 |
|
1071 bool ScrollableWebContentView::doTap(QStm_Gesture* gesture) |
|
1072 { |
|
1073 bool willHandle = m_gesturesEnabled; |
|
1074 if (willHandle && !isSuperPage()) { |
|
1075 QPointF pos = gesture->scenePosition(this); |
|
1076 bool hasInputMethod = toggleVkb(); |
|
1077 sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, pos); |
|
1078 emit contentViewMouseEvent(QEvent::GraphicsSceneMouseRelease); |
|
1079 } |
|
1080 return willHandle; |
|
1081 } |
|
1082 |
|
1083 bool ScrollableWebContentView::doMaybeTap(QStm_Gesture* gesture) |
|
1084 { |
|
1085 bool willHandle = m_gesturesEnabled; |
|
1086 if (willHandle && isSuperPage()) { |
|
1087 QPointF pos = gesture->scenePosition(this); |
|
1088 sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, pos); |
|
1089 } |
|
1090 return willHandle; |
|
1091 } |
|
1092 |
|
1093 #ifdef USE_KINETIC_SCROLLER |
|
1094 bool ScrollableWebContentView::doPan(QStm_Gesture* gesture) |
|
1095 { |
|
1096 if (m_touchDownTimer->isActive()) { |
|
1097 m_touchDownTimer->stop(); |
|
1098 } |
|
1099 |
|
1100 QStm_GestureType type = gesture->getGestureStmType(); |
|
1101 bool willHandle = m_gesturesEnabled; |
|
1102 |
|
1103 if (willHandle) { |
|
1104 QPoint scrollPos = ScrollableViewBase::scrollPosition(); |
|
1105 QPoint delta = gesture->getLengthAndDirection(); |
|
1106 delta.ry() = -delta.y(); |
|
1107 m_kineticScroller->doPan(delta); |
|
1108 } |
|
1109 return willHandle; |
|
1110 } |
|
1111 #else |
|
1112 |
|
1113 |
|
1114 bool ScrollableWebContentView::doLeftRight(QStm_Gesture* gesture) |
|
1115 { |
|
1116 bool ret = true; |
|
1117 if (m_hitTest.isContentEditable() && m_isInputOn) { |
|
1118 QPointF pos = gesture->scenePosition(this); |
|
1119 sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true); |
|
1120 } |
|
1121 else { |
|
1122 ret = doPan(gesture); |
|
1123 } |
|
1124 return ret; |
|
1125 } |
|
1126 |
|
1127 |
|
1128 bool ScrollableWebContentView::doUpDown(QStm_Gesture* gesture) |
|
1129 { |
|
1130 bool ret = true; |
|
1131 if (m_hitTest.isContentEditable() && m_isInputOn) { |
|
1132 QPointF pos = gesture->scenePosition(this); |
|
1133 sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true); |
|
1134 } |
|
1135 else { |
|
1136 ret = doPan(gesture); |
|
1137 } |
|
1138 return ret; |
|
1139 } |
|
1140 |
|
1141 |
|
1142 |
|
1143 bool ScrollableWebContentView::doPan(QStm_Gesture* gesture) |
|
1144 { |
|
1145 bool willHandle = m_gesturesEnabled; |
|
1146 if (m_hitTest.isContentEditable() && m_isInputOn) { |
|
1147 QPointF pos = gesture->scenePosition(this); |
|
1148 sendEventToWebKit(QEvent::GraphicsSceneMouseMove, pos, true); |
|
1149 } |
|
1150 else { |
|
1151 dehighlightWebElement(); |
|
1152 if (willHandle) { |
|
1153 if (gesture->gestureState() != Qt::GestureFinished) { |
|
1154 QPointF delta = gesture->sceneLengthAndDirection(this); |
|
1155 |
|
1156 if (isSuperPage()) { |
|
1157 delta.rx() = 0.0; |
|
1158 } |
|
1159 else { |
|
1160 //delta.rx() = -delta.x(); |
|
1161 } |
|
1162 |
|
1163 //disableContentUpdates(); |
|
1164 qstmDebug() << "doPan: gesture timestamp: " << gesture->timestamp().toString("hh:mm:ss.zzz") << |
|
1165 ", delta: " << delta << "\n"; |
|
1166 |
|
1167 m_scrollHelper->scroll(delta); |
|
1168 } |
|
1169 } |
|
1170 } |
|
1171 return willHandle; |
|
1172 } |
|
1173 #endif //USE_KINETIC_SCROLLER |
|
1174 |
|
1175 |
|
1176 bool ScrollableWebContentView::doRelease(QStm_Gesture* gesture) |
|
1177 { |
|
1178 bool willHandle = m_gesturesEnabled; |
|
1179 if (willHandle) { |
|
1180 if (m_ignoreNextRelease) { |
|
1181 m_ignoreNextRelease = false; |
|
1182 } |
|
1183 else if (m_scrollHelper->isScrolling()) { |
|
1184 m_scrollHelper->panFromOvershoot(); |
|
1185 // enableContentUpdates(); |
|
1186 } |
|
1187 else { |
|
1188 /* |
|
1189 * on tap we send mouseRelease |
|
1190 * assumption here is that we can get |
|
1191 * either tap or release gesture but not both. |
|
1192 */ |
|
1193 doTap(gesture); |
|
1194 } |
|
1195 } |
|
1196 return willHandle; |
|
1197 } |
|
1198 |
|
1199 #ifdef USE_KINETIC_SCROLLER |
|
1200 bool ScrollableWebContentView::doFlick(QStm_Gesture* gesture) |
|
1201 { |
|
1202 int direction = gesture->getDirection(); |
|
1203 QStm_GestureType type = gesture->getGestureStmType(); |
|
1204 bool willHandle = m_gesturesEnabled; |
|
1205 if (willHandle ) { |
|
1206 m_kineticScroller->doFlick(90 * gesture->getSpeedVec()); |
|
1207 } |
|
1208 } |
|
1209 |
|
1210 #else |
|
1211 bool ScrollableWebContentView::doFlick(QStm_Gesture* gesture) |
|
1212 { |
|
1213 bool willHandle = m_gesturesEnabled; |
|
1214 int afterPinch = m_pinchFinishTime.elapsed(); |
|
1215 if (willHandle && afterPinch > 100 && m_scrollHelper->isScrolling()) { |
|
1216 dehighlightWebElement(); |
|
1217 int direction = gesture->sceneDirection(this); |
|
1218 QPointF v = gesture->sceneSpeedVec(this); |
|
1219 QPointF vOrig = v; |
|
1220 qstmDebug() << "doFlick: timestamp: " << gesture->timestamp().toString("hh:mm:ss.zzz") << |
|
1221 ", v: " << v << "\n"; |
|
1222 if (v.x() != 0.0 || v.y() != 0.0) { |
|
1223 if (direction == EEast || direction == EWest) { |
|
1224 v.ry() = 0.0; |
|
1225 } |
|
1226 if (direction == ENorth || direction == ESouth) { |
|
1227 v.rx() = 0.0; |
|
1228 } |
|
1229 m_scrollHelper->kineticScroll(v); |
|
1230 //enableContentUpdates(); |
|
1231 //m_tileUpdateEnableTimer.start(TileUpdateEnableDelay); |
|
1232 } |
|
1233 else if (afterPinch <= 500) { |
|
1234 qstmDebug() << "doFlick: Flick is too soon after pinch\n"; |
|
1235 } |
|
1236 } |
|
1237 return willHandle; |
|
1238 } |
|
1239 #endif //USE_KINETIC_SCROLLER |
|
1240 |
|
1241 bool ScrollableWebContentView::doDoubleTap(QStm_Gesture* gesture) |
|
1242 { |
|
1243 if (!m_gesturesEnabled || !m_viewportMetaData->m_userScalable) { |
|
1244 m_touchDownTimer->stop(); |
|
1245 m_hoverTimer->stop(); |
|
1246 return m_gesturesEnabled; |
|
1247 } |
|
1248 dehighlightWebElement(); |
|
1249 QPointF pos = gesture->scenePosition(this); |
|
1250 pos = mapFromScene(pos); |
|
1251 qstmDebug() << "doDoubleTap: zoom at pos: " << pos << "\n"; |
|
1252 zoomAtPoint(pos); |
|
1253 |
|
1254 return m_gesturesEnabled; |
|
1255 } |
|
1256 |
|
1257 #define square(x) (x)*(x) |
|
1258 |
|
1259 qreal ScrollableWebContentView::calcScale(int origDistance, QPointF p1, QPointF p2) |
|
1260 { |
|
1261 qreal d1f = origDistance; |
|
1262 qreal dist = calcDistance(p1, p2); |
|
1263 return (dist/ d1f); |
|
1264 } |
|
1265 |
|
1266 qreal ScrollableWebContentView::calcDistance(QPointF pt1, QPointF pt2) |
|
1267 { |
|
1268 return (sqrt((double)square(pt2.x() - pt1.x()) + square(pt2.y() - pt1.y()))); |
|
1269 } |
|
1270 |
|
1271 QPointF ScrollableWebContentView::calcCenter(QPointF pt1, QPointF pt2) |
|
1272 { |
|
1273 return((pt1 + pt2) / 2); |
|
1274 } |
|
1275 |
|
1276 bool ScrollableWebContentView::doPinch(QStm_Gesture* gesture) |
|
1277 { |
|
1278 m_scrollHelper->stopScrollNoSignal(); |
|
1279 dehighlightWebElement(); |
|
1280 m_pinchFinishTime.restart(); |
|
1281 if (!m_gesturesEnabled || !m_viewportMetaData->m_userScalable) |
|
1282 return m_gesturesEnabled; |
|
1283 |
|
1284 // Normally, "details" contains the distance between the two touched points |
|
1285 // It's null when the pinch starts (which in effect is zero) |
|
1286 // When we start pinch, we don't zoom because there is no delta |
|
1287 QPointF p1 = gesture->scenePosition(this); |
|
1288 QPointF p2 = gesture->scenePosition2(this); |
|
1289 if (gesture->gestureState() == Qt::GestureFinished) { |
|
1290 commitZoom(); |
|
1291 return m_gesturesEnabled; |
|
1292 } |
|
1293 |
|
1294 if (!gesture->getDetails()) { |
|
1295 m_pinchStartDistance = calcDistance(p1, p2); |
|
1296 m_pinchStartScale = zoomScale(); |
|
1297 } |
|
1298 else { |
|
1299 qreal scale = calcScale(m_pinchStartDistance, p1, p2); |
|
1300 qreal newScale = qBound(m_viewportMetaData->m_minimumScale, |
|
1301 scale * m_pinchStartScale, |
|
1302 m_viewportMetaData->m_maximumScale); |
|
1303 // Don't allow zooming beyond the min/max but still call the zoom animation (coz the hotspot could be moving and we want to pan with it) |
|
1304 //zoomToHotSpot(calcCenter(p1, p2), newScale); |
|
1305 if (!qFuzzyCompare(zoomScale(), newScale)) { |
|
1306 startZoomAnimationToHotSpot(calcCenter(p1, p2), newScale, ZoomAnimationDuration); |
|
1307 } |
|
1308 } |
|
1309 return m_gesturesEnabled; |
|
1310 } |
|
1311 |
|
1312 bool ScrollableWebContentView::isZooming() |
|
1313 { |
|
1314 return m_zoomAnimator->state() == QAbstractAnimation::Running; |
|
1315 } |
|
1316 |
|
1317 void ScrollableWebContentView::setGesturesEnabled(bool value) |
|
1318 { |
|
1319 if (!value && m_touchDownTimer->isActive()) { |
|
1320 m_touchDownTimer->stop(); |
|
1321 } |
|
1322 |
|
1323 m_gesturesEnabled = value; |
|
1324 } |
|
1325 |
|
1326 bool ScrollableWebContentView::gesturesEnabled() |
|
1327 { |
|
1328 return m_gesturesEnabled; |
|
1329 } |
|
1330 |
|
1331 |
|
1332 void ScrollableWebContentView::dehighlightWebElement() |
|
1333 { |
|
1334 m_touchDownTimer->stop(); |
|
1335 m_hoverTimer->stop(); |
|
1336 |
|
1337 QSizeF contentSize = webView()->size(); |
|
1338 QPointF dummyPosF(-contentSize.width() - 2.0, -contentSize.height( ) - 2.0); |
|
1339 QPoint dummyPos(-1, -1); |
|
1340 QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMouseRelease); |
|
1341 event.setScenePos(dummyPos); |
|
1342 event.setPos(dummyPos); |
|
1343 event.setButton(Qt::LeftButton); |
|
1344 |
|
1345 bool hasInputMethod = toggleInputMethod(false); |
|
1346 webView()->page()->event(&event); |
|
1347 toggleInputMethod(hasInputMethod); |
|
1348 //sendEventToWebKit(QEvent::GraphicsSceneMouseRelease, dummyPos); |
|
1349 } |
|
1350 |
|
1351 |
|
1352 void ScrollableWebContentView::stopScrolling() |
|
1353 { |
|
1354 m_isScrolling = false; |
|
1355 //enableContentUpdates(); |
|
1356 } |
|
1357 |
|
1358 |
265 |
1359 |
266 bool ScrollableWebContentView::sceneEventFilter(QGraphicsItem* item, QEvent* event) |
1360 bool ScrollableWebContentView::sceneEventFilter(QGraphicsItem* item, QEvent* event) |
267 { |
1361 { |
268 Q_UNUSED(item); |
1362 Q_UNUSED(item); |
269 |
1363 |
270 bool handled = false; |
1364 bool handled = false; |
271 |
1365 #ifdef USE_KINETIC_SCROLLER |
272 if (!isVisible() || !m_gesturesEnabled) { |
1366 if (!isVisible()) |
273 if (event->type() == QEvent::GraphicsSceneContextMenu) |
1367 return handled; |
274 return true; |
|
275 else |
|
276 return handled; |
|
277 } |
|
278 |
1368 |
279 //Pass all events to recognizer |
1369 //Pass all events to recognizer |
280 handled = m_gestureRecognizer.mouseEventFilter(static_cast<QGraphicsSceneMouseEvent *>(event)); |
1370 handled = m_gestureRecognizer.mouseEventFilter(static_cast<QGraphicsSceneMouseEvent *>(event)); |
|
1371 #endif |
281 return handled; |
1372 return handled; |
282 } |
1373 } |
|
1374 |
283 |
1375 |
284 void ScrollableWebContentView::handleGesture(GestureEvent* gestureEvent) |
1376 void ScrollableWebContentView::handleGesture(GestureEvent* gestureEvent) |
285 { |
1377 { |
286 switch (gestureEvent->type()) { |
1378 switch (gestureEvent->type()) { |
287 case GestureEvent::Touch: |
1379 case GestureEvent::Touch: |