22 ** Nokia at developer.feedback@nokia.com. |
22 ** Nokia at developer.feedback@nokia.com. |
23 ** |
23 ** |
24 ****************************************************************************/ |
24 ****************************************************************************/ |
25 |
25 |
26 #include "hbsplashscreen.h" |
26 #include "hbsplashscreen.h" |
|
27 #include "hbsplashscreen_generic_p.h" |
27 #include "hbsplash_p.h" |
28 #include "hbsplash_p.h" |
28 #include <QPainter> |
29 #include <QPainter> |
29 #include <QImage> |
|
30 #include <QApplication> |
30 #include <QApplication> |
31 #include <QWidget> |
|
32 #include <QPixmap> |
|
33 |
|
34 // To play nice with GPU resources it may be beneficial to avoid using QWidget |
|
35 // for showing the splash screen. (each top-level widget results in creating a |
|
36 // new window surface which consumes gpu memory) Instead, we can create & show a |
|
37 // CCoeControl which draws using the traditional Symbian GC methods. (And thus |
|
38 // uses the "legacy" surface which is still available currently. However if some |
|
39 // day it is removed then this solution will not work anymore.) |
|
40 #ifdef Q_OS_SYMBIAN |
|
41 // Do not enable for now, may cause some flickering. |
|
42 // The system transition effects may not like this solution anyway. |
|
43 //#define HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
|
44 #endif |
|
45 |
|
46 #ifdef HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
|
47 #include <coecntrl.h> |
|
48 #include <fbs.h> |
|
49 #include <w32std.h> |
|
50 #endif |
|
51 |
31 |
52 /*! |
32 /*! |
53 @stable |
33 @stable |
54 @hbcore |
34 @hbcore |
55 \class HbSplashScreen |
35 \class HbSplashScreen |
87 \var HbSplashScreen::Flag HbSplashScreen::FixedHorizontal |
67 \var HbSplashScreen::Flag HbSplashScreen::FixedHorizontal |
88 |
68 |
89 Indicates that the application will force its orientation to horizontal. As a |
69 Indicates that the application will force its orientation to horizontal. As a |
90 result the splash screen will also be forced to horizontal orientation. |
70 result the splash screen will also be forced to horizontal orientation. |
91 */ |
71 */ |
92 |
|
93 class HbSplashScreenInterface |
|
94 { |
|
95 public: |
|
96 virtual ~HbSplashScreenInterface() {} |
|
97 virtual void start(HbSplashScreen::Flags flags) = 0; |
|
98 virtual void release() = 0; |
|
99 }; |
|
100 |
|
101 class HbSplashScreenGeneric : public QWidget, public HbSplashScreenInterface |
|
102 { |
|
103 public: |
|
104 HbSplashScreenGeneric(); |
|
105 ~HbSplashScreenGeneric(); |
|
106 |
|
107 void start(HbSplashScreen::Flags flags); |
|
108 void release(); |
|
109 |
|
110 private: |
|
111 void paintEvent(QPaintEvent *event); |
|
112 void repaint(); |
|
113 |
|
114 uchar *mImageData; |
|
115 QPixmap mContents; |
|
116 }; |
|
117 |
|
118 #ifdef HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
|
119 |
|
120 class HbSplashScreenSymbian : public CCoeControl, public HbSplashScreenInterface |
|
121 { |
|
122 public: |
|
123 HbSplashScreenSymbian(); |
|
124 ~HbSplashScreenSymbian(); |
|
125 |
|
126 void start(HbSplashScreen::Flags flags); |
|
127 void release(); |
|
128 |
|
129 private: |
|
130 void Draw(const TRect &rect) const; |
|
131 |
|
132 CFbsBitmap *mContents; |
|
133 }; |
|
134 |
|
135 #endif // HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
|
136 |
72 |
137 static HbSplashScreenInterface *splashScreen = 0; |
73 static HbSplashScreenInterface *splashScreen = 0; |
138 |
74 |
139 struct RequestProps { |
75 struct RequestProps { |
140 RequestProps() : mSplashFlags(HbSplashScreen::Default) { } |
76 RequestProps() : mSplashFlags(HbSplashScreen::Default) { } |
267 QImage::Format fmt; |
202 QImage::Format fmt; |
268 RequestProps *props = requestProps(); |
203 RequestProps *props = requestProps(); |
269 mImageData = HbSplash::load(w, h, bpl, fmt, flags, |
204 mImageData = HbSplash::load(w, h, bpl, fmt, flags, |
270 props->mAppId, props->mScreenId); |
205 props->mAppId, props->mScreenId); |
271 if (mImageData) { |
206 if (mImageData) { |
272 QImage img(mImageData, w, h, bpl, fmt); |
207 mContents = QImage(mImageData, w, h, bpl, fmt); |
273 mContents = QPixmap::fromImage(img); |
|
274 resize(mContents.size()); |
208 resize(mContents.size()); |
275 } |
209 } |
276 } |
210 } |
277 if (!mContents.isNull()) { |
211 if (!mContents.isNull()) { |
|
212 qDebug("[hbsplash] splash screen initialized"); |
278 #ifdef Q_OS_SYMBIAN |
213 #ifdef Q_OS_SYMBIAN |
279 showFullScreen(); |
214 showFullScreen(); // krazy:exclude=qmethods |
280 #else |
215 #else |
281 show(); |
216 show(); |
282 #endif |
217 #endif |
283 QApplication::processEvents(); |
218 QApplication::processEvents(); |
284 QApplication::flush(); |
219 QApplication::flush(); |
|
220 // The splash screen must be destroyed automatically when |
|
221 // loosing foreground. |
|
222 if (QApplication::instance()) { |
|
223 QApplication::instance()->installEventFilter(this); |
|
224 } |
|
225 // The splash screen must be destroyed automatically after |
|
226 // a certain amount of time. |
|
227 mTimerId = startTimer(auto_stop_interval); |
285 } |
228 } |
286 } catch (const std::bad_alloc &) { |
229 } catch (const std::bad_alloc &) { |
287 } |
230 } |
288 } |
231 } |
289 |
232 |
290 void HbSplashScreenGeneric::paintEvent(QPaintEvent *event) |
233 void HbSplashScreenGeneric::paintEvent(QPaintEvent *event) |
291 { |
234 { |
292 Q_UNUSED(event); |
235 Q_UNUSED(event); |
293 QPainter painter(this); |
236 QPainter painter(this); |
294 painter.drawPixmap(QPointF(0, 0), mContents); |
237 painter.drawImage(QPointF(0, 0), mContents); |
295 } |
238 } |
296 |
239 |
297 void HbSplashScreenGeneric::repaint() |
240 void HbSplashScreenGeneric::repaint() |
298 { |
241 { |
299 QWidget::repaint(); |
242 QWidget::repaint(); |
300 QApplication::flush(); |
243 QApplication::flush(); |
301 } |
244 } |
302 |
245 |
303 #ifdef HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
246 void HbSplashScreenGeneric::timerEvent(QTimerEvent *event) |
304 |
247 { |
305 HbSplashScreenSymbian::HbSplashScreenSymbian() |
248 if (event->timerId() == mTimerId) { |
306 : mContents(0) |
249 qDebug("[hbsplash] timeout while splash screen is active"); |
307 { |
250 deleteLater(); |
308 } |
251 splashScreen = 0; |
309 |
|
310 HbSplashScreenSymbian::~HbSplashScreenSymbian() |
|
311 { |
|
312 delete mContents; |
|
313 } |
|
314 |
|
315 void HbSplashScreenSymbian::release() |
|
316 { |
|
317 delete this; |
|
318 } |
|
319 |
|
320 static uchar *fbsBitmapAllocFunc(int w, int h, int bpl, QImage::Format fmt, void *param) |
|
321 { |
|
322 if (fmt != QImage::Format_ARGB32_Premultiplied) { |
|
323 qWarning("HbSplash: fbsBitmapAllocFunc: unsupported format %d", fmt); |
|
324 return 0; |
|
325 } |
|
326 TDisplayMode mode = EColor16MAP; |
|
327 CFbsBitmap *bmp = static_cast<CFbsBitmap *>(param); |
|
328 if (bmp->Create(TSize(w, h), mode) == KErrNone) { |
|
329 int bmpBpl = CFbsBitmap::ScanLineLength(w, mode); |
|
330 if (bpl == bmpBpl) { |
|
331 return reinterpret_cast<uchar *>(bmp->DataAddress()); |
|
332 } else { |
|
333 qWarning("HbSplash: fbsBitmapAllocFunc: bpl mismatch (%d - %d)", bpl, bmpBpl); |
|
334 } |
|
335 } else { |
252 } else { |
336 qWarning("HbSplash: fbsBitmapAllocFunc: bitmap Create() failed"); |
253 QWidget::timerEvent(event); |
337 } |
254 } |
338 return 0; |
255 } |
339 } |
256 |
340 |
257 bool HbSplashScreenGeneric::eventFilter(QObject *obj, QEvent *event) |
341 void HbSplashScreenSymbian::start(HbSplashScreen::Flags flags) |
258 { |
342 { |
259 if (event->type() == QEvent::ApplicationDeactivate) { |
343 try { |
260 qDebug("[hbsplash] foreground lost while splash screen is active"); |
344 if (!mContents) { |
261 deleteLater(); |
345 mContents = new CFbsBitmap; |
262 splashScreen = 0; |
346 int w, h, bpl; |
263 } |
347 QImage::Format fmt; |
264 return QWidget::eventFilter(obj, event); |
348 RequestProps *props = requestProps(); |
265 } |
349 if (HbSplash::load(w, h, bpl, fmt, flags, |
|
350 props->mAppId, props->mScreenId, |
|
351 fbsBitmapAllocFunc, mContents)) |
|
352 { |
|
353 TRect rect(TPoint(0, 0), TSize(w, h)); |
|
354 TRAPD(err, { |
|
355 CreateWindowL(); |
|
356 RWindow *window = static_cast<RWindow *>(DrawableWindow()); |
|
357 window->SetSurfaceTransparency(ETrue); |
|
358 SetRect(rect); |
|
359 ActivateL(); }); |
|
360 if (err == KErrNone) { |
|
361 MakeVisible(ETrue); |
|
362 DrawNow(); |
|
363 } else { |
|
364 qWarning("HbSplash: symbian control init failed (%d)", err); |
|
365 } |
|
366 } else { |
|
367 delete mContents; |
|
368 mContents = 0; |
|
369 } |
|
370 } |
|
371 } catch (const std::bad_alloc &) { |
|
372 } |
|
373 } |
|
374 |
|
375 void HbSplashScreenSymbian::Draw(const TRect &rect) const |
|
376 { |
|
377 Q_UNUSED(rect); |
|
378 if (mContents) { |
|
379 SystemGc().BitBlt(TPoint(0, 0), mContents); |
|
380 } |
|
381 } |
|
382 |
|
383 #endif // HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE |
|