1 /*
2 SDL - Simple DirectMedia Layer
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this library; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18
19 */
20
21 #include"sdlenvdata.h"
22 #include"dsa.h"
23 #include"appsrv.h"
24
25 class CCurrentAppUi;
26 class CEikonEnv;
27
28 extern void ContainerWindowChanged();
29 extern void PrepareContainerWindowChanged();
30
31 extern TInt DoMain(TAny* /*aParam*/);
32
33 EpocSdlEnvData* gEpocEnv;
34
TSdlCleanupItem(TSdlCleanupOperation aOperation,TAny * aItem,TBool aThreadCleanup)35 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem, TBool aThreadCleanup) :
36 iOperation(aOperation), iItem(aItem), iThread(aThreadCleanup ? RThread().Id() : gEpocEnv->iId)
37 {
38 }
39
IsOwnThreaded()40 TBool EnvUtils::IsOwnThreaded()
41 {
42 return gEpocEnv->iEpocEnvFlags & CSDL::EOwnThread;
43 }
44
EventQueue()45 MEventQueue& EpocSdlEnv::EventQueue()
46 {
47 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
48 return *gEpocEnv->iEventQueue;
49 }
50
51
Flags(TInt aFlag)52 TBool EpocSdlEnv::Flags(TInt aFlag)
53 {
54 const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag;
55 return flag == aFlag;
56 }
57
Argc()58 TInt EpocSdlEnv::Argc()
59 {
60 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
61 return gEpocEnv->iArgc;
62 }
63
64
Argv()65 char** EpocSdlEnv::Argv()
66 {
67 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
68 return gEpocEnv->iArgv;
69 }
70
71
IsDsaAvailable()72 TBool EpocSdlEnv::IsDsaAvailable()
73 {
74 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
75 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
76 }
77
PostUpdate()78 void EpocSdlEnv::PostUpdate()
79 {
80 while(EnvUtils::RunSingleThread()){}
81 }
82
WaitDsaAvailable()83 void EpocSdlEnv::WaitDsaAvailable()
84 {
85 gEpocEnv->iEpocEnvFlags |= EpocSdlEnvData::EWaitDsa;
86 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0);
87 if(gEpocEnv->iEpocEnvFlags & EpocSdlEnvData::EWaitDsa)
88 EpocSdlEnv::DoSuspend(ETrue);
89 //gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
90 /*if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
91 {
92 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0);
93 }
94 */
95 }
96
97
ResumeDsa()98 void EpocSdlEnv::ResumeDsa()
99 {
100 if(gEpocEnv->iEpocEnvFlags & EpocSdlEnvData::EWaitDsa)
101 EpocSdlEnv::DoResume(ETrue);
102 gEpocEnv->iEpocEnvFlags &= ~EpocSdlEnvData::EWaitDsa;
103 }
104
105
IsSuspend()106 TBool EpocSdlEnv::IsSuspend()
107 {
108 return gEpocEnv->iEpocEnvFlags & EpocSdlEnvData::ESuspend;
109 }
110
DoSuspend(TBool aInternal)111 void EpocSdlEnv::DoSuspend(TBool aInternal)
112 {
113 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, aInternal);
114 if(EnvUtils::IsOwnThreaded())
115 {
116 RThread thread;
117 User::LeaveIfError(thread.Open(gEpocEnv->iId));
118 thread.Suspend();
119 }
120
121 gEpocEnv->iEpocEnvFlags |= EpocSdlEnvData::ESuspend;
122
123
124 for(TInt i = gEpocEnv->iChildThreads->Count() - 1; i >= 0; i--)
125 {
126 RThread th;
127 if(th.Open(gEpocEnv->iChildThreads->At(i)) == KErrNone)
128 {
129 const TExitType reason = th.ExitType();
130 if(reason != EExitPending)
131 {
132 gEpocEnv->iChildThreads->Delete(i);
133 }
134 else
135 {
136 th.Suspend();
137 }
138 th.Close();
139 }
140 }
141
142 EpocSdlEnv::DisableDraw();
143
144 /*if(gEpocEnv->iDsa != NULL && (gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop)))
145 {
146 gEpocEnv->iDsa->SetSuspend();
147 if(EnvUtils::IsOwnThreaded())
148 {
149 RThread().Suspend();
150 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0);
151 }
152 }
153 */
154 }
155
156 /*
157 void EpocSdlEnv::SetWaitDsa()
158 {
159 if(!IsDsaAvailable())
160 {
161 if(EnvUtils::IsOwnThreaded())
162 {
163 RThread th;
164 th.Open(gEpocEnv->iId);
165 th.Suspend();
166 th.Close();
167 }
168 if(gEpocEnv->iDsa != NULL)
169 gEpocEnv->iDsa->SetSuspend();
170 }
171 }
172 */
173
DoResume(TBool aInternal,TBool aRendezvous)174 void EpocSdlEnv::DoResume(TBool aInternal, TBool aRendezvous)
175 {
176 if(EnvUtils::IsOwnThreaded())
177 {
178 RThread thread;
179 User::LeaveIfError(thread.Open(gEpocEnv->iId));
180 if(aRendezvous)
181 {
182 TRequestStatus status;
183 thread.Rendezvous(status);
184
185 #ifdef __WINS__
186 thread.SetPriority(EPriorityNormal);
187 #endif
188 thread.Resume();
189 User::WaitForRequest(status);
190 }
191 else
192 {
193 thread.Resume();
194 }
195 gEpocEnv->iEpocEnvFlags &= ~EpocSdlEnvData::ESuspend;
196 thread.Close();
197 }
198 else
199 {
200 if(aRendezvous && !gEpocEnv->iCaller->IsActive())
201 gEpocEnv->iCaller->Start(TCallBack(DoMain));
202 else
203 gEpocEnv->iEpocEnvFlags &= ~EpocSdlEnvData::ESuspend;
204 }
205
206 if(gEpocEnv->iChildThreads != NULL)
207 {
208 for(TInt i = gEpocEnv->iChildThreads->Count() - 1; i >= 0; i--)
209 {
210 RThread th;
211 if(th.Open(gEpocEnv->iChildThreads->At(i)) == KErrNone)
212 {
213 if(th.ExitType() != EExitPending)
214 {
215 gEpocEnv->iChildThreads->Delete(i);
216 }
217 else
218 {
219 th.Resume();
220 }
221 th.Close();
222 }
223 }
224 }
225
226 if(!aRendezvous)
227 EpocSdlEnv::EnableDraw();
228
229
230 const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, aInternal);
231 gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue);
232
233 }
234
235
AllocSwSurface(const TSize & aSize,TDisplayMode aMode)236 TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode)
237 {
238 return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode);
239 }
240
AllocHwSurface(const TSize & aSize,TDisplayMode aMode)241 TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode)
242 {
243 return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode);
244 }
245
246
UnlockHwSurface()247 void EpocSdlEnv::UnlockHwSurface()
248 {
249 gEpocEnv->iDsa->UnlockHwSurface();
250 }
251
LockHwSurface()252 TUint8* EpocSdlEnv::LockHwSurface()
253 {
254 return gEpocEnv->iDsa->LockHwSurface();
255 }
256
257
UpdateSwSurface()258 void EpocSdlEnv::UpdateSwSurface()
259 {
260 gEpocEnv->iDsa->UpdateSurface();
261 }
262
UpdateHwSurface()263 void EpocSdlEnv::UpdateHwSurface()
264 {
265 if(gEpocEnv->iDsa->IsHwScreenSurface())
266 gEpocEnv->iDsa->UpdateSurface();
267 }
268
AddUpdateRect(TUint8 * aAddress,const TRect & aUpdateRect,const TRect & aRect)269 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
270 {
271 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
272 }
273
Request(TInt aService)274 void EpocSdlEnv::Request(TInt aService)
275 {
276 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
277 gEpocEnv->iAppSrv->Request(aService);
278 }
279
280
CreateZoomer(const TSize & aRequestedSize)281 void EpocSdlEnv::CreateZoomer(const TSize& aRequestedSize)
282 {
283 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
284 if(gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->WindowSize() != aRequestedSize)
285 {
286 TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize));
287 }
288 }
289
290
ScreenSize()291 TSize EpocSdlEnv::ScreenSize()
292 {
293 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
294 return gEpocEnv->iDsa == NULL ? TSize(0, 0) : gEpocEnv->iDsa->ScreenRect().Size();
295 }
296
WindowSize()297 TSize EpocSdlEnv::WindowSize()
298 {
299 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
300 return gEpocEnv->iDsa == NULL ? TSize(0, 0) : gEpocEnv->iDsa->WindowSize();
301 }
302
DisplayMode()303 TDisplayMode EpocSdlEnv::DisplayMode()
304 {
305 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
306 }
307
PointerMode()308 TPointerCursorMode EpocSdlEnv::PointerMode()
309 {
310 return static_cast<TPointerCursorMode>
311 (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
312 }
313
314
SetAppOrientation(CSDL::TAppOrientation aOrientation)315 TInt EpocSdlEnv::SetAppOrientation(CSDL::TAppOrientation aOrientation)
316 {
317 gEpocEnv->iAppSrv->SetParam(aOrientation);
318 return static_cast<CSDL::TAppOrientation>
319 (gEpocEnv->iAppSrv->RequestValue(EpocSdlEnv::ESetAppOrientation));
320 }
321
SetPalette(TInt aFirstcolor,TInt aColorCount,TUint32 * aPalette)322 TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette)
323 {
324 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
325 }
326
PanicMain(TInt aErr)327 void EpocSdlEnv::PanicMain(TInt aErr)
328 {
329 gEpocEnv->iAppSrv->PanicMain(aErr);
330 }
331
332
AppendCleanupItem(const TSdlCleanupItem & aItem)333 TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
334 {
335 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
336 return err;
337 }
338
RemoveCleanupItem(TAny * aItem)339 void EpocSdlEnv::RemoveCleanupItem(TAny* aItem)
340 {
341 for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
342 {
343 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
344 gEpocEnv->iCleanupItems->Delete(i);
345 }
346 }
347
CleanupItems()348 void EpocSdlEnv::CleanupItems()
349 {
350 const TThreadId id = RThread().Id();
351 TInt last = gEpocEnv->iCleanupItems->Count() - 1;
352 TInt i;
353 for(i = last; i >= 0 ; i--)
354 {
355 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
356 if(item.iThread == id)
357 {
358 item.iThread = TThreadId(0);
359 item.iOperation(item.iItem);
360 }
361 }
362 last = gEpocEnv->iCleanupItems->Count() - 1;
363 for(i = last; i >= 0 ; i--)
364 {
365 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
366 if(item.iThread == TThreadId(0))
367 {
368 gEpocEnv->iCleanupItems->Delete(i);
369 }
370 }
371 }
372
FreeSurface()373 void EpocSdlEnv::FreeSurface()
374 {
375 Request(CSdlAppServ::EAppSrvDsaStatus);
376 if(gEpocEnv->iDsa != NULL)
377 {
378 if(gEpocEnv->iDsa->IsHwScreenSurface())
379 {
380 gEpocEnv->iDsa->SetUpdating(EFalse);
381 }
382 __ASSERT_ALWAYS(!gEpocEnv->iDsa->IsUpdating(), PANIC(KErrNotReady));
383 gEpocEnv->iDsa->Free();
384 }
385 }
386
LockPalette(TBool aLock)387 void EpocSdlEnv::LockPalette(TBool aLock)
388 {
389 gEpocEnv->iDsa->LockPalette(aLock);
390 }
391
ObserverEvent(TInt aService,TInt aParam)392 void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam)
393 {
394 const TBool sdlThread = RThread().Id() == gEpocEnv->iId;
395 const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam);
396 gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread);
397 if(sdlThread && EnvUtils::IsOwnThreaded())
398 {
399 gEpocEnv->iAppSrv->SetParam(aParam);
400 const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService);
401 gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse);
402 }
403 }
404
405
WindowCoordinates(const TPoint & aPoint)406 TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint)
407 {
408 return gEpocEnv->iDsa == NULL ? aPoint :
409 gEpocEnv->iDsa->WindowCoordinates(aPoint);
410 }
411
PanicMain(const TDesC & aInfo,TInt aErr)412 void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr)
413 {
414 gEpocEnv->iAppSrv->PanicMain(aInfo, aErr);
415 }
416 /*
417 void EpocSdlEnv::ScreenSizeChanged()
418 {
419 // gEpocEnv->iDsa->WaitDeviceChange(EFalse);
420 }
421 */
422
423 //Dsa is a low priority ao, it has to wait if its pending event, but ws
424 //event has been prioritized before it
425 //this is not called from app thread!
426 /*
427 void EpocSdlEnv::WaitDeviceChange()
428 {
429 LockPalette(ETrue);
430
431 if(EnvUtils::IsOwnThreaded())
432 gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
433
434
435 static TSize ssz = TSize(-1, -1);
436 const TSize sz = WindowSize();
437 if(sz != ssz)
438 {
439 DisableDraw();
440 const TInt param = reinterpret_cast<TInt>(&sz);
441 ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
442
443 }
444
445 ContainerWindowChanged();
446
447 LockPalette(EFalse);
448 }
449 */
450
ScreenSizeChanged()451 void EpocSdlEnv::ScreenSizeChanged()
452 {
453 LockPalette(ETrue);
454 DisableDraw();
455 const TSize sz = WindowSize();
456 const TInt param = reinterpret_cast<TInt>(&sz);
457 ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
458 LockPalette(EFalse);
459 ContainerWindowChanged();
460 }
461
462 /*
463 void EpocSdlEnv::WaitDeviceChange()
464 {
465 LockPalette(ETrue);
466
467 if(EnvUtils::IsOwnThreaded())
468 gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
469
470
471 static TSize ssz = TSize(-1, -1);
472 const TSize sz = WindowSize();
473 if(sz != ssz)
474 {
475 DisableDraw();
476 const TInt param = reinterpret_cast<TInt>(&sz);
477 ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
478
479 }
480
481 ContainerWindowChanged();
482
483 LockPalette(EFalse);
484 }
485 */
486 /*
487 * This function try to find best fit if screen content does not fit in screen
488 */
AutoOrientation(const TSize & aSize)489 TBool EpocSdlEnv::AutoOrientation(const TSize& aSize)
490 {
491 const CSDL::TAppOrientation mode = gEpocEnv->iAppOrientation;
492
493 const TSize screenSize = gEpocEnv->iDsa->ScreenRect().Size();
494
495 if(mode == CSDL::EDefaultAppOrientation &&
496 gEpocEnv->iDsa &&
497 screenSize.iWidth != screenSize.iHeight)
498 {
499 CSDL::TAppOrientation dir = CSDL::EPortraitAppOrientation;
500
501 const TBool landscape = screenSize.iWidth > screenSize.iHeight;
502
503 //First we check if it windows entrily inside either of orientations
504 if(!EpocSdlEnv::Flags(CSDL::EImageResizeZoomOut) ||
505 (screenSize.iWidth == aSize.iWidth && screenSize.iHeight == aSize.iHeight))
506 {
507 if(screenSize.iWidth <= aSize.iWidth && screenSize.iHeight <= aSize.iHeight)
508 {
509 if(landscape)
510 dir = CSDL::ELandscapeAppOrientation;
511 return KErrNone == EpocSdlEnv::SetAppOrientation(dir);
512 }
513 else if(screenSize.iWidth <= aSize.iHeight && screenSize.iHeight <= aSize.iWidth)
514 {
515 if(!landscape)
516 dir = CSDL::ELandscapeAppOrientation;
517 return KErrNone == EpocSdlEnv::SetAppOrientation(dir);
518 }
519 }
520 //Then try to find more suitable dimensions
521 const TRect rect1 = CDsa::CalcResizeRect(screenSize, aSize);
522 const TRect rect2 = CDsa::CalcResizeRect(TSize(screenSize.iHeight, screenSize.iWidth), aSize);
523
524 const TInt area1 = rect1.Size().iWidth * rect1.Size().iHeight;
525 const TInt area2 = rect2.Size().iWidth * rect2.Size().iHeight;
526
527 //then better fit is the bigger intersection area
528 if(area1 > area2)
529 {
530 //current is better
531 if(landscape)
532 dir = CSDL::ELandscapeAppOrientation;
533 }
534 else if(area1 < area2)
535 {
536 //we have to turn the screen
537 if(!landscape)
538 dir = CSDL::ELandscapeAppOrientation;
539 }
540 else
541 {
542 return EFalse;
543 }
544 return KErrNone == EpocSdlEnv::SetAppOrientation(dir);
545 }
546 return EFalse;
547 }
548
CheckSdl()549 LOCAL_C TBool CheckSdl()
550 {
551 TInt isExit = ETrue;
552 RThread sdl;
553 if(sdl.Open(gEpocEnv->iId) == KErrNone)
554 {
555 if(sdl.ExitType() == EExitPending)
556 {
557 isExit = EFalse;
558 }
559 sdl.Close();
560 }
561 return isExit;
562 }
563
Free()564 void EpocSdlEnvData::Free()
565 {
566 if(RThread().Id() == gEpocEnv->iId)
567 {
568 if(iDsa != NULL)
569 {
570 __ASSERT_ALWAYS(!iDsa->IsUpdating(), PANIC(KErrNotReady));
571 iDsa->Free();
572 }
573 return;
574 }
575
576 __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrInUse));
577 }
578
Delete()579 void EpocSdlEnvData::Delete()
580 {
581
582 for(TInt i = 0; i <= iArgc; i++)
583 {
584 if(iArgv != NULL)
585 User::Free( iArgv[i] );
586 }
587
588 User::Free(iArgv);
589
590 iArgv = NULL;
591 iArgc = 0;
592
593 delete iEventQueue;
594
595 if(iDsa != NULL)
596 {
597 __ASSERT_ALWAYS(!gEpocEnv->iDsa->IsUpdating(), PANIC(KErrNotReady));
598 iDsa->Free();
599 }
600
601 delete iDsa;
602 delete iAppSrv;
603
604 delete gEpocEnv->iCaller;
605 }
606
ApplyGlesDsa()607 TInt EpocSdlEnv::ApplyGlesDsa()
608 {
609 CDsa* dsa = NULL;
610 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
611 gEpocEnv->iDsa = dsa;
612 return err;
613 }
614
Window()615 RWindow* EpocSdlEnv::Window()
616 {
617 return gEpocEnv == NULL ? NULL : (gEpocEnv->iDsa == NULL ? NULL : gEpocEnv->iDsa->Window());
618 }
619
SetOrientation(CSDL::TOrientationMode aOrientation)620 void EpocSdlEnv::SetOrientation(CSDL::TOrientationMode aOrientation)
621 {
622 gEpocEnv->iDsa->SetOrientation(aOrientation);
623 }
624
StackSize()625 TInt EpocSdlEnv::StackSize()
626 {
627 return gEpocEnv->iStackSize;
628 }
629
IsVideoThread()630 TBool EpocSdlEnv::IsVideoThread()
631 {
632 return RThread().Id() == gEpocEnv->iDsa->OwnerThread();
633 }
634
EnableDraw()635 void EpocSdlEnv::EnableDraw()
636 {
637 if(gEpocEnv->iDsa)
638 gEpocEnv->iDsa->DisableDraw(EFalse);
639 }
640
641
DisableDraw()642 void EpocSdlEnv::DisableDraw()
643 {
644 if(gEpocEnv->iDsa)
645 gEpocEnv->iDsa->DisableDraw(ETrue);
646 }
647
BgColor()648 TUint32 EpocSdlEnv::BgColor()
649 {
650 return gEpocEnv->iColor;
651 }
652 /*
653 const CFbsBitmap** EpocSdlEnv::BitGdiCanvas()
654 {
655 return gEpocEnv->iBitGdiCanvas;
656 }
657 */
658
AppendThread(TInt aThreadId)659 void EpocSdlEnv::AppendThread(TInt aThreadId)
660 {
661 TRAPD(err, gEpocEnv->iChildThreads->AppendL(aThreadId));
662 PANIC_IF_ERROR(err);
663 }
664
RemoveThread(TInt aThreadId)665 void EpocSdlEnv::RemoveThread(TInt aThreadId)
666 {
667 for(TInt i = gEpocEnv->iChildThreads->Count() - 1; i >= 0; i--)
668 {
669 if(gEpocEnv->iChildThreads->At(i) == aThreadId)
670 {
671 gEpocEnv->iChildThreads->Delete(i);
672 }
673 else
674 {
675 RThread th;
676 if(th.Open(gEpocEnv->iChildThreads->At(i)) == KErrNone)
677 {
678 if(th.ExitType() != EExitPending)
679 {
680 gEpocEnv->iChildThreads->Delete (i);
681 }
682 th.Close();
683 }
684 }
685 }
686 }
687
688