|
1 // NotifierProxy.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #include <fshell/common.mmh> |
|
13 #include <e32notif.h> |
|
14 #include <e32ver.h> |
|
15 |
|
16 #ifndef FSHELL_WSERV_SUPPORT |
|
17 |
|
18 EXPORT_C TInt StartNotifierProxyThreadFunction(TAny*) |
|
19 { |
|
20 return KErrNotSupported; |
|
21 } |
|
22 |
|
23 EXPORT_C TInt ShutdownProxyNotifier() |
|
24 { |
|
25 return KErrNotSupported; |
|
26 } |
|
27 |
|
28 EXPORT_C TBool NotifierProxyIsRunning() |
|
29 { |
|
30 return EFalse; |
|
31 } |
|
32 |
|
33 #else |
|
34 |
|
35 #include "NotifierProxy.h" |
|
36 #include <fshell/clogger.h> |
|
37 #include "utils.h" |
|
38 |
|
39 _LIT(KRealNotifierServerName, "RealNtfyr"); |
|
40 _LIT8(KRealNotifierServerName8, "RealNtfyr"); |
|
41 |
|
42 #define LeaveIfErr(_err, _args...) \ |
|
43 do \ |
|
44 { \ |
|
45 if (_err < 0) \ |
|
46 { \ |
|
47 RClogger::Slog(_args); \ |
|
48 User::Leave(_err); \ |
|
49 } \ |
|
50 } \ |
|
51 while (0) |
|
52 |
|
53 const TInt KShutdownProxy = 1000; |
|
54 const TInt KPingProxy = 1001; |
|
55 const TInt KInfoPrintTime = 2000000; // 2 seconds |
|
56 |
|
57 TInt RRealNotifier::Connect() |
|
58 { |
|
59 return CreateSession(KRealNotifierServerName, TVersion(KNotifierMajorVersionNumber,KNotifierMinorVersionNumber,KNotifierBuildVersionNumber),-1); |
|
60 } |
|
61 |
|
62 CNotifierProxyServer::CNotifierProxyServer() |
|
63 : CServer2(0, ESharableSessions) |
|
64 { |
|
65 } |
|
66 |
|
67 void CNotifierProxyServer::ConstructL() |
|
68 { |
|
69 //__DEBUGGER(); |
|
70 SetupWindowL(); |
|
71 TFontSpec spec(_L("Roman"), 12); |
|
72 LeaveIfErr(iScreenDevice->GetNearestFontInPixels(iFont, spec), _L("Couldn't find a suitable font")); |
|
73 iPeriodic = CPeriodic::NewL(CActive::EPriorityStandard); |
|
74 iText.ReserveL(8); |
|
75 iUndertaker = new(ELeave) CPanicDialogWatcher(*this); |
|
76 iUndertaker->ConstructL(); |
|
77 |
|
78 StartL(KRealNotifierServerName); // We start with the name of what we're going to rename the real notifier to, this way we ensure that the following code can only be run by one thread at once |
|
79 |
|
80 RMemoryAccess::LoadDriver(); |
|
81 LeaveIfErr(iMemAccess.Open(), _L("Couldn't open mem access")); |
|
82 |
|
83 TServerKernelInfoBuf buf; |
|
84 TInt err = iMemAccess.GetObjectInfo(EServer, _L("!Notifier"), buf); |
|
85 User::LeaveIfError(err); |
|
86 TUint8* realServer = buf().iAddressOfKernelObject; |
|
87 err = iMemAccess.GetObjectInfo(EServer, KRealNotifierServerName, buf); |
|
88 User::LeaveIfError(err); |
|
89 TUint8* myServer = buf().iAddressOfKernelObject; |
|
90 |
|
91 // Should really have some kind of swap operation here... |
|
92 iMemAccess.InPlaceObjectRename(EServer, realServer, KRealNotifierServerName8); |
|
93 iMemAccess.InPlaceObjectRename(EServer, myServer, _L8("!Notifier")); |
|
94 iProxying = ETrue; |
|
95 } |
|
96 |
|
97 CNotifierProxyServer::~CNotifierProxyServer() |
|
98 { |
|
99 delete iRedrawer; |
|
100 //delete iAnimationTimer; |
|
101 //delete iBitmap; |
|
102 //delete iDsa; |
|
103 delete iScreenDevice; |
|
104 delete iGc; |
|
105 iWin.Close(); |
|
106 iWg.Close(); |
|
107 iWs.Close(); |
|
108 delete iPeriodic; |
|
109 iText.ResetAndDestroy(); |
|
110 delete iUndertaker; |
|
111 |
|
112 if (iProxying) |
|
113 { |
|
114 TServerKernelInfoBuf buf; |
|
115 TInt err = iMemAccess.GetObjectInfo(EServer, KRealNotifierServerName, buf); |
|
116 if (!err) |
|
117 { |
|
118 TUint8* realServer = buf().iAddressOfKernelObject; |
|
119 iMemAccess.InPlaceObjectRename(EServer, realServer, _L8("!Notifier")); |
|
120 // Temporarily both us and the real server will have name !Notifier. When we finish destructing, we'll clean up and the system should be back in the state it was |
|
121 } |
|
122 } |
|
123 iMemAccess.Close(); |
|
124 RMemoryAccess::CloseDriver(); |
|
125 } |
|
126 |
|
127 CSession2* CNotifierProxyServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const |
|
128 { |
|
129 CNotifierProxySession* res = new(ELeave) CNotifierProxySession(); |
|
130 CleanupStack::PushL(res); |
|
131 res->ConstructL(); |
|
132 CleanupStack::Pop(res); |
|
133 return res; |
|
134 } |
|
135 |
|
136 void CNotifierProxySession::ConstructL() |
|
137 { |
|
138 User::LeaveIfError(iRealNotifier.Connect()); |
|
139 } |
|
140 |
|
141 CNotifierProxyServer& CNotifierProxySession::Server() |
|
142 { |
|
143 return *const_cast<CNotifierProxyServer*>(static_cast<const CNotifierProxyServer*>(CSession2::Server())); |
|
144 } |
|
145 |
|
146 const CNotifierProxyServer& CNotifierProxySession::Server() const |
|
147 { |
|
148 return *static_cast<const CNotifierProxyServer*>(CSession2::Server()); |
|
149 } |
|
150 |
|
151 void CNotifierProxySession::ServiceL(const RMessage2 &aMessage) |
|
152 { |
|
153 switch (aMessage.Function()) |
|
154 { |
|
155 case ENotifierInfoPrint: |
|
156 { |
|
157 //__DEBUGGER(); |
|
158 RBuf buf; |
|
159 CleanupClosePushL(buf); |
|
160 buf.CreateL(aMessage.GetDesLengthL(0)); |
|
161 aMessage.ReadL(0, buf); |
|
162 RThread client; |
|
163 TInt err = aMessage.Client(client); |
|
164 TUint clientId = 0; |
|
165 if (!err) clientId = client.Id(); |
|
166 client.Close(); |
|
167 Server().InfoPrint(buf, clientId); |
|
168 CleanupStack::PopAndDestroy(&buf); |
|
169 aMessage.Complete(KErrNone); |
|
170 break; |
|
171 } |
|
172 case EStartNotifier: |
|
173 { |
|
174 TUid notifierUid = TUid::Uid(aMessage.Int0()); |
|
175 RBuf8 buf, responseBuf; |
|
176 CleanupClosePushL(buf); |
|
177 buf.CreateL(aMessage.GetDesLengthL(1)); |
|
178 aMessage.ReadL(1, buf); |
|
179 TInt res = KErrNone; |
|
180 if (aMessage.Ptr2()) |
|
181 { |
|
182 CleanupClosePushL(responseBuf); |
|
183 responseBuf.CreateL(aMessage.GetDesMaxLengthL(2)); |
|
184 res = iRealNotifier.StartNotifier(notifierUid, buf, responseBuf); |
|
185 if (res == KErrNone || responseBuf.Length()) |
|
186 { |
|
187 aMessage.WriteL(2, responseBuf); |
|
188 } |
|
189 CleanupStack::PopAndDestroy(&responseBuf); |
|
190 } |
|
191 else |
|
192 { |
|
193 res = iRealNotifier.StartNotifier(notifierUid, buf); |
|
194 } |
|
195 CleanupStack::PopAndDestroy(&buf); |
|
196 aMessage.Complete(res); |
|
197 break; |
|
198 } |
|
199 case EStartNotifierFromSpecifiedDll: |
|
200 case EStartNotifierFromSpecifiedDllAndGetResponse: |
|
201 aMessage.Complete(KErrNotSupported); // This is what the docs say - god knows why the client bothers to pass it through |
|
202 break; |
|
203 case ECancelNotifier: |
|
204 { |
|
205 TUid notifierUid = TUid::Uid(aMessage.Int0()); |
|
206 TInt res = iRealNotifier.CancelNotifier(notifierUid); |
|
207 aMessage.Complete(res); |
|
208 break; |
|
209 } |
|
210 case EUpdateNotifier: |
|
211 { |
|
212 TUid notifierUid = TUid::Uid(aMessage.Int0()); |
|
213 RBuf8 buf, responseBuf; |
|
214 CleanupClosePushL(buf); |
|
215 buf.CreateL(aMessage.GetDesLengthL(1)); |
|
216 aMessage.ReadL(1, buf); |
|
217 CleanupClosePushL(responseBuf); |
|
218 responseBuf.CreateL(aMessage.GetDesMaxLengthL(2)); |
|
219 TInt res = iRealNotifier.UpdateNotifier(notifierUid, buf, responseBuf); |
|
220 if (res == KErrNone || responseBuf.Length()) |
|
221 { |
|
222 aMessage.WriteL(2, responseBuf); |
|
223 } |
|
224 CleanupStack::PopAndDestroy(&responseBuf); |
|
225 CleanupStack::PopAndDestroy(&buf); |
|
226 aMessage.Complete(res); |
|
227 break; |
|
228 } |
|
229 case EUpdateNotifierAndGetResponse: |
|
230 case EStartNotifierAndGetResponse: |
|
231 case ENotifierNotify: |
|
232 { |
|
233 CAsyncWaiter* waiter = new(ELeave) CAsyncWaiter(iRealNotifier, aMessage); |
|
234 waiter->ForwardMessageL(); |
|
235 break; |
|
236 } |
|
237 case ENotifierNotifyCancel: |
|
238 iRealNotifier.NotifyCancel(); |
|
239 aMessage.Complete(KErrNone); |
|
240 break; |
|
241 case KShutdownProxy: |
|
242 CActiveScheduler::Stop(); |
|
243 break; |
|
244 case KPingProxy: |
|
245 aMessage.Complete(KErrNone); |
|
246 break; |
|
247 default: |
|
248 __DEBUGGER(); |
|
249 aMessage.Complete(KErrNotSupported); |
|
250 } |
|
251 } |
|
252 |
|
253 void CNotifierProxySession::Disconnect(const RMessage2 &aMessage) |
|
254 { |
|
255 iRealNotifier.Close(); |
|
256 //TODO Need to wait for any CAsyncWaiters to be completed? If so, do it here and defer the super call until that time |
|
257 CSession2::Disconnect(aMessage); |
|
258 } |
|
259 |
|
260 CAsyncWaiter::CAsyncWaiter(RRealNotifier& aRealNotifier, const RMessage2& aMessage) |
|
261 : CActive(CActive::EPriorityStandard), iRealNotifier(aRealNotifier), iMsg(aMessage) |
|
262 { |
|
263 CActiveScheduler::Add(this); |
|
264 } |
|
265 |
|
266 CAsyncWaiter::~CAsyncWaiter() |
|
267 { |
|
268 iBuf.Close(); |
|
269 iWideBuf.Close(); |
|
270 iResponseBuf.Close(); |
|
271 } |
|
272 |
|
273 void CAsyncWaiter::ForwardMessageL() |
|
274 { |
|
275 switch (iMsg.Function()) |
|
276 { |
|
277 case EUpdateNotifierAndGetResponse: |
|
278 { |
|
279 TUid notifierUid = TUid::Uid(iMsg.Int0()); |
|
280 iBuf.CreateL(iMsg.GetDesLengthL(1)); |
|
281 iMsg.ReadL(1, iBuf); |
|
282 iResponseBuf.CreateL(iMsg.GetDesMaxLengthL(2)); |
|
283 iRealNotifier.UpdateNotifierAndGetResponse(iStatus, notifierUid, iBuf, iResponseBuf); |
|
284 SetActive(); |
|
285 break; |
|
286 } |
|
287 case EStartNotifierAndGetResponse: |
|
288 { |
|
289 TUid notifierUid = TUid::Uid(iMsg.Int0()); |
|
290 iBuf.CreateL(iMsg.GetDesLengthL(1)); |
|
291 iMsg.ReadL(1, iBuf); |
|
292 iResponseBuf.CreateL(iMsg.GetDesMaxLengthL(2)); |
|
293 iRealNotifier.StartNotifierAndGetResponse(iStatus, notifierUid, iBuf, iResponseBuf); |
|
294 SetActive(); |
|
295 break; |
|
296 } |
|
297 case ENotifierNotify: |
|
298 { |
|
299 // iWideBuf is the combined buffer |
|
300 iWideBuf.CreateL(iMsg.GetDesLengthL(1)); |
|
301 iMsg.ReadL(1, iWideBuf); |
|
302 // iResponseBuf is the button val |
|
303 iResponseBuf.CreateMaxL(sizeof(TInt)); |
|
304 TInt comboLineLen = iMsg.Int2(); |
|
305 TInt comboButLen = iMsg.Int3(); |
|
306 const TUint16* ptr = iWideBuf.Ptr(); |
|
307 iTempPtrs[0].Set(ptr, comboLineLen >> 16); |
|
308 ptr += iTempPtrs[0].Length(); |
|
309 iTempPtrs[1].Set(ptr, comboLineLen & 0xFFFF); |
|
310 ptr += iTempPtrs[1].Length(); |
|
311 iTempPtrs[2].Set(ptr, comboButLen >> 16); |
|
312 ptr += iTempPtrs[2].Length(); |
|
313 iTempPtrs[3].Set(ptr, comboButLen & 0xFFFF); |
|
314 |
|
315 iRealNotifier.Notify(iTempPtrs[0], iTempPtrs[1], iTempPtrs[2], iTempPtrs[3], *(TInt*)iResponseBuf.Ptr(), iStatus); |
|
316 SetActive(); |
|
317 break; |
|
318 } |
|
319 default: |
|
320 __DEBUGGER(); |
|
321 } |
|
322 } |
|
323 |
|
324 void CAsyncWaiter::RunL() |
|
325 { |
|
326 TInt res = iStatus.Int(); |
|
327 switch (iMsg.Function()) |
|
328 { |
|
329 case EUpdateNotifierAndGetResponse: |
|
330 case EStartNotifierAndGetResponse: |
|
331 if (res == KErrNone || iResponseBuf.Length()) |
|
332 { |
|
333 TInt err = iMsg.Write(2, iResponseBuf); |
|
334 if (err) |
|
335 { |
|
336 res = err; |
|
337 } |
|
338 } |
|
339 iMsg.Complete(res); |
|
340 break; |
|
341 case ENotifierNotify: |
|
342 { |
|
343 TInt err = iMsg.Write(0, iResponseBuf); |
|
344 if (err) res = err; |
|
345 iMsg.Complete(res); |
|
346 break; |
|
347 } |
|
348 default: |
|
349 __DEBUGGER(); |
|
350 User::Leave(KErrNotSupported); |
|
351 } |
|
352 delete this; // Our work here is done |
|
353 } |
|
354 |
|
355 void CAsyncWaiter::DoCancel() |
|
356 { |
|
357 // We never call Cancel on our waiters |
|
358 } |
|
359 |
|
360 void MainL() |
|
361 { |
|
362 CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; |
|
363 CleanupStack::PushL(scheduler); |
|
364 CActiveScheduler::Install(scheduler); |
|
365 CNotifierProxyServer* server = new(ELeave) CNotifierProxyServer; |
|
366 CleanupStack::PushL(server); |
|
367 server->ConstructL(); |
|
368 CActiveScheduler::Start(); |
|
369 CleanupStack::PopAndDestroy(2, scheduler); // server, scheduler |
|
370 } |
|
371 |
|
372 EXPORT_C TInt StartNotifierProxyThreadFunction(TAny*) |
|
373 { |
|
374 TInt err = KErrNoMemory; |
|
375 CTrapCleanup* cleanup = CTrapCleanup::New(); |
|
376 if (cleanup) |
|
377 { |
|
378 TRAP(err, MainL()); |
|
379 delete cleanup; |
|
380 } |
|
381 return err; |
|
382 } |
|
383 |
|
384 class RDebugNotifier : public RNotifier |
|
385 { |
|
386 public: |
|
387 TInt ShutdownProxy() |
|
388 { |
|
389 return SendReceive(KShutdownProxy, TIpcArgs()); |
|
390 } |
|
391 TInt PingProxy() |
|
392 { |
|
393 return SendReceive(KPingProxy, TIpcArgs()); |
|
394 } |
|
395 }; |
|
396 |
|
397 EXPORT_C TInt ShutdownProxyNotifier() |
|
398 { |
|
399 RDebugNotifier notifier; |
|
400 TInt err = notifier.Connect(); |
|
401 if (err == KErrNotFound) |
|
402 { |
|
403 // Oh dear, !Notifier isn't running. Meaning we renamed it then crashed, probably. Try renaming the real one |
|
404 RMemoryAccess::LoadDriver(); |
|
405 RMemoryAccess mem; |
|
406 err = mem.Open(); |
|
407 if (err) return err; |
|
408 TServerKernelInfoBuf buf; |
|
409 TInt err = mem.GetObjectInfo(EServer, KRealNotifierServerName, buf); |
|
410 if (!err) |
|
411 { |
|
412 TUint8* realServer = buf().iAddressOfKernelObject; |
|
413 mem.InPlaceObjectRename(EServer, realServer, _L8("!Notifier")); |
|
414 } |
|
415 mem.Close(); |
|
416 return err; |
|
417 } |
|
418 |
|
419 err = notifier.ShutdownProxy(); |
|
420 if (err == KErrServerTerminated) err = KErrNone; // It's expected to get KErrServerTerminated, because we deliberately don't complete the message. This way the client is more likely to get the completion once the server has actually gone, and not slightly before |
|
421 notifier.Close(); |
|
422 |
|
423 return err; |
|
424 } |
|
425 |
|
426 EXPORT_C TBool NotifierProxyIsRunning() |
|
427 { |
|
428 RDebugNotifier notifier; |
|
429 TInt err = notifier.Connect(); |
|
430 if (err) return EFalse; // Not even original notifier is running?! |
|
431 err = notifier.PingProxy(); |
|
432 notifier.Close(); |
|
433 return err == KErrNone; // The real proxy will return KErrNotSupported in this scenario |
|
434 } |
|
435 |
|
436 |
|
437 void CNotifierProxyServer::SetupWindowL() |
|
438 { |
|
439 //__DEBUGGER(); |
|
440 LeaveIfErr(iWs.Connect(), _L("Couldn't connect to windowserver")); |
|
441 //iWs.SetAutoFlush(ETrue); |
|
442 iRedrawer = new(ELeave) CRedrawer(*this); |
|
443 iRedrawer->Go(); |
|
444 |
|
445 iScreenDevice = new(ELeave) CWsScreenDevice(iWs); |
|
446 LeaveIfErr(iScreenDevice->Construct(), _L("Couldn't construct screen device")); // User default screen number |
|
447 LeaveIfErr(iScreenDevice->CreateContext(iGc), _L("Couldn't create gc")); |
|
448 iWg = RWindowGroup(iWs); |
|
449 LeaveIfErr(iWg.Construct(2, EFalse), _L("Couldn't construct windowgroup")); |
|
450 iWin = RWindow(iWs); |
|
451 LeaveIfErr(iWin.Construct(iWg, (TUint32)this), _L("Couldn't construct window")); |
|
452 |
|
453 iWin.SetBackgroundColor(KRgbBlack); |
|
454 iWg.SetOrdinalPosition(0, 1000); // 1000 is ECoeWinPriorityAlwaysAtFront, but I don't want the dependancy on a cone header |
|
455 TRect rect(TPoint(), TSize(iScreenDevice->SizeInPixels().iWidth, 50)); |
|
456 iWin.SetExtent(rect.iTl, rect.Size()); |
|
457 iWin.SetVisible(EFalse); |
|
458 iWin.Activate(); |
|
459 iWs.Flush(); |
|
460 |
|
461 //iBitmap = new(ELeave) CFbsBitmap; |
|
462 //LeaveIfErr(iBitmap->Create(iScreenDevice->SizeInPixels(), EColor16MU), _L("Couldn't create bitmap")); |
|
463 //iDsa = CDirectScreenAccess::NewL(iWs, *iScreenDevice, iWin, *this); |
|
464 } |
|
465 |
|
466 void CNotifierProxyServer::DoWservInitiatedRedraw(const TRect& /*aRect*/) |
|
467 { |
|
468 //__DEBUGGER(); |
|
469 // This code based on CCoeControl::HandleRedrawEvent |
|
470 //iWin.BeginRedraw(aRect); |
|
471 iWin.BeginRedraw(TRect(TPoint(), iWin.Size())); |
|
472 iGc->Activate(iWin); |
|
473 |
|
474 iGc->UseFont(iFont); |
|
475 iGc->SetPenColor(KRgbGreen); |
|
476 iGc->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
477 iGc->SetBrushColor(KRgbBlack); |
|
478 for (TInt i = 0; i < iText.Count(); i++) |
|
479 { |
|
480 TPoint drawPoint(0, iFont->FontMaxAscent() + i * iFont->FontLineGap()); |
|
481 if (drawPoint.iY > iWin.Size().iHeight) |
|
482 { |
|
483 // We've more to draw than we have room. Bail. |
|
484 break; |
|
485 } |
|
486 //iGc->DrawText(iText[i]->iText, drawPoint); |
|
487 iGc->DrawText(iText[i]->iText, BoxForLine(i), iFont->FontMaxAscent()); |
|
488 } |
|
489 iGc->DiscardFont(); |
|
490 iGc->Deactivate(); |
|
491 iWin.EndRedraw(); |
|
492 } |
|
493 |
|
494 TRect CNotifierProxyServer::BoxForLine(TInt aLineIndex) |
|
495 { |
|
496 TRect textBox = TRect(0, aLineIndex * iFont->FontLineGap(), iWin.Size().iWidth, (aLineIndex+1) * iFont->FontLineGap()); |
|
497 return textBox; |
|
498 } |
|
499 |
|
500 RWsSession& CNotifierProxyServer::WsSession() |
|
501 { |
|
502 return iWs; |
|
503 } |
|
504 |
|
505 void CNotifierProxyServer::InfoPrint(const TDesC& aText, TUint aClientId) |
|
506 { |
|
507 TPtrC text(aText); |
|
508 TInt newline = aText.Locate('\n'); |
|
509 if (newline != KErrNotFound) |
|
510 { |
|
511 // UIQ supported 2-line infoprints so some code puts a newline in - if so split it up and treat as two calls |
|
512 TPtrC first = aText.Left(newline); |
|
513 TPtrC second = aText.Mid(newline+1); |
|
514 InfoPrint(first, aClientId); |
|
515 //InfoPrint(second, aClientId); |
|
516 text.Set(second); // Drop through at this point - prevents recursing if there are many newlines (also stops more than one newline from being recognised) |
|
517 } |
|
518 |
|
519 CLine* line = new CLine(text, aClientId); |
|
520 if (!line) return; // OOM |
|
521 |
|
522 // Check if client should be getting frequent flyer miles, if so limit it |
|
523 for (TInt i = iText.Count() - 1; i >= 0; i--) |
|
524 { |
|
525 CLine* line = iText[i]; |
|
526 if (aClientId && aClientId == line->iClientId && text.Left(6) == line->iText.Left(6)) |
|
527 { |
|
528 iText.Remove(i); |
|
529 // And restart timer if the one we've just removed was at index zero, ie about to be removed anyway (otherwise timer will remove the new one sooner at the time when the old one was due) |
|
530 if (i == 0) iPeriodic->Cancel(); // (cancelling it here will cause it to be restarted in DisplayAndStartTimer) |
|
531 } |
|
532 } |
|
533 |
|
534 TInt err = iText.Append(line); |
|
535 if (err) |
|
536 { |
|
537 delete line; |
|
538 } |
|
539 else |
|
540 { |
|
541 RecalculateWindow(); |
|
542 iWin.Invalidate(); |
|
543 DisplayAndStartTimer(); |
|
544 iWs.Flush(); |
|
545 } |
|
546 } |
|
547 |
|
548 CRedrawer::CRedrawer(CNotifierProxyServer& aServer) |
|
549 : CActive(CActive::EPriorityStandard), iServer(aServer) |
|
550 { |
|
551 CActiveScheduler::Add(this); |
|
552 } |
|
553 |
|
554 void CRedrawer::Go() |
|
555 { |
|
556 if (!IsActive()) |
|
557 { |
|
558 iServer.WsSession().RedrawReady(&iStatus); |
|
559 SetActive(); |
|
560 } |
|
561 } |
|
562 |
|
563 void CRedrawer::RunL() |
|
564 { |
|
565 TWsRedrawEvent redrawEvent; |
|
566 iServer.WsSession().GetRedraw(redrawEvent); |
|
567 TRect rect=redrawEvent.Rect(); |
|
568 |
|
569 iServer.DoWservInitiatedRedraw(rect); |
|
570 Go(); |
|
571 iServer.WsSession().Flush(); |
|
572 } |
|
573 |
|
574 void CRedrawer::DoCancel() |
|
575 { |
|
576 iServer.WsSession().RedrawReadyCancel(); |
|
577 } |
|
578 |
|
579 CRedrawer::~CRedrawer() |
|
580 { |
|
581 Cancel(); |
|
582 } |
|
583 |
|
584 void CNotifierProxyServer::RecalculateWindow() |
|
585 { |
|
586 // Grow or shrink the window if needed to display all the text we have |
|
587 TInt numLines = iText.Count(); |
|
588 |
|
589 const TInt KMaxWindowHeight = 200; |
|
590 TInt newHeight = Min(BoxForLine(0).Height() * numLines, KMaxWindowHeight); // Don't exceed our defined max height |
|
591 TInt currentHeight = iWin.Size().iHeight; |
|
592 if (newHeight != currentHeight) |
|
593 { |
|
594 iWin.SetSize(TSize(iWin.Size().iWidth, newHeight)); |
|
595 } |
|
596 } |
|
597 |
|
598 TInt CNotifierProxyServer::StaticTick(TAny* aSelf) |
|
599 { |
|
600 static_cast<CNotifierProxyServer*>(aSelf)->Tick(); |
|
601 return 0; |
|
602 } |
|
603 |
|
604 void CNotifierProxyServer::Tick() |
|
605 { |
|
606 // Remove 1 line from the top of the infoprint each time the timer fires, if nothing left hide the window |
|
607 if (iText.Count()) |
|
608 { |
|
609 iText.Remove(0); |
|
610 } |
|
611 |
|
612 if (iText.Count() == 0) |
|
613 { |
|
614 iWin.SetVisible(EFalse); |
|
615 iPeriodic->Cancel(); // No need for further ticks |
|
616 } |
|
617 else |
|
618 { |
|
619 RecalculateWindow(); |
|
620 iWin.Invalidate(); |
|
621 } |
|
622 iWs.Flush(); |
|
623 } |
|
624 |
|
625 void CNotifierProxyServer::DisplayAndStartTimer() |
|
626 { |
|
627 if (iText.Count()) |
|
628 { |
|
629 iWin.SetVisible(ETrue); |
|
630 if (!iPeriodic->IsActive()) |
|
631 { |
|
632 iPeriodic->Start(KInfoPrintTime, KInfoPrintTime, TCallBack(&StaticTick, this)); |
|
633 } |
|
634 } |
|
635 } |
|
636 |
|
637 CLine::CLine(const TDesC& aText, TUint aClientId) |
|
638 : iText(aText), iClientId(aClientId) |
|
639 { |
|
640 //iTimeOfPrint.UniversalTime(); |
|
641 } |
|
642 |
|
643 CPanicDialogWatcher::CPanicDialogWatcher(CNotifierProxyServer& aServer) |
|
644 : CActive(CActive::EPriorityStandard), iServer(aServer) |
|
645 { |
|
646 CActiveScheduler::Add(this); |
|
647 } |
|
648 |
|
649 void CPanicDialogWatcher::ConstructL() |
|
650 { |
|
651 User::LeaveIfError(iUndertaker.Create()); |
|
652 iUndertaker.Logon(iStatus, iThreadHandle); |
|
653 SetActive(); |
|
654 } |
|
655 |
|
656 CPanicDialogWatcher::~CPanicDialogWatcher() |
|
657 { |
|
658 Cancel(); |
|
659 iUndertaker.Close(); |
|
660 } |
|
661 |
|
662 void CPanicDialogWatcher::RunL() |
|
663 { |
|
664 TInt threadHandle = iThreadHandle; |
|
665 iUndertaker.Logon(iStatus, iThreadHandle); |
|
666 SetActive(); |
|
667 |
|
668 RThread thread; |
|
669 thread.SetHandle(threadHandle); |
|
670 iTempName = thread.FullName(); |
|
671 PrettyName(EListThread, iTempName); |
|
672 if (thread.ExitType() == EExitPanic) |
|
673 { |
|
674 TExitCategoryName cat = thread.ExitCategory(); |
|
675 TBuf<256> buf; |
|
676 buf.Format(_L("Panic: %S %d from %S"), &cat, thread.ExitReason(), &iTempName); |
|
677 iServer.InfoPrint(buf, 0); |
|
678 } |
|
679 else if (thread.ExitType() == EExitKill) |
|
680 { |
|
681 TBuf<256> buf; |
|
682 buf.Format(_L("Kill %d: Tid %d %S"), thread.ExitReason(), TUint(thread.Id()), &iTempName); |
|
683 iServer.InfoPrint(buf, 0); |
|
684 } |
|
685 else if (thread.ExitType() == EExitTerminate) |
|
686 { |
|
687 TBuf<256> buf; |
|
688 buf.Format(_L("Terminate %d: Tid %d %S"), thread.ExitReason(), TUint(thread.Id()), &iTempName); |
|
689 iServer.InfoPrint(buf, 0); |
|
690 } |
|
691 thread.Close(); |
|
692 } |
|
693 |
|
694 void CPanicDialogWatcher::DoCancel() |
|
695 { |
|
696 iUndertaker.LogonCancel(); |
|
697 } |
|
698 |
|
699 #endif |