21 ** If you have questions regarding the use of this file, please contact |
21 ** If you have questions regarding the use of this file, please contact |
22 ** Nokia at developer.feedback@nokia.com. |
22 ** Nokia at developer.feedback@nokia.com. |
23 ** |
23 ** |
24 ****************************************************************************/ |
24 ****************************************************************************/ |
25 |
25 |
26 #include <QApplication> |
26 #include "hbthemeserverapplication_p.h" |
27 #include <QLibrary> |
27 #include <QTextStream> |
28 #include <QDebug> |
28 #include <cstdlib> |
29 |
29 |
30 #include "hbthemeserver_p.h" |
30 void showHelp(const QString &argv0, const QString &error = QString()) |
31 #include "hbthemecommon_p.h" |
|
32 #include "hbtheme.h" |
|
33 #if defined (Q_OS_SYMBIAN) |
|
34 #include "hbthemecommon_symbian_p.h" |
|
35 #include <eikenv.h> |
|
36 #include <apgwgnam.h> |
|
37 #endif |
|
38 #include <qtsingleapplication.h> |
|
39 #include <QWindowsStyle> |
|
40 |
|
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 |
|
46 #ifdef Q_OS_SYMBIAN |
|
47 class Lock |
|
48 { |
31 { |
49 public: |
32 QTextStream qerr(stderr); |
50 enum State { |
33 qerr << "Hb Theme Server" << endl; |
51 Reserved, |
34 if (!error.isEmpty()) { |
52 Acquired, |
35 qerr << argv0 << ": " << error << endl; |
53 Error |
|
54 }; |
|
55 Lock(); |
|
56 ~Lock(){close();} |
|
57 void close(){mFile.Close(); mFs.Close();} |
|
58 State acquire(); |
|
59 static bool serverExists(); |
|
60 |
|
61 private: |
|
62 RFs mFs; |
|
63 RFile mFile; |
|
64 }; |
|
65 |
|
66 Lock::Lock() |
|
67 { |
|
68 // Using a file for interprocess lock |
|
69 const int NumMessageSlots = 1; |
|
70 if (mFs.Connect(NumMessageSlots) == KErrNone) { |
|
71 mFs.CreatePrivatePath(EDriveC); |
|
72 if (mFs.SetSessionToPrivate(EDriveC) == KErrNone) { |
|
73 _LIT(KFileName, "lockFile"); |
|
74 const TUint mode = EFileShareReadersOrWriters; |
|
75 if (mFile.Create(mFs, KFileName, mode) == KErrAlreadyExists) { |
|
76 mFile.Open(mFs, KFileName, mode); |
|
77 } |
|
78 } |
|
79 } |
36 } |
80 } |
37 qerr << "Usage: " << argv0 << " [options]" << endl; |
81 |
38 qerr << endl; |
82 // Try to acquire lock |
39 qerr << "Options:" << endl; |
83 Lock::State Lock::acquire() |
40 qerr << " -start start a new server" << endl; |
84 { |
41 qerr << " -restart same as -stop -start" << endl; |
85 State state = Error; |
42 qerr << " -stop stop an existing server instance" << endl; |
86 // If process holding the lock crashes, file server releases the lock |
43 qerr << " -persistent keep server running when the last client disconnects" << endl; |
87 if (mFile.SubSessionHandle()) { |
44 qerr << " -h, -help display this information" << endl; |
88 TInt error = mFile.Lock(0, 1); |
|
89 if (error == KErrNone) { |
|
90 state = Acquired; |
|
91 } else if (error == KErrLocked) { |
|
92 state = Reserved; |
|
93 } |
|
94 } |
|
95 return state; |
|
96 } |
|
97 |
|
98 // Check if Symbian server exists |
|
99 bool Lock::serverExists() |
|
100 { |
|
101 TFindServer findHbServer(KThemeServerName); |
|
102 TFullName name; |
|
103 return findHbServer.Next(name) == KErrNone; |
|
104 } |
|
105 |
|
106 #endif |
|
107 /* |
|
108 This function loads library which keeps resources of default theme |
|
109 */ |
|
110 bool loadResourceLibrary(QString resourceLibName) |
|
111 { |
|
112 bool loadSuccess; |
|
113 // To load resources embedded in hb library |
|
114 QLibrary hbLib(resourceLibName); |
|
115 loadSuccess = hbLib.load(); |
|
116 |
|
117 if ( !loadSuccess ) { |
|
118 // Library may not be loaded, if it was built in debug mode and the name in debug mode is |
|
119 // different, change the name to debug version in that scenario |
|
120 #ifdef Q_OS_WIN32 |
|
121 resourceLibName += WIN32_DEBUG_SUFFIX; |
|
122 #elif defined(Q_OS_MAC) |
|
123 resourceLibName += MAC_DEBUG_SUFFIX; |
|
124 #endif |
|
125 // On symbian library name in debug mode is same as that in release mode, |
|
126 // so no need to do anything for that |
|
127 hbLib.setFileName(resourceLibName); |
|
128 loadSuccess = hbLib.load(); |
|
129 } |
|
130 #ifdef THEME_SERVER_TRACES |
|
131 if (loadSuccess) { |
|
132 qDebug() << "Loaded library " << resourceLibName; |
|
133 } |
|
134 else { |
|
135 qDebug() << "Could not load library " << resourceLibName; |
|
136 } |
|
137 #endif // THEME_SERVER_TRACES |
|
138 |
|
139 return loadSuccess; |
|
140 } |
45 } |
141 |
46 |
142 int main(int argc, char *argv[]) |
47 int main(int argc, char *argv[]) |
143 { |
48 { |
144 #ifdef QT_DEBUG |
49 if(!HbThemeServerApplication::acquireLock()) { |
145 //temporary solution until Hb specific style is ready |
|
146 QApplication::setStyle( new QWindowsStyle ); |
|
147 #endif // QT_DEBUG |
|
148 #if QT_VERSION >= 0x040601 |
|
149 QApplication::setAttribute(Qt::AA_S60DontConstructApplicationPanes); |
|
150 #endif // QT_VERSION |
|
151 #ifdef THEME_SERVER_TRACES |
|
152 qDebug() << "HbThemeServer::main: START!!!"; |
|
153 #endif |
|
154 #ifdef Q_OS_SYMBIAN |
|
155 // Guard against starting multiple copies of the server |
|
156 Lock lock; |
|
157 Lock::State lockState; |
|
158 for(;;) { |
|
159 lockState = lock.acquire(); |
|
160 if (lockState == Lock::Acquired) { |
|
161 break; |
|
162 } else if (lockState == Lock::Reserved) { |
|
163 // Process may be starting, wait for server object to be created |
|
164 if (Lock::serverExists()) { |
|
165 #ifdef THEME_SERVER_TRACES |
|
166 qDebug() << "HbThemeServer::main: serverExists!!!"; |
|
167 #endif |
|
168 break; |
|
169 } else { |
|
170 const TInt KTimeout = 100000; // 100 ms |
|
171 User::After(KTimeout); |
|
172 } |
|
173 } else { |
|
174 break; |
|
175 } |
|
176 } |
|
177 if (lockState != Lock::Acquired) { |
|
178 // With KErrAlreadyExists client should try to connect, otherwise bail out. |
|
179 #ifdef THEME_SERVER_TRACES |
|
180 qDebug() << "HbThemeServer::main: Lock not acquired!!!"; |
|
181 #endif |
|
182 RProcess::Rendezvous(lockState == Lock::Reserved ? KErrAlreadyExists:KErrGeneral); |
|
183 return KErrNone; |
|
184 } |
|
185 #endif // Q_OS_SYMBIAN |
|
186 #ifdef THEME_SERVER_TRACES |
|
187 qDebug() << "HbThemeServer::main: start construction QtSingleApplication!!!"; |
|
188 #endif |
|
189 QtSingleApplication app(argc, argv ); |
|
190 |
|
191 if (app.isRunning()) { |
|
192 #ifdef THEME_SERVER_TRACES |
|
193 qDebug() << "HbThemeServer::main: first instance already running!!!"; |
|
194 #endif |
|
195 return 0; |
50 return 0; |
196 } |
51 } |
|
52 |
|
53 HbThemeServerApplication app(argc, argv); |
197 |
54 |
198 #ifdef THEME_SERVER_TRACES |
55 if (HbThemeServerApplication::Options::help) { |
199 qDebug() << "HbThemeServer::main: I'm first instance!!!"; |
56 showHelp(argv[0], HbThemeServerApplication::Options::error); |
200 #endif |
57 return EXIT_SUCCESS; |
201 |
|
202 #if defined (Q_OS_SYMBIAN) |
|
203 CEikonEnv * env = CEikonEnv::Static(); |
|
204 if ( env ) { |
|
205 CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(env->WsSession()); |
|
206 env->RootWin().SetOrdinalPosition(0, ECoeWinPriorityNeverAtFront); // avoid coming to foreground |
|
207 wgName->SetHidden(ETrue); // hides us from FSW and protects us from OOM FW etc. |
|
208 wgName->SetSystem(ETrue); // Allow only application with PowerManagement cap to shut us down |
|
209 wgName->SetCaptionL(_L("HbThemeServer")); |
|
210 wgName->SetAppUid(KNullUid); |
|
211 wgName->SetWindowGroupName(env->RootWin()); |
|
212 CleanupStack::PopAndDestroy(); |
|
213 RThread::RenameMe(_L("HbThemeServer")); |
|
214 } |
58 } |
215 #endif |
|
216 HbTheme::instance(); //for theme initialization, instance needs to be created before starting the server. |
|
217 loadResourceLibrary(RESOURCE_LIB_NAME); |
|
218 #ifdef HB_DEVELOPER |
|
219 loadResourceLibrary(TEST_RESOURCE_LIB_NAME); |
|
220 #endif |
|
221 |
59 |
222 HbThemeServer server; |
60 if (HbThemeServerApplication::Options::stop) { |
|
61 app.stop(); |
|
62 } |
223 |
63 |
224 bool success = server.startServer(); |
64 if (app.isRunning() || !HbThemeServerApplication::Options::start) { |
225 |
65 return EXIT_SUCCESS; |
226 if ( !success ) { |
|
227 #ifdef THEME_SERVER_TRACES |
|
228 qDebug() << "HbThemeServer::main: server not started!!!"; |
|
229 #endif |
|
230 return -1; |
|
231 } |
66 } |
232 |
|
233 #ifdef THEME_SERVER_TRACES |
|
234 qDebug() << "HbThemeServer::main: server started!!!"; |
|
235 #endif |
|
236 |
67 |
237 #ifndef Q_OS_SYMBIAN |
68 if (app.initialize()) { |
238 #ifdef QT_DEBUG |
69 return app.exec(); |
239 server.showMinimized(); |
70 } |
240 #endif |
|
241 #endif // Q_OS_SYMBIAN |
|
242 |
71 |
243 int result = app.exec(); |
72 return EXIT_FAILURE; |
244 #ifdef THEME_SERVER_TRACES |
|
245 qDebug() << "HbThemeServer::main: out from exec, with result code: " << result; |
|
246 #endif |
|
247 return result; |
|
248 } |
73 } |