diff -r 16d8024aca5e -r f7ac710697a9 src/hbservers/hbdevicedialogappserver/main.cpp --- a/src/hbservers/hbdevicedialogappserver/main.cpp Mon Apr 19 14:02:13 2010 +0300 +++ b/src/hbservers/hbdevicedialogappserver/main.cpp Mon May 03 12:48:33 2010 +0300 @@ -36,54 +36,125 @@ #include #include #include +#include +#include "hbddappfactorysymbian.h" #endif // Q_OS_SYMBIAN -// QApplication calls RProcess::Rendezvous() before server has been created. -// Semaphores are signaled when server initialization is done. #if defined (Q_OS_SYMBIAN) -static void SignalClientSemaphores() +class Lock { - // Initialisation complete, now signal client(s) - _LIT(KFindPattern, "hbdevdlgcli_?*"); - TFindSemaphore find(KFindPattern); - RSemaphore sema; - TFullName findResult; - while(find.Next(findResult) == KErrNone) { - sema.Open(find); - sema.Signal(); - sema.Close(); +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(KHbServerName); + TFullName name; + return findHbServer.Next(name) == KErrNone; +} + #endif // Q_OS_SYMBIAN +#define USE_LOCKER 1 int main(int arg, char *args[]) { INSTALL_MESSAGE_HANDLER #if defined (Q_OS_SYMBIAN) // Guard against starting multiple copies of the server - RSemaphore serverExistsSema; - _LIT(KSemaName, "hbdevdlgsrv"); - TInt error = serverExistsSema.CreateGlobal(KSemaName, 0); - if (error != KErrNone) { - RProcess::Rendezvous(error); - return error; + 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()) { + 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. + RProcess::Rendezvous(lockState == Lock::Reserved ? KErrAlreadyExists:KErrGeneral); + return KErrNone; + } + _LIT(KThreadName, "hbdevdlgsrvapp"); + RThread().RenameMe(KThreadName); // nicer panic info + + HbApplication app(deviceDialogAppFactory, arg, args, Hb::NoSplash); +#else // Q_OS_SYMBIAN + HbApplication app(arg, args); #endif // Q_OS_SYMBIAN - HbApplication app(arg, args, Hb::NoSplash); - - //QTranslator translator; - //QString lang_id = QLocale::system().name(); - //translator.load(path_to + "common_" + lang_id); - //app.installTranslator(&translator); - HbView* view = new HbView; view->hideItems(Hb::AllItems); view->setContentFullScreen(); - // Workaround to get device dialogs visible until transparency works - HbMainWindow mainWindow(0); //, Hb::WindowFlagTransparent); + HbMainWindow mainWindow(0, Hb::WindowFlagTransparent); + +#if defined (Q_OS_SYMBIAN) + CCoeControl *c = mainWindow.effectiveWinId(); + RWindow *rw = static_cast(c->DrawableWindow()); + rw->SetRequiredDisplayMode( EColor16MA ); + TInt err = rw->SetTransparencyAlphaChannel(); + if ( err == KErrNone ) { + rw->SetBackgroundColor(~0); + } +#endif // Q_OS_SYMBIAN HbTransparentWindow *transparentWindow = new HbTransparentWindow; HbStackedLayout *stackedLayout = new HbStackedLayout; @@ -92,32 +163,31 @@ mainWindow.addView(view); - HbDeviceDialogServer server; - server.setMainWindow(&mainWindow); - #if defined (Q_OS_SYMBIAN) CEikonEnv* env = CEikonEnv::Static(); - if ( env ) - { + if (env) { CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(env->WsSession()); 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("HbDeviceDialogAppServer")); wgName->SetAppUid(KNullUid); wgName->SetWindowGroupName(env->RootWin()); - CleanupStack::PopAndDestroy(); + CleanupStack::PopAndDestroy(); + } +#endif // Q_OS_SYMBIAN - } - SignalClientSemaphores(); + // HbApplication must be created before the server to have environment ready + HbDeviceDialogServer server; + server.setMainWindow(&mainWindow); + +#if defined (Q_OS_SYMBIAN) + // Server is created, client may connect + RProcess::Rendezvous(KErrNone); #endif // Q_OS_SYMBIAN int returnValue = app.exec(); -#if defined (Q_OS_SYMBIAN) - serverExistsSema.Close(); -#endif // Q_OS_SYMBIAN - UNINSTALL_MESSAGE_HANDLER return returnValue;