src/hbcore/gui/hbsplashscreen.cpp
changeset 3 11d3954df52a
parent 2 06ff229162e9
child 5 627c4a0fd0e7
equal deleted inserted replaced
2:06ff229162e9 3:11d3954df52a
    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) { }
   151   HbMainWindow after the window has become fully visible.
    87   HbMainWindow after the window has become fully visible.
   152  */
    88  */
   153 void HbSplashScreen::start(Flags flags)
    89 void HbSplashScreen::start(Flags flags)
   154 {
    90 {
   155     if (!splashScreen) {
    91     if (!splashScreen) {
   156         splashScreen =
    92         splashScreen = new HbSplashScreenGeneric;
   157 #ifdef HB_SPLASH_USE_SYMBIAN_LEGACY_SURFACE
       
   158             new HbSplashScreenSymbian
       
   159 #else
       
   160             new HbSplashScreenGeneric
       
   161 #endif
       
   162             ;
       
   163     }
    93     }
   164     splashScreen->start(flags | requestProps()->mSplashFlags);
    94     splashScreen->start(flags | requestProps()->mSplashFlags);
   165 }
    95 }
   166 
    96 
   167 /*!
    97 /*!
   242 void HbSplashScreen::setScreenId(const QString &screenId)
   172 void HbSplashScreen::setScreenId(const QString &screenId)
   243 {
   173 {
   244     requestProps()->mScreenId = screenId;
   174     requestProps()->mScreenId = screenId;
   245 }
   175 }
   246 
   176 
       
   177 const int auto_stop_interval = 10000; // 10 sec
       
   178 
   247 HbSplashScreenGeneric::HbSplashScreenGeneric()
   179 HbSplashScreenGeneric::HbSplashScreenGeneric()
   248     : QWidget(0, Qt::SplashScreen), mImageData(0)
   180     : QWidget(0, Qt::SplashScreen), mImageData(0)
   249 {
   181 {
   250 }
   182 }
   251 
   183 
   252 HbSplashScreenGeneric::~HbSplashScreenGeneric()
   184 HbSplashScreenGeneric::~HbSplashScreenGeneric()
   253 {
   185 {
   254     delete mImageData;
   186     if (mImageData) {
       
   187         qDebug("[hbsplash] destroying splash screen");
       
   188         delete mImageData;
       
   189     }
   255 }
   190 }
   256 
   191 
   257 void HbSplashScreenGeneric::release()
   192 void HbSplashScreenGeneric::release()
   258 {
   193 {
   259     delete this;
   194     delete this;
   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();
   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