Add manual orientation switching support.
[SDL.s60v3.git] / src / main / symbian / SDL_main.cpp
blob96f7298ba07c59e010f29d0bba1793da81e1e5b8
1 extern "C" {
2 #include "SDL_events_c.h"
4 #include <queue>
5 #include "epoc_sdl.h"
6 #include "sdlepocapi.h"
7 #include <e32base.h>
8 #include <estlib.h>
9 #include <stdio.h>
10 #include <badesca.h>
11 #include <w32std.h>
12 #include <aknappui.h>
13 #include <aknapp.h>
14 #include "SDL_epocevents_c.h"
15 #include "SDL_keysym.h"
16 #include "dsa.h"
17 #include "SDL_loadso.h"
19 extern SDLKey* KeyMap();
20 extern void ResetKeyMap();
22 class CCurrentAppUi;
23 class CEikonEnv;
24 class CSdlAppServ;
25 class CEventQueue;
27 NONSHARABLE_CLASS(EpocSdlEnvData)
29 public:
30 void Free();
31 void Delete();
32 CEventQueue* iEventQueue;
33 TMainFunc iMain;
34 int iEpocEnvFlags;
35 int iArgc;
36 char** iArgv;
37 CDsa* iDsa;
38 CSdlAppServ* iAppSrv;
39 TThreadId iId;
40 CArrayFix<TSdlCleanupItem>* iCleanupItems;
41 CSDL* iSdl;
42 TRequestStatus* iCallerStatus;
43 bool iWaitingForOrientationChange;
45 TSize iSize;
46 TDisplayMode iMode;
49 EpocSdlEnvData* gEpocEnv;
51 NONSHARABLE_CLASS(EnvUtils)
53 public:
54 static inline TBool IsOwnThreaded();
55 static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus);
56 static void RunSingleThread();
59 inline TBool EnvUtils::IsOwnThreaded()
61 return gEpocEnv->iEpocEnvFlags & CSDL::EOwnThread;
64 void EnvUtils::RunSingleThread()
66 if(!EnvUtils::IsOwnThreaded())
68 int count = RThread().RequestCount();
69 if(count > 0)
71 int err;
72 if(CActiveScheduler::RunIfReady(err, CActive::EPriorityIdle))
74 CActiveScheduler::Current()->WaitForAnyRequest();
80 int Panic(int aErr, int aLine)
82 TBuf<64> b;
83 b.Format(_L("Main at %d"), aLine);
84 User::Panic(b, aErr);
85 return 0;
89 class CEventQueue : public CBase, public MEventQueue
91 public:
92 void ConstructL();
93 ~CEventQueue();
94 int Append(const TWsEvent& aEvent);
95 const TWsEvent Shift();
96 void Lock();
97 void Unlock();
98 TBool HasData();
100 private:
101 std::queue<TWsEvent> m_queue;
102 RCriticalSection iCS;
105 void CEventQueue::ConstructL()
107 if(EnvUtils::IsOwnThreaded())
108 User::LeaveIfError(iCS.CreateLocal());
111 CEventQueue::~CEventQueue()
113 iCS.Close();
116 int CEventQueue::Append(const TWsEvent& aEvent)
118 Lock();
119 m_queue.push(aEvent);
120 Unlock();
121 return 0;
125 TBool CEventQueue::HasData()
127 EnvUtils::RunSingleThread();
128 return !m_queue.empty();
131 void CEventQueue::Lock()
133 if(EnvUtils::IsOwnThreaded())
134 iCS.Wait();
137 void CEventQueue::Unlock()
139 if(EnvUtils::IsOwnThreaded())
140 iCS.Signal();
143 const TWsEvent CEventQueue::Shift()
145 const TWsEvent event = m_queue.front();
146 m_queue.pop();
147 return event;
151 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) :
152 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
155 #define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
157 MAINFUNC(1)
158 MAINFUNC(2)
159 MAINFUNC(3)
160 MAINFUNC(4)
161 MAINFUNC(5)
162 MAINFUNC(6)
164 EXPORT_C TMainFunc::TMainFunc()
166 Mem::FillZ(iMainFunc, sizeof(iMainFunc));
170 const void* TMainFunc::operator[](int aIndex) const
172 return iMainFunc[aIndex];
176 NONSHARABLE_CLASS(CSdlAppServ) : public CActive
178 public:
179 enum
181 EAppSrvNoop = CDsa::ELastDsaRequest,
182 EAppSrvWindowWidth,
183 EAppSrvWindowHeight,
184 EAppSrvWindowDisplayMode,
185 EAppSrvWindowPointerCursorMode,
186 EAppSrvDsaStatus,
187 EAppSrvStopThread,
188 EAppSrvWaitDsa
190 CSdlAppServ();
191 void ConstructL();
192 ~CSdlAppServ();
193 int Request(int aService);
194 int RequestValue(int aService);
195 void Init();
196 void PanicMain(int aReason);
197 void PanicMain(const TDesC& aInfo, int aReason);
198 void SetObserver(MSDLObserver* aObserver);
199 int ObserverEvent(int aEvent, int aParam);
200 void SetParam(int aParam);
201 void HandleObserverValue(int aService, int aReturnValue, TBool aMainThread);
202 MSDLObserver* Observer();
204 private:
205 void RunL();
206 void DoCancel();
207 const TThreadId iMainId;
208 RThread iAppThread;
209 int iService;
210 int iReturnValue;
211 RSemaphore iSema;
212 MSDLObserver* iObserver;
213 TRequestStatus* iStatusPtr;
216 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id()), iObserver( NULL )
220 MSDLObserver* CSdlAppServ::Observer()
222 return iObserver;
225 void CSdlAppServ::SetObserver(MSDLObserver* aObserver)
227 iObserver = aObserver;
230 int CSdlAppServ::ObserverEvent(int aEvent, int aParam)
232 if(iObserver != NULL)
234 if(RThread().Id() == gEpocEnv->iId && EnvUtils::IsOwnThreaded())
236 return iObserver->SdlThreadEvent(aEvent, aParam);
238 else if(RThread().Id() == iMainId)
240 return iObserver->SdlEvent(aEvent, aParam);
242 PANIC(KErrNotSupported);
244 return 0;
247 void CSdlAppServ::PanicMain(int aReason)
249 iAppThread.Panic(RThread().Name(), aReason);
252 void CSdlAppServ::PanicMain(const TDesC& aInfo, int aReason)
254 iAppThread.Panic(aInfo, aReason);
257 void CSdlAppServ::ConstructL()
259 CActiveScheduler::Add(this);
260 if(EnvUtils::IsOwnThreaded())
261 User::LeaveIfError(iSema.CreateLocal(1));
262 iStatus = KRequestPending;
263 iStatusPtr = &iStatus;
264 SetActive();
267 CSdlAppServ::~CSdlAppServ()
269 Cancel();
270 if(iSema.Handle() != NULL)
271 iSema.Signal();
272 iSema.Close();
273 iAppThread.Close();
276 int CSdlAppServ::Request(int aService)
278 if(EnvUtils::IsOwnThreaded())
280 if(RThread().Id() == iAppThread.Id())
281 return KErrBadHandle;
282 iSema.Wait();
284 EnvUtils::RunSingleThread();
285 iService = aService;
286 iAppThread.RequestComplete(iStatusPtr, KErrNone);
287 return KErrNone;
290 int CSdlAppServ::RequestValue(int aService)
292 Request(aService);
293 Request(EAppSrvNoop);
294 return iReturnValue;
297 void CSdlAppServ::Init()
299 PANIC_IF_ERROR(iAppThread.Open(iMainId));
302 void CSdlAppServ::SetParam(int aParam)
304 iReturnValue = aParam;
307 void CSdlAppServ::HandleObserverValue(int aService, int aReturnValue, TBool aMainThread)
309 if(iObserver != NULL && aMainThread)
311 switch(aService)
313 case MSDLObserver::EEventScreenSizeChanged:
314 if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette)
315 EpocSdlEnv::LockPalette(EFalse);
316 break;
319 if(!aMainThread && aService == MSDLObserver::EEventSuspend)
321 if(iObserver == NULL || (gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend))
323 EpocSdlEnv::Suspend();
328 void CSdlAppServ::RunL()
330 if(iStatus == KErrNone)
332 switch(iService)
334 case CSdlAppServ::EAppSrvWaitDsa:
335 EpocSdlEnv::SetWaitDsa();
336 iReturnValue = EpocSdlEnv::IsDsaAvailable();
337 break;
339 case CSdlAppServ::EAppSrvStopThread:
340 if(gEpocEnv->iDsa != NULL)
341 gEpocEnv->iDsa->SetSuspend();
342 break;
344 case EAppSrvWindowPointerCursorMode:
345 iReturnValue = gEpocEnv->iDsa != NULL ? gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady;
346 break;
348 case EAppSrvDsaStatus:
349 if(gEpocEnv->iDsa != NULL)
350 gEpocEnv->iDsa->Stop();
351 iReturnValue = KErrNone;
352 break;
354 case EAppSrvNoop:
355 break;
357 case MSDLObserver::EEventResume:
358 case MSDLObserver::EEventSuspend:
359 case MSDLObserver::EEventScreenSizeChanged:
360 case MSDLObserver::EEventWindowReserved:
361 case MSDLObserver::EEventKeyMapInit:
362 case MSDLObserver::EEventWindowNotAvailable:
363 case MSDLObserver::EEventMainExit:
364 iReturnValue = ObserverEvent(iService, iReturnValue);
365 HandleObserverValue(iService, iReturnValue, ETrue);
366 break;
368 default:
369 PANIC(KErrNotSupported);
370 break;
373 iStatus = KRequestPending;
374 iStatusPtr = &iStatus;
375 SetActive();
378 if(EnvUtils::IsOwnThreaded())
379 iSema.Signal();
382 void CSdlAppServ::DoCancel()
384 if(EnvUtils::IsOwnThreaded())
385 iSema.Wait();
386 TRequestStatus* s = &iStatus;
387 iAppThread.RequestComplete(s, KErrCancel);
390 MEventQueue& EpocSdlEnv::EventQueue()
392 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
393 return *gEpocEnv->iEventQueue;
397 TBool EpocSdlEnv::Flags(int aFlag)
399 const int flag = gEpocEnv->iEpocEnvFlags & aFlag;
400 return flag == aFlag;
403 int EpocSdlEnv::Argc()
405 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
406 return gEpocEnv->iArgc;
409 char** EpocSdlEnv::Argv()
411 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
412 return gEpocEnv->iArgv;
415 TBool EpocSdlEnv::IsDsaAvailable()
417 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
418 return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
421 void EpocSdlEnv::WaitDsaAvailable()
423 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0);
424 gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
425 if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
427 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0);
431 void EpocSdlEnv::Suspend()
433 if(gEpocEnv->iDsa != NULL && (gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop)))
435 gEpocEnv->iDsa->SetSuspend();
436 if(EnvUtils::IsOwnThreaded())
438 RThread().Suspend();
439 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0);
444 void EpocSdlEnv::SetWaitDsa()
446 if(!IsDsaAvailable())
448 if(EnvUtils::IsOwnThreaded())
450 RThread th;
451 th.Open(gEpocEnv->iId);
452 th.Suspend();
453 th.Close();
455 if(gEpocEnv->iDsa != NULL)
456 gEpocEnv->iDsa->SetSuspend();
460 void EpocSdlEnv::Resume()
462 if(gEpocEnv->iDsa != NULL)
464 gEpocEnv->iDsa->Resume();
466 if(EnvUtils::IsOwnThreaded())
468 RThread th;
469 th.Open(gEpocEnv->iId);
470 th.Resume();
471 th.Close();
473 const int value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0);
474 gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue);
477 int EpocSdlEnv::AllocSurface(const TSize& aSize, TDisplayMode aMode)
479 return gEpocEnv->iDsa->AllocSurface(aSize, aMode);
482 void EpocSdlEnv::UnlockHwSurface()
484 gEpocEnv->iDsa->UnlockHwSurface();
487 TUint8* EpocSdlEnv::LockHwSurface()
489 return gEpocEnv->iDsa->LockHwSurface();
492 void EpocSdlEnv::UpdateSwSurface()
494 gEpocEnv->iDsa->UpdateSwSurface();
497 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
499 return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
502 void EpocSdlEnv::Request(int aService)
504 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
505 gEpocEnv->iAppSrv->Request(aService);
508 TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize)
510 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
511 return gEpocEnv->iDsa == NULL ? TSize(0, 0) : gEpocEnv->iDsa->WindowSize();
514 TSize EpocSdlEnv::WindowSize()
516 __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
517 return gEpocEnv->iDsa == NULL ? TSize(0, 0) : gEpocEnv->iDsa->WindowSize();
520 TDisplayMode EpocSdlEnv::DisplayMode()
522 return gEpocEnv->iDsa == NULL ? ENone : gEpocEnv->iDsa->DisplayMode();
525 TPointerCursorMode EpocSdlEnv::PointerMode()
527 return static_cast<TPointerCursorMode>(gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
530 int EpocSdlEnv::SetPalette(int aFirstcolor, int aColorCount, TUint32* aPalette)
532 return gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
535 void EpocSdlEnv::PanicMain(int aErr)
537 gEpocEnv->iAppSrv->PanicMain(aErr);
541 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
543 TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
544 return err;
547 void EpocSdlEnv::RemoveCleanupItem(TAny* aItem)
549 for(int i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
551 if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
552 gEpocEnv->iCleanupItems->Delete(i);
556 void EpocSdlEnv::CleanupItems()
558 const TThreadId id = RThread().Id();
559 int last = gEpocEnv->iCleanupItems->Count() - 1;
560 int i;
562 for(i = last; i >= 0 ; i--)
564 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
565 if(item.iThread == id)
567 item.iThread = TThreadId(0);
568 item.iOperation(item.iItem);
572 last = gEpocEnv->iCleanupItems->Count() - 1;
574 for(i = last; i >= 0 ; i--)
576 TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
577 if(item.iThread == TThreadId(0))
579 gEpocEnv->iCleanupItems->Delete(i);
584 void EpocSdlEnv::FreeSurface()
586 Request(CSdlAppServ::EAppSrvDsaStatus);
587 if(gEpocEnv->iDsa != NULL)
588 gEpocEnv->iDsa->Free();
591 void EpocSdlEnv::LockPalette(TBool aLock)
593 gEpocEnv->iDsa->LockPalette(aLock);
596 void EpocSdlEnv::ObserverEvent(int aService, int aParam)
598 const TBool sdlThread = RThread().Id() == gEpocEnv->iId;
599 const int valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam);
600 gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread);
601 if(sdlThread)
603 gEpocEnv->iAppSrv->SetParam(aParam);
604 const int valuet = gEpocEnv->iAppSrv->RequestValue(aService);
605 gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse);
609 TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint)
611 return gEpocEnv->iDsa == NULL ? aPoint : gEpocEnv->iDsa->WindowCoordinates(aPoint);
614 void EpocSdlEnv::PanicMain(const TDesC& aInfo, int aErr)
616 gEpocEnv->iAppSrv->PanicMain(aInfo, aErr);
619 //Dsa is a low priority ao, it has to wait if its pending event, but ws
620 //event has been prioritized before it
621 //this is not called from app thread!
622 void EpocSdlEnv::WaitDeviceChange()
624 LockPalette(ETrue);
625 gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
626 const TSize sz = WindowSize();
627 const int param = reinterpret_cast<int>(&sz);
628 ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
631 LOCAL_C TBool CheckSdl()
633 int isExit = ETrue;
634 RThread sdl;
635 if(sdl.Open(gEpocEnv->iId) == KErrNone)
637 if(sdl.ExitType() == EExitPending)
639 isExit = EFalse;
641 sdl.Close();
643 return isExit;
646 void EpocSdlEnvData::Free()
648 if(RThread().Id() == gEpocEnv->iId)
650 if(iDsa != NULL)
651 iDsa->Free();
652 return;
655 __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady));
658 void EpocSdlEnvData::Delete()
660 for(int i = 0; i <= iArgc; i++)
662 if(iArgv != NULL)
663 delete[] iArgv[i];
666 delete[] iArgv;
668 iArgv = NULL;
669 iArgc = 0;
671 delete iEventQueue;
673 if(iDsa != NULL)
674 iDsa->Free();
676 delete iDsa;
677 delete iAppSrv;
680 _LIT(KSDLMain, "SDLMain");
682 LOCAL_C int MainL()
684 gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat<TSdlCleanupItem>(8);
686 char** envp=0;
687 /* !! process exits here if there is "exit()" in main! */
688 int ret = 0;
689 for(int i = 0; i < 6; i++)
691 void* f = (void*) gEpocEnv->iMain[i];
692 if(f != NULL)
694 switch(i)
696 case 0:
697 ret = ((mainfunc1)f)();
698 return ret;
700 case 3:
701 ((mainfunc1)f)();
702 return ret;
704 case 1:
705 ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
706 return ret;
708 case 4:
709 ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
710 return ret;
712 case 2:
713 ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
714 return ret;
716 case 5:
717 ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
718 return ret;
722 PANIC(KErrNotFound);
723 return 0;
726 LOCAL_C int DoMain(TAny* /*aParam*/)
728 TBool fbsconnected = EFalse;
729 CTrapCleanup* cleanup = NULL;
731 if(EnvUtils::IsOwnThreaded())
733 cleanup = CTrapCleanup::New();
735 if(RFbsSession::GetSession() == NULL)
737 PANIC_IF_ERROR(RFbsSession::Connect());
738 fbsconnected = ETrue;
741 gEpocEnv->iAppSrv->Init();
743 // Call stdlib main
744 int ret = 0;
745 if(EnvUtils::IsOwnThreaded())
747 //completes waiting rendesvous
748 RThread::Rendezvous(KErrNone);
751 TRAPD(err, err = MainL());
753 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err);
755 // Free resources and return
756 EpocSdlEnv::CleanupItems();
758 gEpocEnv->iCleanupItems->Reset();
759 delete gEpocEnv->iCleanupItems;
760 gEpocEnv->iCleanupItems = NULL;
762 gEpocEnv->Free(); //free up in thread resources
764 if(fbsconnected)
765 RFbsSession::Disconnect();
767 delete cleanup;
769 if(gEpocEnv->iCallerStatus != NULL)
771 User::RequestComplete(gEpocEnv->iCallerStatus, err);
772 return 0;
774 else
776 return err == KErrNone ? ret : err;
780 EXPORT_C CSDL::~CSDL()
782 gEpocEnv->Free();
783 gEpocEnv->Delete();
785 delete gEpocEnv;
786 gEpocEnv = NULL;
789 EXPORT_C CSDL* CSDL::NewL(int aFlags)
791 __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
792 gEpocEnv = new EpocSdlEnvData;
793 Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
795 gEpocEnv->iEpocEnvFlags = aFlags;
796 gEpocEnv->iEventQueue = new (ELeave) CEventQueue();
797 gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ();
799 CSDL* sdl = new (ELeave) CSDL();
801 gEpocEnv->iSdl = sdl;
803 return sdl;
806 EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
808 if(gEpocEnv->iDsa == NULL)
809 gEpocEnv->iDsa = CDsa::CreateL(aSession);
810 gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
813 int EpocSdlEnv::ApplyGlesDsa()
815 CDsa* dsa = NULL;
816 TRAPD(err, dsa = gEpocEnv->iDsa->CreateGlesDsaL());
817 gEpocEnv->iDsa = dsa;
818 return err;
821 RWindow* EpocSdlEnv::Window()
823 return gEpocEnv->iDsa->Window();
826 void EpocSdlEnv::UpdateWholeScreen(bool val)
828 gEpocEnv->iDsa->m_updateWholeScreen = val;
831 bool EpocSdlEnv::GetUpdateWholeScreen()
833 return gEpocEnv->iDsa->m_updateWholeScreen;
836 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation, const TSize& aSize, TDisplayMode aMode)
838 gEpocEnv->iWaitingForOrientationChange = true;
839 gEpocEnv->iSize = aSize;
840 gEpocEnv->iMode = aMode;
842 TRAPD(err, static_cast<CAknAppUi*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation));
845 EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, int aStackSize)
847 ASSERT(gEpocEnv != NULL);
848 gEpocEnv->iMain = aFunc;
849 const TBool args = aArg != NULL;
851 if(gEpocEnv->iArgv != NULL)
852 User::Leave(KErrAlreadyExists);
854 gEpocEnv->iArgc = args ? aArg->Count() + 1 : 0;
855 gEpocEnv->iArgv = new char*[gEpocEnv->iArgc + 2];
857 int k = 0;
858 const TFileName processName = RProcess().FileName();
859 const int len = processName.Length();
860 gEpocEnv->iArgv[k] = new char[len + 1];
861 Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len);
862 gEpocEnv->iArgv[k][len] = 0;
864 for(int i = 0; args && (i < aArg->Count()); i++)
866 k++;
867 const int len = aArg->MdcaPoint(i).Length();
868 gEpocEnv->iArgv[k] = new char[len + 1];
869 Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len);
870 gEpocEnv->iArgv[k][len] = 0;
873 gEpocEnv->iArgv[k + 1] = NULL;
875 gEpocEnv->iEventQueue->ConstructL();
876 gEpocEnv->iAppSrv->ConstructL();
878 if(EnvUtils::IsOwnThreaded())
880 RThread thread;
881 User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL));
883 if(aStatus != NULL)
885 thread.Logon(*aStatus);
888 gEpocEnv->iId = thread.Id();
889 thread.SetPriority(EPriorityLess);
890 thread.Resume();
891 thread.Close();
893 else
895 gEpocEnv->iCallerStatus = aStatus;
896 if(aStatus != NULL)
897 *aStatus = KRequestPending;
898 gEpocEnv->iId = RThread().Id();
899 // when priority is not lowered screen updates much more frequently, which
900 // may be undesired, for example in case of openttd's generating world dialog
901 RThread().SetPriority(EPriorityLess);
902 DoMain( NULL );
905 return gEpocEnv->iId;
908 EXPORT_C int CSDL::AppendWsEvent(const TWsEvent& aEvent)
910 return EpocSdlEnv::EventQueue().Append(aEvent);
913 EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, int aErr)
915 EpocSdlEnv::PanicMain(aInfo, aErr);
918 EXPORT_C int CSDL::GetSDLCode(int aScanCode)
920 if(aScanCode < 0)
921 return MAX_SCANCODE;
922 if(aScanCode >= MAX_SCANCODE)
923 return -1;
924 return KeyMap()[aScanCode];
927 EXPORT_C int CSDL::SDLCodesCount() const
929 return MAX_SCANCODE;
932 EXPORT_C void CSDL::ResetSDLCodes()
934 ResetKeyMap();
937 EXPORT_C int CSDL::SetSDLCode(int aScanCode, int aSDLCode)
939 const int current = GetSDLCode(aScanCode);
940 if(aScanCode >= 0 && aScanCode < MAX_SCANCODE)
941 KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode);
942 return current;
946 EXPORT_C MSDLObserver* CSDL::Observer()
948 return gEpocEnv->iAppSrv->Observer();
951 EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver)
953 gEpocEnv->iAppSrv->SetObserver(aObserver);
956 EXPORT_C void CSDL::Resume()
958 EpocSdlEnv::Resume();
961 EXPORT_C void CSDL::Suspend()
963 if(gEpocEnv->iDsa != NULL)
964 gEpocEnv->iDsa->DoStop();
967 EXPORT_C void CSDL::Resize()
969 if(gEpocEnv->iWaitingForOrientationChange)
971 EpocSdlEnv::AllocSurface(gEpocEnv->iSize, gEpocEnv->iMode);
972 gEpocEnv->iWaitingForOrientationChange = false;
974 else
976 TSize size = gEpocEnv->iDsa->Window()->Size();
977 SDL_PrivateResize(size.iWidth, size.iHeight);
981 EXPORT_C CSDL::CSDL()
984 TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus)
986 if(gEpocEnv->iId != TThreadId(0) &&
987 aThread.Open(gEpocEnv->iId) &&
988 aThread.ExitType() == EExitPending)
990 aThread.Rendezvous(aStatus);
991 return ETrue;
993 return EFalse;
996 void* SDL_LoadObject(const char *sofile)
998 RLibrary* lib = new RLibrary();
999 if(lib == NULL)
1000 return NULL;
1001 TFileName name;
1002 name.Copy(TPtrC8((const TUint8*)sofile));
1003 if(KErrNone == lib->Load(name))
1004 return lib;
1005 delete lib;
1006 return NULL;
1009 void* SDL_LoadFunction(void *handle, const char *name)
1011 TLex8 v((const TUint8*)(name));
1012 int ord;
1014 if(KErrNone != v.Val(ord))
1015 return NULL;
1017 const RLibrary* lib = reinterpret_cast<RLibrary*>(handle);
1018 TLibraryFunction f = lib->Lookup(ord);
1019 return (void*)(f);
1022 void SDL_UnloadObject(void *handle)
1024 RLibrary* lib = reinterpret_cast<RLibrary*>(handle);
1025 lib->Close();
1026 delete lib;