src/hbservers/hbthemeserver/hbthemeserverapplication.cpp
changeset 2 06ff229162e9
child 3 11d3954df52a
equal deleted inserted replaced
1:f7ac710697a9 2:06ff229162e9
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     6 **
       
     7 ** This file is part of the HbServers module of the UI Extensions for Mobile.
       
     8 **
       
     9 ** GNU Lesser General Public License Usage
       
    10 ** This file may be used under the terms of the GNU Lesser General Public
       
    11 ** License version 2.1 as published by the Free Software Foundation and
       
    12 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    13 ** Please review the following information to ensure the GNU Lesser General
       
    14 ** Public License version 2.1 requirements will be met:
       
    15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    16 **
       
    17 ** In addition, as a special exception, Nokia gives you certain additional
       
    18 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    20 **
       
    21 ** If you have questions regarding the use of this file, please contact
       
    22 ** Nokia at developer.feedback@nokia.com.
       
    23 **
       
    24 ****************************************************************************/
       
    25 #include "hbthemeserverapplication_p.h"
       
    26 #include "hbthemeserver_p.h"
       
    27 #include "hbthemecommon_p.h"
       
    28 #include "hbtheme.h"
       
    29 
       
    30 #include <QWindowsStyle>
       
    31 #include <QLibrary>
       
    32 #include <QDebug>
       
    33 
       
    34 #if defined (Q_OS_SYMBIAN)
       
    35 #include "hbthemecommon_symbian_p.h"
       
    36 #include <eikenv.h>
       
    37 #include <apgwgnam.h>
       
    38 #endif
       
    39 
       
    40 static const QLatin1String APP_NAME("HbThemeServer");
       
    41 static const QLatin1String RESOURCE_LIB_NAME("HbCore");
       
    42 static const QLatin1String TEST_RESOURCE_LIB_NAME("HbTestResources");
       
    43 static const QLatin1String WIN32_DEBUG_SUFFIX("d");
       
    44 static const QLatin1String MAC_DEBUG_SUFFIX("_debug");
       
    45 static const QLatin1String STOP_MESSAGE("stop");
       
    46 
       
    47 bool HbThemeServerApplication::Options::help = false;
       
    48 bool HbThemeServerApplication::Options::start = false;
       
    49 bool HbThemeServerApplication::Options::stop = false;
       
    50 bool HbThemeServerApplication::Options::persistent = false;
       
    51 QString HbThemeServerApplication::Options::error = QString();
       
    52 
       
    53 HbThemeServerApplication::HbThemeServerApplication(int &argc, char *argv[]) :
       
    54     QtSingleApplication(argc, argv), server(0)
       
    55 {
       
    56     setApplicationName(APP_NAME);
       
    57 
       
    58 #ifdef QT_DEBUG
       
    59     //temporary solution until Hb specific style is ready
       
    60     setStyle(new QWindowsStyle);
       
    61 #endif // QT_DEBUG
       
    62 
       
    63 #if QT_VERSION >= 0x040601
       
    64     setAttribute(Qt::AA_S60DontConstructApplicationPanes);
       
    65 #endif // QT_VERSION
       
    66 
       
    67     // ignore command line arguments on Symbian
       
    68 #ifdef Q_OS_SYMBIAN
       
    69     Options::start = true;
       
    70     Options::persistent = true;
       
    71 #else
       
    72     QStringList args = arguments();
       
    73     args.removeFirst(); // ignore argv0
       
    74     const bool wasEmpty = args.isEmpty();
       
    75     const bool restart = args.removeAll(QLatin1String("-restart"));
       
    76     Options::start = args.removeAll(QLatin1String("-start")) || restart;
       
    77     Options::stop = args.removeAll(QLatin1String("-stop")) || restart;
       
    78     Options::persistent = args.removeAll(QLatin1String("-persistent"));
       
    79     Options::help = args.removeAll(QLatin1String("-help")) || args.removeAll(QLatin1String("-h")) || !args.isEmpty() || wasEmpty;
       
    80     if (!args.isEmpty()) {
       
    81         Options::error = tr("Unknown option(s): '%1'").arg(args.join(QLatin1String(" ")));
       
    82     }
       
    83 #endif // Q_OS_SYMBIAN
       
    84 }
       
    85 
       
    86 HbThemeServerApplication::~HbThemeServerApplication()
       
    87 {
       
    88     delete server;
       
    89 }
       
    90 
       
    91 bool HbThemeServerApplication::initialize()
       
    92 {
       
    93 #if defined (Q_OS_SYMBIAN)
       
    94     CEikonEnv * env = CEikonEnv::Static();
       
    95     if ( env ) {
       
    96         CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(env->WsSession());
       
    97         env->RootWin().SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); // avoid coming to foreground
       
    98         wgName->SetHidden(ETrue); // hides us from FSW and protects us from OOM FW etc.
       
    99         wgName->SetSystem(ETrue); // Allow only application with PowerManagement cap to shut us down    
       
   100         wgName->SetCaptionL(_L("HbThemeServer")); // TODO: use QCoreApplication::applicationName()
       
   101         wgName->SetAppUid(KNullUid);
       
   102         wgName->SetWindowGroupName(env->RootWin());
       
   103         CleanupStack::PopAndDestroy();
       
   104         RThread::RenameMe(_L("HbThemeServer")); // TODO: use QCoreApplication::applicationName()
       
   105     }
       
   106 #endif
       
   107 
       
   108     // as for theme initialization, an instance needs to be created before starting the server
       
   109     HbTheme::instance();
       
   110 
       
   111     // load resource libraries in order to make binary resources accessible
       
   112     bool result = loadLibrary(RESOURCE_LIB_NAME);
       
   113 #ifdef HB_DEVELOPER
       
   114     loadLibrary(TEST_RESOURCE_LIB_NAME);
       
   115 #endif
       
   116     return result;
       
   117 }
       
   118 
       
   119 int HbThemeServerApplication::exec()
       
   120 {
       
   121     if (!server) {
       
   122         server = new HbThemeServer;
       
   123     }
       
   124 
       
   125     if (server->startServer()) {
       
   126 #if !defined(Q_OS_SYMBIAN) && defined(QT_DEBUG)
       
   127         server->showMinimized();
       
   128 #endif
       
   129         return QtSingleApplication::exec();
       
   130     }
       
   131 
       
   132     return EXIT_FAILURE;
       
   133 }
       
   134 
       
   135 void HbThemeServerApplication::stop()
       
   136 {
       
   137 #ifndef Q_OS_SYMBIAN
       
   138     sendMessage(STOP_MESSAGE);
       
   139 #endif // Q_OS_SYMBIAN
       
   140 }
       
   141 
       
   142 bool HbThemeServerApplication::loadLibrary(const QString &name)
       
   143 {
       
   144     // To load resources embedded in hb library
       
   145     QLibrary library(name);
       
   146     bool result = library.load();
       
   147 
       
   148     if (!result) {
       
   149         // Library may not be loaded, if it was built in debug mode and the name in debug mode is
       
   150         // different, change the name to debug version in that scenario
       
   151         QString alternateName = name;
       
   152 #ifdef Q_OS_WIN32
       
   153         alternateName += WIN32_DEBUG_SUFFIX;
       
   154 #elif defined(Q_OS_MAC)
       
   155         alternateName += MAC_DEBUG_SUFFIX;
       
   156 #endif
       
   157         // On symbian library name in debug mode is same as that in release mode,
       
   158         // so no need to do anything for that
       
   159         library.setFileName(alternateName);
       
   160         result = library.load();
       
   161     }
       
   162 #ifdef THEME_SERVER_TRACES
       
   163     if (result) {
       
   164         qDebug() << "HbThemeServerApplication::loadLibrary(): loaded library " << name;
       
   165     }
       
   166     else {
       
   167         qDebug() << "HbThemeServerApplication::loadLibrary(): could not load library " << name;
       
   168     }
       
   169 #endif // THEME_SERVER_TRACES
       
   170 
       
   171     return result;
       
   172 }
       
   173 
       
   174 void HbThemeServerApplication::receiveMessage(const QString &message)
       
   175 {
       
   176     if (!server)
       
   177         return;
       
   178 
       
   179     if (message == STOP_MESSAGE) {
       
   180         server->stopServer();
       
   181         quit();
       
   182     }
       
   183 }
       
   184 
       
   185 bool HbThemeServerApplication::acquireLock() {
       
   186 #ifdef Q_OS_SYMBIAN
       
   187     // Guard against starting multiple copies of the server
       
   188     Lock lock;
       
   189     Lock::State lockState;
       
   190     for(;;) {
       
   191         lockState = lock.acquire();
       
   192         if (lockState == Lock::Acquired) {
       
   193             break;
       
   194         } else if (lockState == Lock::Reserved) {
       
   195             // Process may be starting, wait for server object to be created
       
   196             if (Lock::serverExists()) {
       
   197 #ifdef THEME_SERVER_TRACES
       
   198         qDebug() << "HbThemeServer::main: serverExists!!!";
       
   199 #endif
       
   200                 break;
       
   201             } else {
       
   202                 const TInt KTimeout = 100000; // 100 ms
       
   203                 User::After(KTimeout);
       
   204             }
       
   205         } else {
       
   206             break;
       
   207         }
       
   208     }
       
   209     
       
   210     if (lockState != Lock::Acquired) {
       
   211         // With KErrAlreadyExists client should try to connect, otherwise bail out.
       
   212 #ifdef THEME_SERVER_TRACES
       
   213         qDebug() << "HbThemeServer::main: Lock not acquired!!!";
       
   214 #endif
       
   215         RProcess::Rendezvous(lockState == Lock::Reserved ? KErrAlreadyExists : KErrGeneral);
       
   216     }
       
   217 
       
   218     return (lockState == Lock::Acquired);
       
   219 #else
       
   220     return true;
       
   221 #endif
       
   222 
       
   223 
       
   224 }
       
   225 
       
   226 
       
   227 #ifdef Q_OS_SYMBIAN
       
   228 Lock::Lock()
       
   229 {
       
   230     // Using a file for interprocess lock
       
   231     const int NumMessageSlots = 1;
       
   232     if (mFs.Connect(NumMessageSlots) == KErrNone) {
       
   233         mFs.CreatePrivatePath(EDriveC);
       
   234         if (mFs.SetSessionToPrivate(EDriveC) == KErrNone) {
       
   235             _LIT(KFileName, "lockFile");
       
   236             const TUint mode = EFileShareReadersOrWriters;
       
   237             if (mFile.Create(mFs, KFileName, mode) == KErrAlreadyExists) {
       
   238                 mFile.Open(mFs, KFileName, mode);
       
   239             }
       
   240         }
       
   241     }
       
   242 }
       
   243 
       
   244 // Try to acquire lock
       
   245 Lock::State Lock::acquire()
       
   246 {
       
   247     State state = Error;
       
   248     // If process holding the lock crashes, file server releases the lock
       
   249     if (mFile.SubSessionHandle()) {
       
   250         TInt error = mFile.Lock(0, 1);
       
   251         if (error == KErrNone) {
       
   252             state = Acquired;
       
   253         } else if (error == KErrLocked) {
       
   254             state = Reserved;
       
   255         }
       
   256     }
       
   257     return state;
       
   258 }
       
   259 
       
   260 // Check if Symbian server exists
       
   261 bool Lock::serverExists()
       
   262 {
       
   263     TFindServer findHbServer(KThemeServerName);
       
   264     TFullName name;
       
   265     return findHbServer.Next(name) == KErrNone;
       
   266 }
       
   267 
       
   268 #endif