2 #include "SDL_events_c.h"
6 #include "sdlepocapi.h"
14 #include "SDL_epocevents_c.h"
15 #include "SDL_keysym.h"
17 #include "SDL_loadso.h"
18 #include <remconcoreapitargetobserver.h>
19 #include <remconinterfaceselector.h>
20 #include <remconcoreapitarget.h>
22 extern SDLKey
* KeyMap();
23 extern void ResetKeyMap();
35 CEventQueue
* iEventQueue
;
43 CArrayFix
<TSdlCleanupItem
>* iCleanupItems
;
45 TRequestStatus
* iCallerStatus
;
46 bool iWaitingForOrientationChange
;
52 EpocSdlEnvData
* gEpocEnv
;
57 static void RunSingleThread();
60 void EnvUtils::RunSingleThread()
62 int count
= RThread().RequestCount();
66 if(CActiveScheduler::RunIfReady(err
, CActive::EPriorityIdle
))
68 CActiveScheduler::Current()->WaitForAnyRequest();
73 int Panic(int aErr
, int aLine
)
76 b
.Format(_L("Main at %d"), aLine
);
82 class CEventQueue
: public CBase
, public MEventQueue
87 int Append(const TWsEvent
& aEvent
);
88 const TWsEvent
Shift();
92 std::queue
<TWsEvent
> m_queue
;
95 void CEventQueue::ConstructL()
99 CEventQueue::~CEventQueue()
103 int CEventQueue::Append(const TWsEvent
& aEvent
)
105 m_queue
.push(aEvent
);
109 TBool
CEventQueue::HasData()
111 EnvUtils::RunSingleThread();
112 return !m_queue
.empty();
115 const TWsEvent
CEventQueue::Shift()
117 const TWsEvent event
= m_queue
.front();
123 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation
, TAny
* aItem
) :
124 iOperation(aOperation
), iItem(aItem
), iThread(RThread().Id())
127 #define MAINFUNC(x) TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
136 TMainFunc::TMainFunc()
138 Mem::FillZ(iMainFunc
, sizeof(iMainFunc
));
142 const void* TMainFunc::operator[](int aIndex
) const
144 return iMainFunc
[aIndex
];
148 class CSdlAppServ
: public CActive
153 EAppSrvNoop
= CDsa::ELastDsaRequest
,
156 EAppSrvWindowDisplayMode
,
157 EAppSrvWindowPointerCursorMode
,
165 int Request(int aService
);
166 int RequestValue(int aService
);
168 void PanicMain(int aReason
);
169 void PanicMain(const TDesC
& aInfo
, int aReason
);
170 void SetObserver(MSDLObserver
* aObserver
);
171 int ObserverEvent(int aEvent
, int aParam
);
172 void SetParam(int aParam
);
173 void HandleObserverValue(int aService
, int aReturnValue
, TBool aMainThread
);
174 MSDLObserver
* Observer();
179 const TThreadId iMainId
;
183 MSDLObserver
* iObserver
;
184 TRequestStatus
* iStatusPtr
;
187 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh
), iMainId(RThread().Id()), iObserver( NULL
)
191 MSDLObserver
* CSdlAppServ::Observer()
196 void CSdlAppServ::SetObserver(MSDLObserver
* aObserver
)
198 iObserver
= aObserver
;
201 int CSdlAppServ::ObserverEvent(int aEvent
, int aParam
)
203 if(iObserver
!= NULL
)
205 if(RThread().Id() == iMainId
)
207 return iObserver
->SdlEvent(aEvent
, aParam
);
209 PANIC(KErrNotSupported
);
214 void CSdlAppServ::PanicMain(int aReason
)
216 iAppThread
.Panic(RThread().Name(), aReason
);
219 void CSdlAppServ::PanicMain(const TDesC
& aInfo
, int aReason
)
221 iAppThread
.Panic(aInfo
, aReason
);
224 void CSdlAppServ::ConstructL()
226 CActiveScheduler::Add(this);
227 iStatus
= KRequestPending
;
228 iStatusPtr
= &iStatus
;
232 CSdlAppServ::~CSdlAppServ()
238 int CSdlAppServ::Request(int aService
)
240 EnvUtils::RunSingleThread();
242 iAppThread
.RequestComplete(iStatusPtr
, KErrNone
);
246 int CSdlAppServ::RequestValue(int aService
)
249 Request(EAppSrvNoop
);
253 void CSdlAppServ::Init()
255 PANIC_IF_ERROR(iAppThread
.Open(iMainId
));
258 void CSdlAppServ::SetParam(int aParam
)
260 iReturnValue
= aParam
;
263 void CSdlAppServ::HandleObserverValue(int aService
, int aReturnValue
, TBool aMainThread
)
265 if(!aMainThread
&& aService
== MSDLObserver::EEventSuspend
)
267 if(iObserver
== NULL
|| (gEpocEnv
->iDsa
!= NULL
&& gEpocEnv
->iDsa
->Stopped() && aReturnValue
!= MSDLObserver::ESuspendNoSuspend
))
269 EpocSdlEnv::Suspend();
274 void CSdlAppServ::RunL()
276 if(iStatus
== KErrNone
)
280 case CSdlAppServ::EAppSrvWaitDsa
:
281 EpocSdlEnv::SetWaitDsa();
282 iReturnValue
= EpocSdlEnv::IsDsaAvailable();
285 case CSdlAppServ::EAppSrvStopThread
:
286 if(gEpocEnv
->iDsa
!= NULL
)
287 gEpocEnv
->iDsa
->SetSuspend();
290 case EAppSrvWindowPointerCursorMode
:
291 iReturnValue
= gEpocEnv
->iDsa
!= NULL
? gEpocEnv
->iDsa
->Session().PointerCursorMode() : KErrNotReady
;
294 case EAppSrvDsaStatus
:
295 if(gEpocEnv
->iDsa
!= NULL
)
296 gEpocEnv
->iDsa
->Stop();
297 iReturnValue
= KErrNone
;
303 case MSDLObserver::EEventResume
:
304 case MSDLObserver::EEventSuspend
:
305 case MSDLObserver::EEventWindowReserved
:
306 case MSDLObserver::EEventKeyMapInit
:
307 case MSDLObserver::EEventWindowNotAvailable
:
308 case MSDLObserver::EEventMainExit
:
309 iReturnValue
= ObserverEvent(iService
, iReturnValue
);
310 HandleObserverValue(iService
, iReturnValue
, ETrue
);
314 PANIC(KErrNotSupported
);
318 iStatus
= KRequestPending
;
319 iStatusPtr
= &iStatus
;
324 void CSdlAppServ::DoCancel()
326 TRequestStatus
* s
= &iStatus
;
327 iAppThread
.RequestComplete(s
, KErrCancel
);
330 MEventQueue
& EpocSdlEnv::EventQueue()
332 __ASSERT_DEBUG(gEpocEnv
!= NULL
, PANIC(KErrNotReady
));
333 return *gEpocEnv
->iEventQueue
;
337 TBool
EpocSdlEnv::Flags(int aFlag
)
339 const int flag
= gEpocEnv
->iEpocEnvFlags
& aFlag
;
340 return flag
== aFlag
;
343 int EpocSdlEnv::Argc()
345 __ASSERT_DEBUG(gEpocEnv
!= NULL
, PANIC(KErrNotReady
));
346 return gEpocEnv
->iArgc
;
349 char** EpocSdlEnv::Argv()
351 __ASSERT_DEBUG(gEpocEnv
!= NULL
, PANIC(KErrNotReady
));
352 return gEpocEnv
->iArgv
;
355 TBool
EpocSdlEnv::IsDsaAvailable()
357 __ASSERT_DEBUG(gEpocEnv
!= NULL
, PANIC(KErrNotReady
));
358 return gEpocEnv
->iDsa
!= NULL
&& gEpocEnv
->iDsa
->IsDsaAvailable();
361 void EpocSdlEnv::WaitDsaAvailable()
363 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable
, 0);
364 gEpocEnv
->iAppSrv
->Request(CSdlAppServ::EAppSrvStopThread
);
365 if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop
))
367 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend
, 0);
371 void EpocSdlEnv::Suspend()
373 if(gEpocEnv
->iDsa
!= NULL
&& (gEpocEnv
->iDsa
->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop
)))
375 gEpocEnv
->iDsa
->SetSuspend();
379 void EpocSdlEnv::SetWaitDsa()
381 if(!IsDsaAvailable())
383 if(gEpocEnv
->iDsa
!= NULL
)
384 gEpocEnv
->iDsa
->SetSuspend();
388 void EpocSdlEnv::Resume()
390 if(gEpocEnv
->iDsa
!= NULL
)
392 gEpocEnv
->iDsa
->Resume();
395 const int value
= gEpocEnv
->iAppSrv
->ObserverEvent(MSDLObserver::EEventResume
, 0);
396 gEpocEnv
->iAppSrv
->HandleObserverValue(MSDLObserver::EEventResume
, value
, ETrue
);
399 int EpocSdlEnv::AllocSurface(const TSize
& aSize
, TDisplayMode aMode
)
401 return gEpocEnv
->iDsa
->AllocSurface(aSize
, aMode
);
404 void EpocSdlEnv::UnlockHwSurface()
406 gEpocEnv
->iDsa
->UnlockHwSurface();
409 TUint8
* EpocSdlEnv::LockHwSurface()
411 return gEpocEnv
->iDsa
->LockHwSurface();
414 void EpocSdlEnv::UpdateSwSurface()
416 gEpocEnv
->iDsa
->UpdateSwSurface();
419 TBool
EpocSdlEnv::AddUpdateRect(TUint8
* aAddress
, const TRect
& aUpdateRect
, const TRect
& aRect
)
421 return gEpocEnv
->iDsa
->AddUpdateRect(aAddress
, aUpdateRect
, aRect
);
424 void EpocSdlEnv::Request(int aService
)
426 __ASSERT_DEBUG(gEpocEnv
!= NULL
, PANIC(KErrNotReady
));
427 gEpocEnv
->iAppSrv
->Request(aService
);
430 TDisplayMode
EpocSdlEnv::DisplayMode()
432 return gEpocEnv
->iDsa
== NULL
? ENone
: gEpocEnv
->iDsa
->DisplayMode();
435 TPointerCursorMode
EpocSdlEnv::PointerMode()
437 return static_cast<TPointerCursorMode
>(gEpocEnv
->iAppSrv
->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode
));
440 int EpocSdlEnv::SetPalette(int aFirstcolor
, int aColorCount
, TUint32
* aPalette
)
442 return gEpocEnv
->iDsa
->SetPalette(aFirstcolor
, aColorCount
, aPalette
);
445 void EpocSdlEnv::PanicMain(int aErr
)
447 gEpocEnv
->iAppSrv
->PanicMain(aErr
);
451 int EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem
& aItem
)
453 TRAPD(err
, gEpocEnv
->iCleanupItems
->AppendL(aItem
));
457 void EpocSdlEnv::RemoveCleanupItem(TAny
* aItem
)
459 for(int i
= 0; i
< gEpocEnv
->iCleanupItems
->Count(); i
++)
461 if(gEpocEnv
->iCleanupItems
->At(i
).iItem
== aItem
)
462 gEpocEnv
->iCleanupItems
->Delete(i
);
466 void EpocSdlEnv::CleanupItems()
468 const TThreadId id
= RThread().Id();
469 int last
= gEpocEnv
->iCleanupItems
->Count() - 1;
472 for(i
= last
; i
>= 0 ; i
--)
474 TSdlCleanupItem
& item
= gEpocEnv
->iCleanupItems
->At(i
);
475 if(item
.iThread
== id
)
477 item
.iThread
= TThreadId(0);
478 item
.iOperation(item
.iItem
);
482 last
= gEpocEnv
->iCleanupItems
->Count() - 1;
484 for(i
= last
; i
>= 0 ; i
--)
486 TSdlCleanupItem
& item
= gEpocEnv
->iCleanupItems
->At(i
);
487 if(item
.iThread
== TThreadId(0))
489 gEpocEnv
->iCleanupItems
->Delete(i
);
494 void EpocSdlEnv::FreeSurface()
496 Request(CSdlAppServ::EAppSrvDsaStatus
);
497 if(gEpocEnv
->iDsa
!= NULL
)
498 gEpocEnv
->iDsa
->Free();
501 void EpocSdlEnv::ObserverEvent(int aService
, int aParam
)
503 const TBool sdlThread
= RThread().Id() == gEpocEnv
->iId
;
504 const int valuea
= gEpocEnv
->iAppSrv
->ObserverEvent(aService
, aParam
);
505 gEpocEnv
->iAppSrv
->HandleObserverValue(aService
, valuea
, !sdlThread
);
508 gEpocEnv
->iAppSrv
->SetParam(aParam
);
509 const int valuet
= gEpocEnv
->iAppSrv
->RequestValue(aService
);
510 gEpocEnv
->iAppSrv
->HandleObserverValue(aService
, valuet
, EFalse
);
514 void EpocSdlEnv::PanicMain(const TDesC
& aInfo
, int aErr
)
516 gEpocEnv
->iAppSrv
->PanicMain(aInfo
, aErr
);
519 //Dsa is a low priority ao, it has to wait if its pending event, but ws
520 //event has been prioritized before it
521 //this is not called from app thread!
522 void EpocSdlEnv::WaitDeviceChange()
524 gEpocEnv
->iAppSrv
->RequestValue(CSdlAppServ::EAppSrvWaitDsa
);
527 static TBool
CheckSdl()
531 if(sdl
.Open(gEpocEnv
->iId
) == KErrNone
)
533 if(sdl
.ExitType() == EExitPending
)
542 void EpocSdlEnvData::Free()
544 if(RThread().Id() == gEpocEnv
->iId
)
551 __ASSERT_ALWAYS(iArgv
== NULL
|| CheckSdl(), PANIC(KErrNotReady
));
554 void EpocSdlEnvData::Delete()
556 for(int i
= 0; i
<= iArgc
; i
++)
576 _LIT(KSDLMain
, "SDLMain");
580 gEpocEnv
->iCleanupItems
= new CArrayFixFlat
<TSdlCleanupItem
>(8);
583 /* !! process exits here if there is "exit()" in main! */
585 for(int i
= 0; i
< 6; i
++)
587 void* f
= (void*) gEpocEnv
->iMain
[i
];
593 ret
= ((mainfunc1
)f
)();
601 ret
= ((mainfunc2
)f
)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
605 ((mainfunc2
)f
)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
609 ret
= ((mainfunc3
)f
)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp
);
613 ((mainfunc3
)f
)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp
);
622 static int DoMain(TAny
* /*aParam*/)
624 TBool fbsconnected
= EFalse
;
626 gEpocEnv
->iAppSrv
->Init();
631 TRAPD(err
, err
= MainL());
633 EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit
, err
);
635 // Free resources and return
636 EpocSdlEnv::CleanupItems();
638 gEpocEnv
->iCleanupItems
->Reset();
639 delete gEpocEnv
->iCleanupItems
;
640 gEpocEnv
->iCleanupItems
= NULL
;
642 gEpocEnv
->Free(); //free up in thread resources
645 RFbsSession::Disconnect();
647 if(gEpocEnv
->iCallerStatus
!= NULL
)
649 User::RequestComplete(gEpocEnv
->iCallerStatus
, err
);
654 return err
== KErrNone
? ret
: err
;
667 CSDL
* CSDL::NewL(int aFlags
)
669 __ASSERT_ALWAYS(gEpocEnv
== NULL
, PANIC(KErrAlreadyExists
));
670 gEpocEnv
= new EpocSdlEnvData
;
671 Mem::FillZ(gEpocEnv
, sizeof(EpocSdlEnvData
));
673 gEpocEnv
->iEpocEnvFlags
= aFlags
;
674 gEpocEnv
->iEventQueue
= new CEventQueue();
675 gEpocEnv
->iAppSrv
= new CSdlAppServ();
677 CSDL
* sdl
= new CSDL();
679 gEpocEnv
->iSdl
= sdl
;
684 void CSDL::SetContainerWindowL(RWindow
& aWindow
, RWsSession
& aSession
, CWsScreenDevice
& aDevice
)
686 if(gEpocEnv
->iDsa
== NULL
)
687 gEpocEnv
->iDsa
= CDsa::CreateL(aSession
);
688 gEpocEnv
->iDsa
->ConstructL(aWindow
, aDevice
);
691 int EpocSdlEnv::ApplyGlesDsa()
694 TRAPD(err
, dsa
= gEpocEnv
->iDsa
->CreateGlesDsaL());
695 gEpocEnv
->iDsa
= dsa
;
699 RWindow
* EpocSdlEnv::Window()
701 return gEpocEnv
->iDsa
->Window();
704 void EpocSdlEnv::UpdateWholeScreen(bool val
)
706 gEpocEnv
->iDsa
->m_updateWholeScreen
= val
;
709 bool EpocSdlEnv::GetUpdateWholeScreen()
711 return gEpocEnv
->iDsa
->m_updateWholeScreen
;
714 void EpocSdlEnv::SetOrientation(CAknAppUi::TAppUiOrientation orientation
, const TSize
& aSize
, TDisplayMode aMode
)
716 gEpocEnv
->iWaitingForOrientationChange
= true;
717 gEpocEnv
->iSize
= aSize
;
718 gEpocEnv
->iMode
= aMode
;
720 TRAPD(err
, static_cast<CAknAppUi
*>(CEikonEnv::Static()->EikAppUi())->SetOrientationL(orientation
));
723 TThreadId
CSDL::CallMainL(const TMainFunc
& aFunc
, TRequestStatus
* const aStatus
, const CDesC8Array
* const aArg
, int aStackSize
)
725 ASSERT(gEpocEnv
!= NULL
);
726 gEpocEnv
->iMain
= aFunc
;
727 const TBool args
= aArg
!= NULL
;
729 if(gEpocEnv
->iArgv
!= NULL
)
730 User::Leave(KErrAlreadyExists
);
732 gEpocEnv
->iArgc
= args
? aArg
->Count() + 1 : 0;
733 gEpocEnv
->iArgv
= new char*[gEpocEnv
->iArgc
+ 2];
736 const TFileName processName
= RProcess().FileName();
737 const int len
= processName
.Length();
738 gEpocEnv
->iArgv
[k
] = new char[len
+ 1];
739 Mem::Copy(gEpocEnv
->iArgv
[k
], processName
.Ptr(), len
);
740 gEpocEnv
->iArgv
[k
][len
] = 0;
742 for(int i
= 0; args
&& (i
< aArg
->Count()); i
++)
745 const int len
= aArg
->MdcaPoint(i
).Length();
746 gEpocEnv
->iArgv
[k
] = new char[len
+ 1];
747 Mem::Copy(gEpocEnv
->iArgv
[k
], aArg
->MdcaPoint(i
).Ptr(), len
);
748 gEpocEnv
->iArgv
[k
][len
] = 0;
751 gEpocEnv
->iArgv
[k
+ 1] = NULL
;
753 gEpocEnv
->iEventQueue
->ConstructL();
754 gEpocEnv
->iAppSrv
->ConstructL();
756 // for handling volume up/down keys
757 CRemConInterfaceSelector
*iSelector
= CRemConInterfaceSelector::NewL();
758 CRemConCoreApiTarget::NewL( *iSelector
, *this );
759 iSelector
->OpenTargetL();
761 gEpocEnv
->iCallerStatus
= aStatus
;
763 *aStatus
= KRequestPending
;
764 gEpocEnv
->iId
= RThread().Id();
765 // when priority is not lowered screen updates much more frequently, which
766 // may be undesired, for example in case of openttd's generating world dialog
767 RThread().SetPriority(EPriorityLess
);
770 return gEpocEnv
->iId
;
773 int CSDL::AppendWsEvent(const TWsEvent
& aEvent
)
775 return EpocSdlEnv::EventQueue().Append(aEvent
);
778 void CSDL::SDLPanic(const TDesC
& aInfo
, int aErr
)
780 EpocSdlEnv::PanicMain(aInfo
, aErr
);
783 int CSDL::GetSDLCode(int aScanCode
)
787 if(aScanCode
>= MAX_SCANCODE
)
789 return KeyMap()[aScanCode
];
792 int CSDL::SDLCodesCount() const
797 void CSDL::ResetSDLCodes()
802 int CSDL::SetSDLCode(int aScanCode
, int aSDLCode
)
804 const int current
= GetSDLCode(aScanCode
);
805 if(aScanCode
>= 0 && aScanCode
< MAX_SCANCODE
)
806 KeyMap()[aScanCode
] = static_cast<SDLKey
>(aSDLCode
);
811 MSDLObserver
* CSDL::Observer()
813 return gEpocEnv
->iAppSrv
->Observer();
816 void CSDL::SetObserver(MSDLObserver
* aObserver
)
818 gEpocEnv
->iAppSrv
->SetObserver(aObserver
);
823 EpocSdlEnv::Resume();
828 if(gEpocEnv
->iDsa
!= NULL
)
829 gEpocEnv
->iDsa
->DoStop();
834 if(gEpocEnv
->iWaitingForOrientationChange
)
836 EpocSdlEnv::AllocSurface(gEpocEnv
->iSize
, gEpocEnv
->iMode
);
837 gEpocEnv
->iWaitingForOrientationChange
= false;
841 TSize size
= gEpocEnv
->iDsa
->Window()->Size();
842 SDL_PrivateResize(size
.iWidth
, size
.iHeight
);
849 void CSDL::MrccatoCommand(TRemConCoreApiOperationId aOperationId
, TRemConCoreApiButtonAction aButtonAct
)
851 if(aButtonAct
!= ERemConCoreApiButtonClick
)
855 event
.SetType(EEventKey
);
860 case ERemConCoreApiVolumeDown
:
861 event
.Key()->iScanCode
= EStdKeyDecVolume
;
862 event
.SetType(EEventKeyDown
);
863 AppendWsEvent(event
);
864 event
.SetType(EEventKeyUp
);
865 AppendWsEvent(event
);
868 case ERemConCoreApiVolumeUp
:
869 event
.Key()->iScanCode
= EStdKeyIncVolume
;
870 event
.SetType(EEventKeyDown
);
871 AppendWsEvent(event
);
872 event
.SetType(EEventKeyUp
);
873 AppendWsEvent(event
);
881 void* SDL_LoadObject(const char *sofile
)
883 RLibrary
* lib
= new RLibrary();
887 name
.Copy(TPtrC8((const TUint8
*)sofile
));
888 if(KErrNone
== lib
->Load(name
))
894 void* SDL_LoadFunction(void *handle
, const char *name
)
896 TLex8
v((const TUint8
*)(name
));
899 if(KErrNone
!= v
.Val(ord
))
902 const RLibrary
* lib
= reinterpret_cast<RLibrary
*>(handle
);
903 TLibraryFunction f
= lib
->Lookup(ord
);
907 void SDL_UnloadObject(void *handle
)
909 RLibrary
* lib
= reinterpret_cast<RLibrary
*>(handle
);