e14743d1 |
1 | /* |
2 | SDL_Main.cpp |
3 | Symbian OS services for SDL |
4 | |
5 | Markus Mertama |
6 | */ |
7 | |
8 | |
9 | #include "epoc_sdl.h" |
10 | |
11 | #include"sdlepocapi.h" |
12 | #include <e32base.h> |
13 | #include <estlib.h> |
14 | #include <stdio.h> |
15 | #include <badesca.h> |
16 | |
17 | #include "vectorbuffer.h" |
18 | #include <w32std.h> |
19 | #include <aknappui.h> |
20 | #include <aknapp.h> |
21 | #include "SDL_epocevents_c.h" |
22 | #include "SDL_keysym.h" |
23 | #include "dsa.h" |
24 | |
25 | |
26 | #ifdef SYMBIANC |
27 | #include <reent.h> |
28 | #endif |
29 | |
30 | //Markus Mertama |
31 | |
32 | |
33 | extern SDLKey* KeyMap(); |
34 | extern void ResetKeyMap(); |
35 | |
36 | class CCurrentAppUi; |
37 | |
38 | //const TUid KSDLUid = { 0xF01F3D69 }; |
39 | |
40 | NONSHARABLE_CLASS(EnvUtils) |
41 | { |
42 | public: |
43 | static void DisableKeyBlocking(); |
44 | static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus); |
45 | }; |
46 | |
47 | TInt Panic(TInt aErr, TInt aLine) |
48 | { |
49 | TBuf<64> b; |
50 | b.Format(_L("Main at %d"), aLine); |
51 | User::Panic(b, aErr); |
52 | return 0; |
53 | } |
54 | |
55 | |
56 | NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi |
57 | { |
58 | public: |
59 | static CCurrentAppUi* Cast(CEikAppUi* aUi); |
60 | void DisableKeyBlocking(); |
61 | }; |
62 | |
63 | |
64 | CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi) |
65 | { |
66 | return static_cast<CCurrentAppUi*>(aUi); |
67 | } |
68 | |
69 | void CCurrentAppUi::DisableKeyBlocking() |
70 | { |
71 | SetKeyBlockMode(ENoKeyBlock); |
72 | } |
73 | |
74 | |
75 | class CEventQueue : public CBase, public MEventQueue |
76 | { |
77 | public: |
78 | static CEventQueue* NewL(); |
79 | ~CEventQueue(); |
80 | public: |
81 | TInt Append(const TWsEvent& aEvent); |
82 | const TWsEvent& Shift(); |
83 | void Lock(); |
84 | void Unlock(); |
85 | TBool HasData(); |
86 | private: |
87 | TVector<TWsEvent, 64> iVector; |
88 | RCriticalSection iCS; |
89 | }; |
90 | |
91 | CEventQueue* CEventQueue::NewL() |
92 | { |
93 | CEventQueue* q = new (ELeave) CEventQueue(); |
94 | CleanupStack::PushL(q); |
95 | User::LeaveIfError(q->iCS.CreateLocal()); |
96 | CleanupStack::Pop(); |
97 | return q; |
98 | } |
99 | |
100 | CEventQueue::~CEventQueue() |
101 | { |
102 | iCS.Close(); |
103 | } |
104 | |
105 | TInt CEventQueue::Append(const TWsEvent& aEvent) |
106 | { |
107 | iCS.Wait(); |
108 | const TInt err = iVector.Append(aEvent); |
109 | iCS.Signal(); |
110 | return err; |
111 | } |
112 | |
113 | |
114 | TBool CEventQueue::HasData() |
115 | { |
116 | return iVector.Size() > 0; |
117 | } |
118 | |
119 | |
120 | void CEventQueue::Lock() |
121 | { |
122 | iCS.Wait(); |
123 | } |
124 | |
125 | void CEventQueue::Unlock() |
126 | { |
127 | iCS.Signal(); |
128 | } |
129 | |
130 | const TWsEvent& CEventQueue::Shift() |
131 | { |
132 | const TWsEvent& event = iVector.Shift(); |
133 | return event; |
134 | } |
135 | |
136 | |
137 | TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) : |
138 | iOperation(aOperation), iItem(aItem), iThread(RThread().Id()) |
139 | { |
140 | } |
141 | |
142 | class CEikonEnv; |
143 | class CSdlAppServ; |
144 | |
145 | |
146 | NONSHARABLE_CLASS(EpocSdlEnvData) |
147 | { |
148 | public: |
149 | void Free(); |
150 | CEventQueue* iEventQueue; |
151 | TMainFunc iMain; |
152 | TInt iEpocEnvFlags; |
153 | int iArgc; |
154 | char** iArgv; |
155 | CDsa* iDsa; |
156 | CSdlAppServ* iAppSrv; |
157 | TThreadId iId; |
158 | CArrayFix<TSdlCleanupItem>* iCleanupItems; |
159 | CEikAppUi* iAppUi; |
160 | CSDL* iSdl; |
161 | }; |
162 | |
163 | |
164 | EpocSdlEnvData* gEpocEnv; |
165 | |
166 | #define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;} |
167 | |
168 | MAINFUNC(1) |
169 | MAINFUNC(2) |
170 | MAINFUNC(3) |
171 | MAINFUNC(4) |
172 | MAINFUNC(5) |
173 | MAINFUNC(6) |
174 | |
175 | EXPORT_C TMainFunc::TMainFunc() |
176 | { |
177 | Mem::FillZ(iMainFunc, sizeof(iMainFunc)); |
178 | } |
179 | |
180 | |
181 | const void* TMainFunc::operator[](TInt aIndex) const |
182 | { |
183 | return iMainFunc[aIndex]; |
184 | } |
185 | |
186 | |
187 | NONSHARABLE_CLASS(CSdlAppServ) : public CActive |
188 | { |
189 | public: |
190 | enum |
191 | { |
192 | EAppSrvNoop = CDsa::ELastDsaRequest, |
193 | EAppSrvWindowWidth, |
194 | EAppSrvWindowHeight, |
195 | EAppSrvWindowDisplayMode, |
196 | EAppSrvWindowPointerCursorMode, |
197 | EAppSrvDsaStatus, |
198 | EAppSrvStopThread, |
199 | EAppSrvWaitDsa |
200 | }; |
201 | CSdlAppServ(); |
202 | void ConstructL(); |
203 | ~CSdlAppServ(); |
204 | TInt Request(TInt aService); |
205 | TInt RequestValue(TInt aService); |
206 | void Init(); |
207 | void PanicMain(TInt aReason); |
208 | void PanicMain(const TDesC& aInfo, TInt aReason); |
209 | void SetObserver(MSDLObserver* aObserver); |
210 | TInt ObserverEvent(TInt aEvent, TInt aParam); |
211 | void SetParam(TInt aParam); |
212 | void HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread); |
213 | MSDLObserver* Observer(); |
214 | private: |
215 | void RunL(); |
216 | void DoCancel(); |
217 | private: |
218 | const TThreadId iMainId; |
219 | RThread iAppThread; |
220 | TInt iService; |
221 | TInt iReturnValue; |
222 | RSemaphore iSema; |
223 | MSDLObserver* iObserver; |
224 | TRequestStatus* iStatusPtr; |
225 | }; |
226 | |
227 | CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id()) |
228 | { |
229 | } |
230 | |
231 | |
232 | |
233 | MSDLObserver* CSdlAppServ::Observer() |
234 | { |
235 | return iObserver; |
236 | } |
237 | |
238 | |
239 | void CSdlAppServ::SetObserver(MSDLObserver* aObserver) |
240 | { |
241 | iObserver = aObserver; |
242 | } |
243 | |
244 | TInt CSdlAppServ::ObserverEvent(TInt aEvent, TInt aParam) |
245 | { |
246 | if(iObserver != NULL) |
247 | { |
248 | if(RThread().Id() == gEpocEnv->iId) |
249 | { |
250 | return iObserver->SdlThreadEvent(aEvent, aParam); |
251 | } |
252 | else if(RThread().Id() == iMainId) |
253 | { |
254 | return iObserver->SdlEvent(aEvent, aParam); |
255 | } |
256 | PANIC(KErrNotSupported); |
257 | } |
258 | return 0; |
259 | } |
260 | |
261 | void CSdlAppServ::PanicMain(TInt aReason) |
262 | { |
263 | iAppThread.Panic(RThread().Name(), aReason); |
264 | } |
265 | |
266 | void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason) |
267 | { |
268 | iAppThread.Panic(aInfo, aReason); |
269 | } |
270 | |
271 | void CSdlAppServ::ConstructL() |
272 | { |
273 | CActiveScheduler::Add(this); |
274 | User::LeaveIfError(iSema.CreateLocal(1)); |
275 | iStatus = KRequestPending; |
276 | iStatusPtr = &iStatus; |
277 | SetActive(); |
278 | } |
279 | |
280 | CSdlAppServ::~CSdlAppServ() |
281 | { |
282 | Cancel(); |
283 | if(iSema.Handle() != NULL) |
284 | iSema.Signal(); |
285 | iSema.Close(); |
286 | iAppThread.Close(); |
287 | } |
288 | |
289 | TInt CSdlAppServ::Request(TInt aService) |
290 | { |
291 | if(RThread().Id() != iAppThread.Id()) |
292 | { |
293 | iSema.Wait(); |
294 | iService = aService; |
295 | iAppThread.RequestComplete(iStatusPtr, KErrNone); |
296 | return KErrNone; |
297 | } |
298 | return KErrBadHandle; |
299 | } |
300 | |
301 | TInt CSdlAppServ::RequestValue(TInt aService) |
302 | { |
303 | Request(aService); |
304 | Request(EAppSrvNoop); |
305 | return iReturnValue; |
306 | } |
307 | |
308 | void CSdlAppServ::Init() |
309 | { |
310 | PANIC_IF_ERROR(iAppThread.Open(iMainId)); |
311 | } |
312 | |
313 | void CSdlAppServ::SetParam(TInt aParam) |
314 | { |
315 | iReturnValue = aParam; |
316 | } |
317 | |
318 | void CSdlAppServ::HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread) |
319 | { |
320 | if(iObserver != NULL && aMainThread) |
321 | { |
322 | switch(aService) |
323 | { |
324 | case MSDLObserver::EEventScreenSizeChanged: |
325 | if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette) |
326 | EpocSdlEnv::LockPalette(EFalse); |
327 | break; |
328 | } |
329 | } |
330 | if(!aMainThread && aService == MSDLObserver::EEventSuspend) |
331 | { |
332 | if(iObserver == NULL || |
333 | (gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend)) |
334 | { |
335 | EpocSdlEnv::Suspend(); |
336 | } |
337 | } |
338 | } |
339 | |
340 | void CSdlAppServ::RunL() |
341 | { |
342 | if(iStatus == KErrNone) |
343 | { |
344 | switch(iService) |
345 | { |
346 | case CSdlAppServ::EAppSrvWaitDsa: |
347 | EpocSdlEnv::SetWaitDsa(); |
348 | iReturnValue = EpocSdlEnv::IsDsaAvailable(); |
349 | // } |
350 | // gEpocEnv->iDsa->Stop(); |
351 | // gEpocEnv->iDsa->RestartL(); |
352 | break; |
353 | case CSdlAppServ::EAppSrvStopThread: |
354 | gEpocEnv->iDsa->SetSuspend(); |
355 | break; |
356 | case EpocSdlEnv::EDisableKeyBlocking: |
357 | EnvUtils::DisableKeyBlocking(); |
358 | break; |
359 | |
360 | case EAppSrvWindowPointerCursorMode: |
361 | iReturnValue = gEpocEnv->iDsa != NULL ? |
362 | gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady; |
363 | break; |
364 | case EAppSrvDsaStatus: |
365 | gEpocEnv->iDsa->Stop(); |
366 | iReturnValue = KErrNone; |
367 | break; |
368 | case CDsa::ERequestUpdate: |
369 | gEpocEnv->iDsa->UnlockHWSurfaceRequestComplete(); |
370 | break; |
371 | case EAppSrvNoop: |
372 | break; |
373 | case MSDLObserver::EEventResume: |
374 | case MSDLObserver::EEventSuspend: |
375 | case MSDLObserver::EEventScreenSizeChanged: |
376 | case MSDLObserver::EEventWindowReserved: |
377 | case MSDLObserver::EEventKeyMapInit: |
378 | case MSDLObserver::EEventWindowNotAvailable: |
379 | case MSDLObserver::EEventMainExit: |
380 | iReturnValue = ObserverEvent(iService, iReturnValue); |
381 | HandleObserverValue(iService, iReturnValue, ETrue); |
382 | break; |
383 | default: |
384 | PANIC(KErrNotSupported); |
385 | } |
386 | iStatus = KRequestPending; |
387 | iStatusPtr = &iStatus; |
388 | SetActive(); |
389 | } |
390 | iSema.Signal(); |
391 | } |
392 | |
393 | void CSdlAppServ::DoCancel() |
394 | { |
395 | iSema.Wait(); |
396 | TRequestStatus* s = &iStatus; |
397 | iAppThread.RequestComplete(s, KErrCancel); |
398 | } |
399 | |
400 | |
401 | |
402 | MEventQueue& EpocSdlEnv::EventQueue() |
403 | { |
404 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
405 | return *gEpocEnv->iEventQueue; |
406 | } |
407 | |
408 | |
409 | TBool EpocSdlEnv::Flags(TInt aFlag) |
410 | { |
411 | const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag; |
412 | return flag == aFlag; |
413 | } |
414 | |
415 | TInt EpocSdlEnv::Argc() |
416 | { |
417 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
418 | return gEpocEnv->iArgc; |
419 | } |
420 | |
421 | |
422 | char** EpocSdlEnv::Argv() |
423 | { |
424 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
425 | return gEpocEnv->iArgv; |
426 | } |
427 | |
428 | |
429 | TBool EpocSdlEnv::IsDsaAvailable() |
430 | { |
431 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
432 | return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable(); |
433 | } |
434 | |
435 | |
436 | void EpocSdlEnv::WaitDsaAvailable() |
437 | { |
438 | EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0); |
439 | gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread); |
440 | if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) |
441 | { |
442 | EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0); |
443 | } |
444 | } |
445 | |
446 | void EpocSdlEnv::Suspend() |
447 | { |
448 | if(gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop)) |
449 | { |
450 | // gEpocEnv->iDsa->ReleaseStop(); |
451 | gEpocEnv->iDsa->SetSuspend(); |
452 | RThread().Suspend(); |
453 | EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0); |
454 | } |
455 | } |
456 | |
457 | void EpocSdlEnv::SetWaitDsa() |
458 | { |
459 | if(!IsDsaAvailable()) |
460 | { |
461 | RThread th; |
462 | th.Open(gEpocEnv->iId); |
463 | th.Suspend(); |
464 | th.Close(); |
465 | gEpocEnv->iDsa->SetSuspend(); |
466 | } |
467 | } |
468 | |
469 | void EpocSdlEnv::Resume() |
470 | { |
471 | gEpocEnv->iDsa->Resume(); |
472 | RThread th; |
473 | th.Open(gEpocEnv->iId); |
474 | th.Resume(); |
475 | th.Close(); |
476 | |
477 | const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0); |
478 | gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue); |
479 | } |
480 | |
481 | |
482 | TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode) |
483 | { |
484 | return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode); |
485 | } |
486 | |
487 | TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode) |
488 | { |
489 | return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode); |
490 | } |
491 | |
492 | |
493 | void EpocSdlEnv::UnlockHwSurface() |
494 | { |
495 | gEpocEnv->iDsa->UnlockHwSurface(); |
496 | } |
497 | |
498 | TUint8* EpocSdlEnv::LockHwSurface() |
499 | { |
500 | return gEpocEnv->iDsa->LockHwSurface(); |
501 | } |
502 | |
503 | |
504 | void EpocSdlEnv::UpdateSwSurface() |
505 | { |
506 | gEpocEnv->iDsa->UpdateSwSurface(); |
507 | } |
508 | |
509 | TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect) |
510 | { |
511 | return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect); |
512 | } |
513 | |
514 | void EpocSdlEnv::Request(TInt aService) |
515 | { |
516 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
517 | gEpocEnv->iAppSrv->Request(aService); |
518 | } |
519 | |
520 | |
521 | TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize) |
522 | { |
523 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
524 | if(EpocSdlEnv::Flags(CSDL::EAllowImageResize) && gEpocEnv->iDsa->WindowSize() != aRequestedSize) |
525 | { |
526 | TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize)); |
527 | } |
528 | return gEpocEnv->iDsa->WindowSize(); |
529 | } |
530 | |
531 | TSize EpocSdlEnv::WindowSize() |
532 | { |
533 | __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady)); |
534 | return gEpocEnv->iDsa->WindowSize(); |
535 | } |
536 | |
537 | TDisplayMode EpocSdlEnv::DisplayMode() |
538 | { |
539 | return gEpocEnv->iDsa->DisplayMode(); |
540 | } |
541 | |
542 | TPointerCursorMode EpocSdlEnv::PointerMode() |
543 | { |
544 | return static_cast<TPointerCursorMode> |
545 | (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode)); |
546 | } |
547 | |
548 | TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette) |
549 | { |
550 | return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette); |
551 | } |
552 | |
553 | void EpocSdlEnv::PanicMain(TInt aErr) |
554 | { |
555 | gEpocEnv->iAppSrv->PanicMain(aErr); |
556 | } |
557 | |
558 | |
559 | TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem) |
560 | { |
561 | TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem)); |
562 | return err; |
563 | } |
564 | |
565 | void EpocSdlEnv::RemoveCleanupItem(TAny* aItem) |
566 | { |
567 | for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++) |
568 | { |
569 | if(gEpocEnv->iCleanupItems->At(i).iItem == aItem) |
570 | gEpocEnv->iCleanupItems->Delete(i); |
571 | } |
572 | } |
573 | |
574 | void EpocSdlEnv::CleanupItems() |
575 | { |
576 | const TThreadId id = RThread().Id(); |
577 | TInt last = gEpocEnv->iCleanupItems->Count() - 1; |
578 | TInt i; |
579 | for(i = last; i >= 0 ; i--) |
580 | { |
581 | TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); |
582 | if(item.iThread == id) |
583 | { |
584 | item.iThread = TThreadId(0); |
585 | item.iOperation(item.iItem); |
586 | } |
587 | } |
588 | last = gEpocEnv->iCleanupItems->Count() - 1; |
589 | for(i = last; i >= 0 ; i--) |
590 | { |
591 | TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i); |
592 | if(item.iThread == TThreadId(0)) |
593 | { |
594 | gEpocEnv->iCleanupItems->Delete(i); |
595 | } |
596 | } |
597 | } |
598 | |
599 | void EpocSdlEnv::FreeSurface() |
600 | { |
601 | Request(CSdlAppServ::EAppSrvDsaStatus); |
602 | gEpocEnv->iDsa->Free(); |
603 | } |
604 | |
605 | void EpocSdlEnv::LockPalette(TBool aLock) |
606 | { |
607 | gEpocEnv->iDsa->LockPalette(aLock); |
608 | } |
609 | |
610 | void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam) |
611 | { |
612 | const TBool sdlThread = RThread().Id() == gEpocEnv->iId; |
613 | const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam); |
614 | gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread); |
615 | if(sdlThread) |
616 | { |
617 | gEpocEnv->iAppSrv->SetParam(aParam); |
618 | const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService); |
619 | gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse); |
620 | } |
621 | } |
622 | |
623 | |
624 | TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint) |
625 | { |
626 | return gEpocEnv->iDsa->WindowCoordinates(aPoint); |
627 | } |
628 | |
629 | void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr) |
630 | { |
631 | gEpocEnv->iAppSrv->PanicMain(aInfo, aErr); |
632 | } |
633 | //Dsa is a low priority ao, it has to wait if its pending event, but ws |
634 | //event has been prioritized before it |
635 | //this is not called from app thread! |
636 | void EpocSdlEnv::WaitDeviceChange() |
637 | { |
638 | LockPalette(ETrue); |
639 | gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa); |
640 | const TSize sz = WindowSize(); |
641 | const TInt param = reinterpret_cast<TInt>(&sz); |
642 | ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param); |
643 | |
644 | // RThread().Suspend(); |
645 | } |
646 | |
647 | LOCAL_C TBool CheckSdl() |
648 | { |
649 | TInt isExit = ETrue; |
650 | RThread sdl; |
651 | if(sdl.Open(gEpocEnv->iId) == KErrNone) |
652 | { |
653 | if(sdl.ExitType() == EExitPending) |
654 | { |
655 | isExit = EFalse; |
656 | } |
657 | sdl.Close(); |
658 | } |
659 | return isExit; |
660 | } |
661 | |
662 | void EpocSdlEnvData::Free() |
663 | { |
664 | if(RThread().Id() == gEpocEnv->iId) |
665 | { |
666 | iDsa->Free(); |
667 | return; |
668 | } |
669 | |
670 | __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady)); |
671 | |
672 | for(TInt i = 0; i < iArgc; i++) |
673 | User::Free( iArgv[i] ); |
674 | |
675 | User::Free(iArgv); |
676 | |
677 | |
678 | delete iEventQueue; |
679 | |
680 | if(iDsa != NULL) |
681 | iDsa->Free(); |
682 | |
683 | delete iDsa; |
684 | delete iAppSrv; |
685 | } |
686 | |
687 | _LIT(KSDLMain, "SDLMain"); |
688 | |
689 | LOCAL_C int MainL() |
690 | { |
691 | gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat<TSdlCleanupItem>(8); |
692 | |
693 | char** envp=0; |
694 | /* !! process exits here if there is "exit()" in main! */ |
695 | int ret = 0; |
696 | for(TInt i = 0; i < 6; i++) |
697 | { |
698 | void* f = (void*) gEpocEnv->iMain[i]; |
699 | if(f != NULL) |
700 | { |
701 | switch(i) |
702 | { |
703 | case 0: |
704 | ret = ((mainfunc1)f)(); |
705 | return ret; |
706 | case 3: |
707 | ((mainfunc1)f)(); |
708 | return ret; |
709 | case 1: |
710 | ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); |
711 | return ret; |
712 | case 4: |
713 | ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv()); |
714 | return ret; |
715 | case 2: |
716 | ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); |
717 | return ret; |
718 | case 5: |
719 | ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp); |
720 | return ret; |
721 | } |
722 | } |
723 | } |
724 | PANIC(KErrNotFound); |
725 | return 0; |
726 | } |
727 | |
728 | LOCAL_C TInt DoMain(TAny* /*aParam*/) |
729 | { |
730 | |
731 | |
732 | CTrapCleanup* cleanup = CTrapCleanup::New(); |
733 | |
734 | TBool fbsconnected = EFalse; |
735 | if(RFbsSession::GetSession() == NULL) |
736 | { |
737 | PANIC_IF_ERROR(RFbsSession::Connect()); |
738 | fbsconnected = ETrue; |
739 | } |
740 | |
741 | gEpocEnv->iAppSrv->Init(); |
742 | |
743 | #ifdef SYMBIANC |
744 | // Create stdlib |
745 | _REENT; |
746 | #endif |
747 | |
748 | // Call stdlib main |
749 | int ret = 0; |
750 | |
751 | //completes waiting rendesvous |
752 | RThread::Rendezvous(KErrNone); |
753 | |
754 | TRAPD(err, err = MainL()); |
755 | |
756 | EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err); |
757 | |
758 | // Free resources and return |
759 | |
760 | EpocSdlEnv::CleanupItems(); |
761 | |
762 | gEpocEnv->iCleanupItems->Reset(); |
763 | delete gEpocEnv->iCleanupItems; |
764 | gEpocEnv->iCleanupItems = NULL; |
765 | |
766 | gEpocEnv->Free(); //free up in thread resources |
767 | |
768 | #ifdef SYMBIANC |
769 | _cleanup(); //this is normally called at exit, I call it here |
770 | #endif |
771 | |
772 | if(fbsconnected) |
773 | RFbsSession::Disconnect(); |
774 | |
775 | #ifdef SYMBIANC |
776 | CloseSTDLIB(); |
777 | #endif |
778 | |
779 | // delete as; |
780 | delete cleanup; |
781 | |
782 | return err == KErrNone ? ret : err;; |
783 | } |
784 | |
785 | |
786 | |
787 | EXPORT_C CSDL::~CSDL() |
788 | { |
789 | gEpocEnv->Free(); |
790 | User::Free(gEpocEnv); |
791 | gEpocEnv->iSdl = NULL; |
792 | } |
793 | |
794 | EXPORT_C CSDL* CSDL::NewL(TInt aFlags) |
795 | { |
796 | __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists)); |
797 | gEpocEnv = (EpocSdlEnvData*) User::AllocL(sizeof(EpocSdlEnvData)); |
798 | Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData)); |
799 | |
800 | gEpocEnv->iEpocEnvFlags = aFlags; |
801 | gEpocEnv->iEventQueue = CEventQueue::NewL(); |
802 | |
803 | gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ(); |
804 | gEpocEnv->iAppSrv->ConstructL(); |
805 | |
806 | CSDL* sdl = new (ELeave) CSDL(); |
807 | |
808 | gEpocEnv->iSdl = sdl; |
809 | |
810 | return sdl; |
811 | } |
812 | |
813 | /* |
814 | EXPORT_C void CSDL::ReInitL(TFlags aFlags) |
815 | { |
816 | const TFlags prevFlags = gEpocEnv->iEpocEnvFlags; |
817 | gEpocEnv->iEpocEnvFlags = aFlags; |
818 | TInt err = KErrNone; |
819 | if(((prevFlags & EDrawModeDSB) != (aFlags & EDrawModeDSB)) && gEpocEnv->iDsa) |
820 | { |
821 | delete gEpocEnv->iDsa; |
822 | gEpocEnv->iDsa = NULL; |
823 | gEpocEnv->iDsa = CDsa::RecreateL(EpocSdlEnv::Flags(CSDL::EDrawModeDSB)); |
824 | } |
825 | } |
826 | */ |
827 | |
828 | |
829 | EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice) |
830 | { |
831 | if(gEpocEnv->iDsa == NULL) |
832 | gEpocEnv->iDsa = CDsa::CreateL(aSession); |
833 | gEpocEnv->iDsa->ConstructL(aWindow, aDevice); |
834 | } |
835 | |
836 | |
837 | EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, TInt aFlags, TInt aStackSize) |
838 | { |
839 | ASSERT(gEpocEnv != NULL); |
840 | gEpocEnv->iMain = aFunc; |
841 | const TBool args = aArg != NULL; |
842 | |
843 | gEpocEnv->iArgc = aArg->Count() + 1; |
844 | gEpocEnv->iArgv = (char**) User::AllocL(sizeof(char*) * (gEpocEnv->iArgc + 1)); |
845 | |
846 | TInt k = 0; |
847 | const TFileName processName = RProcess().FileName(); |
848 | const TInt len = processName.Length(); |
849 | gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); |
850 | Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len); |
851 | gEpocEnv->iArgv[k][len] = 0; |
852 | |
853 | for(TInt i = 0; args && (i < aArg->Count()); i++) |
854 | { |
855 | k++; |
856 | const TInt len = aArg->MdcaPoint(i).Length(); |
857 | gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1); |
858 | Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len); |
859 | gEpocEnv->iArgv[k][len] = 0; |
860 | } |
861 | |
862 | gEpocEnv->iArgv[gEpocEnv->iArgc] = NULL; |
863 | |
864 | RThread thread; |
865 | User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL)); |
866 | |
867 | if(aStatus != NULL) |
868 | { |
869 | thread.Logon(*aStatus); |
870 | } |
871 | |
872 | gEpocEnv->iId = thread.Id(); |
873 | thread.SetPriority(EPriorityLess); |
874 | if((aFlags & CSDL::ERequestResume) == 0) |
875 | { |
876 | thread.Resume(); |
877 | } |
878 | thread.Close(); |
879 | return gEpocEnv->iId; |
880 | } |
881 | |
882 | EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent) |
883 | { |
884 | return EpocSdlEnv::EventQueue().Append(aEvent); |
885 | } |
886 | |
887 | EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr) |
888 | { |
889 | EpocSdlEnv::PanicMain(aInfo, aErr); |
890 | } |
891 | |
892 | EXPORT_C TInt CSDL::GetSDLCode(TInt aScanCode) |
893 | { |
894 | if(aScanCode < 0) |
895 | return MAX_SCANCODE; |
896 | if(aScanCode >= MAX_SCANCODE) |
897 | return -1; |
898 | return KeyMap()[aScanCode]; |
899 | } |
900 | |
901 | EXPORT_C TInt CSDL::SDLCodesCount() const |
902 | { |
903 | return MAX_SCANCODE; |
904 | } |
905 | |
906 | EXPORT_C void CSDL::ResetSDLCodes() |
907 | { |
908 | ResetKeyMap(); |
909 | } |
910 | |
911 | EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode) |
912 | { |
913 | gEpocEnv->iDsa->SetOrientation(aMode); |
914 | } |
915 | |
916 | EXPORT_C TInt CSDL::SetSDLCode(TInt aScanCode, TInt aSDLCode) |
917 | { |
918 | const TInt current = GetSDLCode(aScanCode); |
919 | if(aScanCode >= 0 && aScanCode < MAX_SCANCODE) |
920 | KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode); |
921 | return current; |
922 | } |
923 | |
924 | |
925 | EXPORT_C MSDLObserver* CSDL::Observer() |
926 | { |
927 | return gEpocEnv->iAppSrv->Observer(); |
928 | } |
929 | |
930 | EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver) |
931 | { |
932 | gEpocEnv->iAppSrv->SetObserver(aObserver); |
933 | } |
934 | |
935 | EXPORT_C void CSDL::Resume() |
936 | { |
937 | EpocSdlEnv::Resume(); |
938 | } |
939 | |
940 | EXPORT_C void CSDL::Suspend() |
941 | { |
942 | gEpocEnv->iDsa->DoStop(); |
943 | } |
944 | |
945 | EXPORT_C CSDL::CSDL() |
946 | { |
947 | } |
948 | |
949 | EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const |
950 | { |
951 | gEpocEnv->iAppUi = &aAppUi; |
952 | EnvUtils::DisableKeyBlocking(); |
953 | } |
954 | |
955 | EXPORT_C TInt CSDL::SetBlitter(MBlitter* aBlitter) |
956 | { |
957 | if(gEpocEnv && gEpocEnv->iDsa) |
958 | { |
959 | gEpocEnv->iDsa->SetBlitter(aBlitter); |
960 | return KErrNone; |
961 | } |
962 | return KErrNotReady; |
963 | } |
964 | |
965 | |
966 | EXPORT_C TInt CSDL::AppendOverlay(MOverlay& aOverlay, TInt aPriority) |
967 | { |
968 | if(gEpocEnv && gEpocEnv->iDsa) |
969 | { |
970 | return gEpocEnv->iDsa->AppendOverlay(aOverlay, aPriority); |
971 | } |
972 | return KErrNotReady; |
973 | } |
974 | |
975 | EXPORT_C TInt CSDL::RemoveOverlay(MOverlay& aOverlay) |
976 | { |
977 | if(gEpocEnv && gEpocEnv->iDsa) |
978 | { |
979 | return gEpocEnv->iDsa->RemoveOverlay(aOverlay); |
980 | } |
981 | return KErrNotReady; |
982 | } |
983 | |
984 | EXPORT_C TInt CSDL::RedrawRequest() |
985 | { |
986 | if(gEpocEnv && gEpocEnv->iDsa) |
987 | { |
988 | return gEpocEnv->iDsa->RedrawRequest(); |
989 | } |
990 | return KErrNotReady; |
991 | } |
992 | |
993 | /* |
994 | EXPORT_C CSDL* CSDL::Current() |
995 | { |
996 | return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL; |
997 | } |
998 | |
999 | |
1000 | EXPORT_C TInt CSDL::SetVolume(TInt aVolume) |
1001 | { |
1002 | return EpocSdlEnv::SetVolume(aVolume); |
1003 | } |
1004 | |
1005 | EXPORT_C TInt CSDL::Volume() const |
1006 | { |
1007 | return EpocSdlEnv::Volume(); |
1008 | } |
1009 | |
1010 | EXPORT_C TInt CSDL::MaxVolume() const |
1011 | { |
1012 | return EpocSdlEnv::MaxVolume(); |
1013 | } |
1014 | */ |
1015 | |
1016 | void EnvUtils::DisableKeyBlocking() |
1017 | { |
1018 | if(gEpocEnv->iAppUi != NULL) |
1019 | return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking(); |
1020 | } |
1021 | |
1022 | TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus) |
1023 | { |
1024 | if(gEpocEnv->iId != TThreadId(0) && |
1025 | aThread.Open(gEpocEnv->iId) && |
1026 | aThread.ExitType() == EExitPending) |
1027 | { |
1028 | aThread.Rendezvous(aStatus); |
1029 | return ETrue; |
1030 | } |
1031 | return EFalse; |
1032 | } |
1033 | |
1034 | |
1035 | |