src/hbservers/hbthemeserver/main.cpp
changeset 1 f7ac710697a9
parent 0 16d8024aca5e
child 2 06ff229162e9
--- a/src/hbservers/hbthemeserver/main.cpp	Mon Apr 19 14:02:13 2010 +0300
+++ b/src/hbservers/hbthemeserver/main.cpp	Mon May 03 12:48:33 2010 +0300
@@ -29,7 +29,9 @@
 
 #include "hbthemeserver_p.h"
 #include "hbthemecommon_p.h"
+#include "hbtheme.h"
 #if defined (Q_OS_SYMBIAN)
+#include "hbthemecommon_symbian_p.h"
 #include <eikenv.h>
 #include <apgwgnam.h>
 #endif
@@ -41,6 +43,67 @@
 static const QLatin1String WIN32_DEBUG_SUFFIX("d");
 static const QLatin1String MAC_DEBUG_SUFFIX("_debug");
 
+#ifdef Q_OS_SYMBIAN
+class Lock
+{
+public:
+    enum State {
+        Reserved,
+        Acquired,
+        Error
+    };
+    Lock();
+    ~Lock(){close();}
+    void close(){mFile.Close(); mFs.Close();}
+    State acquire();
+    static bool serverExists();
+
+private:
+    RFs mFs;
+    RFile mFile;
+};
+
+Lock::Lock()
+{
+    // Using a file for interprocess lock
+    const int NumMessageSlots = 1;
+    if (mFs.Connect(NumMessageSlots) == KErrNone) {
+        mFs.CreatePrivatePath(EDriveC);
+        if (mFs.SetSessionToPrivate(EDriveC) == KErrNone) {
+            _LIT(KFileName, "lockFile");
+            const TUint mode = EFileShareReadersOrWriters;
+            if (mFile.Create(mFs, KFileName, mode) == KErrAlreadyExists) {
+                mFile.Open(mFs, KFileName, mode);
+            }
+        }
+    }
+}
+
+// Try to acquire lock
+Lock::State Lock::acquire()
+{
+    State state = Error;
+    // If process holding the lock crashes, file server releases the lock
+    if (mFile.SubSessionHandle()) {
+        TInt error = mFile.Lock(0, 1);
+        if (error == KErrNone) {
+            state = Acquired;
+        } else if (error == KErrLocked) {
+            state = Reserved;
+        }
+    }
+    return state;
+}
+
+// Check if Symbian server exists
+bool Lock::serverExists()
+{
+    TFindServer findHbServer(KThemeServerName);
+    TFullName name;
+    return findHbServer.Next(name) == KErrNone;
+}
+
+#endif
 /* 
     This function loads library which keeps resources of default theme
 */
@@ -81,38 +144,105 @@
 #ifdef QT_DEBUG
     //temporary solution until Hb specific style is ready
     QApplication::setStyle( new QWindowsStyle );
+#endif // QT_DEBUG
+#if QT_VERSION >= 0x040601
+    QApplication::setAttribute(Qt::AA_S60DontConstructApplicationPanes);
+#endif // QT_VERSION
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: START!!!";
 #endif
-	QtSingleApplication  app( argc, argv );
-	if (app.sendMessage("Am Alive"))
-         return 0;
-    
-    loadResourceLibrary(RESOURCE_LIB_NAME);
-#ifdef BUILD_HB_INTERNAL
-    loadResourceLibrary(TEST_RESOURCE_LIB_NAME);
+#ifdef Q_OS_SYMBIAN
+    // Guard against starting multiple copies of the server
+    Lock lock;
+    Lock::State lockState;
+    for(;;) {
+        lockState = lock.acquire();
+        if (lockState == Lock::Acquired) {
+            break;
+        } else if (lockState == Lock::Reserved) {
+            // Process may be starting, wait for server object to be created
+            if (Lock::serverExists()) {
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: serverExists!!!";
 #endif
-    HbThemeServer server;
-    bool success = server.startServer();
-    if ( !success ) {
-        return -1;
+                break;
+            } else {
+                const TInt KTimeout = 100000; // 100 ms
+                User::After(KTimeout);
+            }
+        } else {
+            break;
+        }
+    }
+    if (lockState != Lock::Acquired) {
+        // With KErrAlreadyExists client should try to connect, otherwise bail out.
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: Lock not acquired!!!";
+#endif
+        RProcess::Rendezvous(lockState == Lock::Reserved ? KErrAlreadyExists:KErrGeneral);
+        return KErrNone;
+    }
+#endif // Q_OS_SYMBIAN
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: start construction QtSingleApplication!!!";
+#endif
+    QtSingleApplication  app(argc, argv );
+
+    if (app.isRunning()) {
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: first instance already running!!!";
+#endif
+        return 0;
     }
 
+#ifdef THEME_SERVER_TRACES
+    qDebug() << "HbThemeServer::main: I'm first instance!!!";
+#endif
+        
 #if defined (Q_OS_SYMBIAN)
     CEikonEnv * env = CEikonEnv::Static();
     if ( env ) {
         CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(env->WsSession());
+        env->RootWin().SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); // avoid coming to foreground
         wgName->SetHidden(ETrue); // hides us from FSW and protects us from OOM FW etc.
         wgName->SetSystem(ETrue); // Allow only application with PowerManagement cap to shut us down    
         wgName->SetCaptionL(_L("HbThemeServer"));
         wgName->SetAppUid(KNullUid);
-        RWindowGroup &rootWindowGroup = env->RootWin();
-        wgName->SetWindowGroupName(rootWindowGroup);
-        rootWindowGroup.SetOrdinalPosition(-1, ECoeWinPriorityNormal); //move to background.        
+        wgName->SetWindowGroupName(env->RootWin());
         CleanupStack::PopAndDestroy();
+        RThread::RenameMe(_L("HbThemeServer"));
     }
-#elif defined(QT_DEBUG)
+#endif
+    HbTheme::instance(); //for theme initialization, instance needs to be created before starting the server.
+    loadResourceLibrary(RESOURCE_LIB_NAME);
+#ifdef HB_DEVELOPER
+    loadResourceLibrary(TEST_RESOURCE_LIB_NAME);
+#endif
+
+    HbThemeServer server;
+
+    bool success = server.startServer();
+    
+    if ( !success ) {
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: server not started!!!";
+#endif
+        return -1;
+    }
+    
+#ifdef THEME_SERVER_TRACES
+    qDebug() << "HbThemeServer::main: server started!!!";
+#endif
+
+#ifndef Q_OS_SYMBIAN
+#ifdef QT_DEBUG
     server.showMinimized();
 #endif
+#endif // Q_OS_SYMBIAN
 
-    return app.exec();
+    int result = app.exec();
+#ifdef THEME_SERVER_TRACES
+        qDebug() << "HbThemeServer::main: out from exec, with result code: " << result;
+#endif
+    return result; 
 }
-