diff -r 000000000000 -r cec860690d41 emulator/emulatorbsp/specific/gui.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emulator/emulatorbsp/specific/gui.cpp Tue Feb 02 01:39:10 2010 +0200 @@ -0,0 +1,4920 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// wins\specific\gui.cpp +// +// +#define WINVER 0x0500 + +#include "gui.h" +#include +#include +#include +#include +#include "variant.h" +#include "resource.h" +#include "winsgui.h" +#include "display_chan.h" +#include "pixelformats.h" +#include "multitouch.h" + +#include "monitors.h" + +//Define these so that emulator generates varying values for gce stride and offset. +//By default in emulator, stride is exactly right for display resolution and offset is zero +//Setting these will identify code which incorrectly calculates these factors instead of requesting them +//Note that multiples of 4 bytes are preferred for various reasons. +//[3/5/07 The Secure presentation burffer ignores stride extra because it uses a windows bitmap header to render.] +// #define TEST_GCE_VARIABLE_STRIDE_EXTRA 16 //This constant is added to each mode's scanline length in bytes. It may cause a break if enabled because the iDisplayBufferOffset is not being set +// #define TEST_GCE_VARIABLE_START_EXTRA 16 //A multiple of this is added to each mode's start address in bytes +// #define ASSYMETRIC_SQUARE_STRIDE //If this is defined and the width==height the the stride will not be the same! + +enum + { + KMaskModeNum=0x0FFFFFFF, + KMaskModeFlag8=0x80000000, + KMaskModeFlag4=0x40000000, + KMaskModeFlag2=0x20000000, + KMaskModeFlag1=0x10000000, + + KModeFlagFlipped=KMaskModeFlag8, + + }; +enum + { + KMaskScreenNum=0x0FFF, + KMaskScreenFlag8=0x8000, + KMaskScreenFlag4=0x4000, + KMaskScreenFlag2=0x2000, + KMaskScreenFlag1=0x1000, + + KScreenFlagSecure=KMaskScreenFlag8, + + }; +const TInt KMaxDisplayColors=16777216; +const TInt KMaxDisplayContrast=1; + +static TEmulatorFlip* CurrentFlipState=NULL; +static TInt CurrentConfiguration = 0; +static TInt SavedFlipMessage = 0; + +DWinsUi *systemIni=NULL; +DMasterIni* masterIni; + +DMultiTouch* TheMultiTouch; +static HWND TheControlWin; +static HWND* TheChildWin=NULL; +static HWND* TheWin=NULL; +static HWND hwndStatus; // To display the X,Y,Z information of each mouse +static TInt VirtualKeyPressed = EStdKeyNull; +static HBITMAP* TheScreenBitmap=NULL; +static TUint LedMask; +static TBool WsSwitchOnScreen; + +const char * DefaultWindowTitle = "Symbian OS Emulator"; + +#ifdef __VC32__ + +#ifdef _DEBUG +const char * VersionText = " - wins udeb"; +#else +const char * VersionText = " - wins urel"; +#endif + +#else +#ifdef __CW32__ + +#ifdef _DEBUG +const char * VersionText = " - winscw udeb"; +#else +const char * VersionText = " - winscw urel"; +#endif + +#else +//not winscw or wins! +#ifdef _DEBUG +const char * VersionText = " - unknown udeb"; +#else +const char * VersionText = " - unknown urel"); +#endif + +#endif +#endif + +void Inactive(); +void Active(); +void DrawLeds(); +void UpdateModifiers(); +TInt DisplayHalFunction(TAny*, TInt aFunction, TAny* a1, TAny* a2); +LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd); + +GLDEF_C const char* skipws(const char* aPtr) + { + while (isspace(*aPtr)) + ++aPtr; + return aPtr; + } + +GLDEF_C const char* skiptok(const char* aPtr) + { + while (isalnum(*aPtr)) + ++aPtr; + return aPtr; + } + +GLDEF_C TInt CompareI(const TDesC8& aLhs, const TDesC8& aRhs) +// +// Case insensitive comparison of descriptors +// (TDesC::CompareF not available to kernel side code) +// + { + TInt ll = aLhs.Length(); + TInt rl = aRhs.Length(); + TInt len = Min(ll, rl); + TInt k = _strnicmp((const char*)aLhs.Ptr(), (const char*)aRhs.Ptr(), len); + return k != 0 ? k : ll - rl; + } + +GLDEF_C TInt MultiProperty(TInt (*aHandler)(TAny* aObj, const char*), TAny* aPtr, const char* aProperty) + { + const char* value = Property::GetString(aProperty); + if (!value) + return KErrNone; + for (;;) + { + TInt r = aHandler(aPtr, value); + if (r != KErrNone) + return r; + const char* ev = strchr(value, ';'); + if (!ev) + break; + value = ev + 1; + } + return KErrNone; + } + +class DWinsGuiPowerHandler : public DPowerHandler + { +public: // from DPowerHandler + void PowerDown(TPowerState); + void PowerUp(); +public: + static DWinsGuiPowerHandler* New(); + void ScreenOn(); + void ScreenOff(); + void ScreenOn(TInt aScreen); + void ScreenOff(TInt aScreen); +public: + DWinsGuiPowerHandler(); + TBool ProcessEvent(const TRawEvent* aEvent); + TBool ProcessEventDfc(const TRawEvent* aEvent); + TBool iStandby; + }; + +static DWinsGuiPowerHandler* WinsGuiPowerHandler; + +_LIT(KWinsGuiName, "WinsGui"); + +DWinsGuiPowerHandler* DWinsGuiPowerHandler::New() + { + DWinsGuiPowerHandler* self = new DWinsGuiPowerHandler(); + if (!self) + return NULL; + self->Add(); + + return self; + } + +DWinsGuiPowerHandler::DWinsGuiPowerHandler() : DPowerHandler(KWinsGuiName) + { + } + +void DWinsGuiPowerHandler::ScreenOff() + { + for(TInt ix=0;ixiScreens.Count();ix++) + ScreenOff(ix); + } + +void DWinsGuiPowerHandler::ScreenOn() + { + for(TInt ix=0;ixiScreens.Count();ix++) + ScreenOn(ix); + } + +void DWinsGuiPowerHandler::ScreenOff(TInt aScreen) + { + PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, FALSE, NULL); + systemIni->iScreens[aScreen]->iScreenOff = ETrue; + } + +void DWinsGuiPowerHandler::ScreenOn(TInt aScreen) + { + PostMessageA(TheWin[aScreen], WM_EMUL_POWER_ON, TRUE, NULL); + systemIni->iScreens[aScreen]->iScreenOff = EFalse; + } + +void DWinsGuiPowerHandler::PowerDown(TPowerState aState) + { + if (aState == EPwStandby) + iStandby = ETrue; + ScreenOff(); + PowerDownDone(); + } + + +void DWinsGuiPowerHandler::PowerUp() + { + iStandby = EFalse; + ScreenOn(); + PowerUpDone(); + } + +// called in the interrupt context +TBool DWinsGuiPowerHandler::ProcessEvent(const TRawEvent* aEvent) + { + if (!iStandby) + // Pass through + return EFalse; + + if ((aEvent->Type() == TRawEvent::EKeyDown)) + { + Wins::Self() -> AssertWakeupSignal(); + } + + // Ignore + return ETrue; + } + +// called in DFC +TBool DWinsGuiPowerHandler::ProcessEventDfc(const TRawEvent* aEvent) + { + if (aEvent->Type() == TRawEvent::EKeyDown) + { + Wins::Self() -> WakeupEvent(); + if (aEvent->ScanCode() == EStdKeyF5) + { + // Simulate a media change interrupt (media removed) + Wins::MediaChangeCallBack(); + *Wins::MediaDoorOpenPtr()=ETrue; + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF8) + { + TRawEvent v; + v.Set(TRawEvent::ECaseClose); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF8) + { + TRawEvent v; + v.Set(TRawEvent::ECaseClose); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyOff) + { + // Pass through + return EFalse; + } + if (aEvent->ScanCode() == EStdKeyF10) + { + TRawEvent v; + v.Set(TRawEvent::ESwitchOff); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + if (aEvent->ScanCode() == EStdKeyF11) + { + TRawEvent v; + v.Set(TRawEvent::ECaseOpen); + Kern::AddEvent(v); + // Ignore + return ETrue; + } + } + else if (aEvent->Type() == TRawEvent::EKeyUp) + { + if (aEvent->ScanCode() == EStdKeyF10) + // Ignore + return ETrue; + + if (aEvent->ScanCode() == EStdKeyF5) + { + // Simulate a media change interrupt (media Present) + *Wins::MediaDoorOpenPtr()=EFalse; + return ETrue; + } + } + + // Path through + return EFalse; + } + +class EventQ + { + enum {ESize = 16}; +public: + EventQ(); + void Add(const TRawEvent& aEvent); +private: + static void Dfc(TAny* aPtr); + void Empty(); +private: + TDfc iDfc; + TRawEvent* iTail; + TRawEvent iQ[ESize]; + }; + +EventQ::EventQ() + :iDfc(&EventQ::Dfc, this, Kern::DfcQue0(), 6), iTail(iQ) + {} + + +void EventQ::Add(const TRawEvent& aEvent) + { + StartOfInterrupt(); + if (WinsGuiPowerHandler->ProcessEvent(&aEvent)) + { + EndOfInterrupt(); + return; + } + + TRawEvent* pE = iTail; + if (pE != &iQ[ESize]) + { + *pE = aEvent; + iTail = pE + 1; + if (pE == iQ) + iDfc.Add(); + } + EndOfInterrupt(); + } + +void EventQ::Dfc(TAny* aPtr) + { + static_cast(aPtr)->Empty(); + } + +void EventQ::Empty() +// +// Called in the DFC +// + { + TInt irq; + TRawEvent* pE = iQ; + for (;;) + { + if (!WinsGuiPowerHandler->ProcessEventDfc(pE)) + Kern::AddEvent(*pE); + ++pE; + irq = NKern::DisableAllInterrupts(); + if (pE == iTail) + break; + NKern::RestoreInterrupts(irq); + } + iTail = iQ; + NKern::RestoreInterrupts(irq); + } + +LOCAL_D EventQ TheEventQ; + +// Virtual keys + + +VirtualKey::VirtualKey(const TInt aCommandData, const TEmulCommand aCommand) : iCommand(aCommand), iData(aCommandData) + { + } + +TBool VKRect::Contains(TInt aX, TInt aY) const + { + return (aX >= iLeft && aX < iRight && aY >= iTop && aY < iBottom); + } + +VKRect::VKRect(const TInt aCommandData, const TEmulCommand aCommand, TInt aX, TInt aY, TInt aWidth, TInt aHeight) : + VirtualKey(aCommandData, aCommand) + { + iLeft = aX; + iTop = aY; + iRight = aX + aWidth; + iBottom = aY + aHeight; + } + + + +void VKRect::Draw(HDC aHdc,COLORREF aColor) const + { + HPEN pen; + pen=CreatePen(PS_SOLID, 2, aColor); + SelectObject(aHdc, pen); + POINT point; + + MoveToEx(aHdc, (int)iLeft, (int)iTop, &point); + LineTo(aHdc, (int)iLeft, (int)iBottom); + LineTo(aHdc, (int)iRight, (int)iBottom); + LineTo(aHdc, (int)iRight, (int)iTop); + LineTo(aHdc, (int)iLeft, (int)iTop); + } + + +KeyCombination::KeyCombination(const TInt aCommandData, TEmulCommand aCommand): + iData(aCommandData), + iCommand(aCommand) +{ + for (TInt i=0;i=0)//if at least one key is not pressed, we return false + return EFalse; + } + return ETrue; +} + +TBool KeyCombination::AddKey(TStdScanCode aKey) +{ + TInt i; + for (i=0;i iMaxScreenWidth) + iMaxScreenWidth = screenWidth; + wsprintfA(property, "Configuration[%d][%d]ScreenHeight", count, aScreen); + screenHeight = Property::GetInt(property, KScreenHeight); + screenHeight = (screenHeight + 3) & ~3; + if (screenHeight > iMaxScreenHeight) + iMaxScreenHeight = screenHeight; +// + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth", count, aScreen); + physicalScreenWidth = Property::GetInt(property); + if (physicalScreenWidth > iMaxPhysicalScreenWidth) + iMaxPhysicalScreenWidth = physicalScreenWidth; + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight", count, aScreen); + physicalScreenHeight = Property::GetInt(property); + if (physicalScreenHeight > iMaxPhysicalScreenHeight) + iMaxPhysicalScreenHeight = physicalScreenHeight; + } + + // Read figures for current configuration + TInt givenWidth, givenHeight; + wsprintfA(property, "Configuration[%d][%d]ScreenWidth",aConf,aScreen); + givenWidth = Property::GetInt(property, KScreenWidth); + iScreenWidth = (givenWidth + 3) & ~3; + wsprintfA(property, "Configuration[%d][%d]ScreenHeight",aConf,aScreen); + givenHeight = Property::GetInt(property, KScreenHeight); + iScreenHeight = (givenHeight + 3) & ~3; + // Width of screen should be multiple number of 4 pixels. + if (givenWidth & 3 || givenHeight & 3) + { + Kern::Printf("Width and Height of Screen should be multiple number of 4 pixels.\n" + "\tWidth of screen[%d] set to: %d\n\tHeight of screen[%d] set to: %d", + aScreen, iScreenWidth, aScreen, iScreenHeight); + } + +// + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenWidth",aConf,aScreen); + iPhysicalScreenWidth = Property::GetInt(property); + wsprintfA(property, "Configuration[%d][%d]PhysicalScreenHeight",aConf,aScreen); + iPhysicalScreenHeight = Property::GetInt(property); +// + wsprintfA(property, "Configuration[%d][%d]ScreenOffsetX",aConf,aScreen); + iScreenOffsetX = Property::GetInt(property, KScreenOffsetX); + wsprintfA(property, "Configuration[%d][%d]ScreenOffsetY",aConf,aScreen); + iScreenOffsetY = Property::GetInt(property, KScreenOffsetY); + + wsprintfA(property, "Configuration[%d][%d]CompositionBuffers",aConf,aScreen); + iCompositionBuffers = Property::GetInt(property, KCompositionBuffers); + + wsprintfA(property, "Configuration[%d][%d]RefreshRateHz",aConf,aScreen); + iRefreshRateHz = Property::GetInt(property, KRefreshRateHz); + + + wsprintfA(property, "Configuration[%d][%d]ColorDepth",aConf,aScreen); + const char* colors = Property::GetString(property); + if (colors) + { + TUint colorDepth=0; + const char* end = colors; + for (;;) + { + const char* beg = skipws(end); + if(*beg==';') + break; + if (!*beg) + break; + end = skiptok(beg); + if (_strnicmp("Gray2",beg,end-beg) == 0) + { + colorDepth|=KEmulGray2|KEmulIsBitMask; + } + else if (_strnicmp("Gray4",beg,end-beg) == 0) + { + colorDepth|=KEmulGray4|KEmulIsBitMask; + } + else if (_strnicmp("Gray16",beg,end-beg) == 0) + { + colorDepth|=KEmulGray16|KEmulIsBitMask; + } + else if (_strnicmp("Gray256",beg,end-beg) == 0) + { + colorDepth|=KEmulGray256|KEmulIsBitMask; + } + else if (_strnicmp("Color16",beg,end-beg) == 0) + { + colorDepth|=KEmulColor16|KEmulIsBitMask; + } + else if (_strnicmp("Color256",beg,end-beg) == 0) + { + colorDepth|=KEmulColor256|KEmulIsBitMask; + } + else if (_strnicmp("Color4K",beg,end-beg) == 0) + { + colorDepth|=KEmulColor4K|KEmulIsBitMask; + } + else if (_strnicmp("Color64K",beg,end-beg) == 0) + { + colorDepth|=KEmulColor64K|KEmulIsBitMask; + } + else if (_strnicmp("Color16M",beg,end-beg) == 0) + { + colorDepth|=KEmulColor16M|KEmulIsBitMask; + } + else + return KErrArgument; + } + iColorDepth = colorDepth; + + } + //multiple mode support is currently only for GCE. + //I fill this array in before knowing if GCE will be instanced. + if (iColorDepth&KEmulIsBitMask) + { + //iModeDepths is only used by GCE + TInt colorDepth=MaskGceOnly(iColorDepth); + TInt setMode=0; + for (TInt i=1;i!=KEmulIsBitMask;i+=i) + if (colorDepth&i) + iModeDepths[setMode++]=BitsForSingleMode(i); + iMaxModes= setMode; + iModeDepths[setMode++]=0; //a bit width of 0 is illegal + } + else + { + iModeDepths[0]=iColorDepth; + iMaxModes=1; + iModeDepths[1]=0; //a bit width of 0 is illegal + } + + wsprintfA(property, "Configuration[%d][%d]FasciaBitmap",aConf,aScreen); + const char* fascia = Property::GetString(property); + if (fascia) + { + TInt len = strlen(fascia); + //the path may have quotes at the start and end + //need to work out if this is an absolute or relative path + if (fascia[0] == '\"') + { + ++fascia; + --len; + if (--len > 0 && fascia[len-1] == '\"') + --len; + } + char* p = iFasciaFileName; + if (fascia[0] != '\\' && (len < 3 || fascia[1] != ':')) + { + //relative path + strcpy(p, Property::GetString("EmulatorDataPath")); + p += strlen(p); + } + memcpy(p, fascia, len); + p[len] = '\0'; + } + else + { + // default to machine name + strcpy(iFasciaFileName, Property::GetString("EmulatorDataPath")); + strcat(iFasciaFileName, Property::GetString("MachineName")); + strcat(iFasciaFileName, ".bmp"); + } + return KErrNone; + } + +TViewport::TViewport() + :iScreenProps(NULL),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0) + { + } + +TViewport::TViewport(DScreenProperties* aScreenProps) + :iScreenProps(aScreenProps),iViewportWidth(0), iViewportHeight(0), iViewportOffsetX(0), iViewportOffsetY(0) + { + } +TViewport::~TViewport() + { + } + + +/** +Changes the logical position of the viewport within the input area +of the emulator screen. The method may adjust the position so that +the viewport stays within the input area. +@param aPosition The new Y position of the top left hand corner of the viewport. +@param aHwnd The window associated with the viewport +*/ +void TViewport::ScrollToY(TInt aPosition, HWND aHwnd) + { + + SCROLLINFO scrollinfo; + scrollinfo.cbSize=sizeof(scrollinfo); + + //save for later + scrollinfo.fMask=SIF_POS; + GetScrollInfo(aHwnd, SB_VERT, &scrollinfo); + TInt oldY=scrollinfo.nPos; + + if(aPosition<0) + { + scrollinfo.nPos = 0; + } + else if( (aPosition+GetViewportHeight())>GetMaxHeight()) + { + scrollinfo.nPos = max(0,GetMaxHeight() - GetViewportHeight() ); + } + else + { + scrollinfo.nPos=aPosition; + } + + SetViewportOffsetY(scrollinfo.nPos); + scrollinfo.fMask=SIF_POS; + SetScrollInfo(aHwnd,SB_VERT, &scrollinfo, TRUE ); + ScrollWindowEx(aHwnd, 0, oldY-scrollinfo.nPos, 0, 0, NULL, NULL, SW_INVALIDATE); + + UpdateChildPos(aHwnd); + } + +/** +As for ScrollToY but for the X direction +*/ +void TViewport::ScrollToX(TInt aPosition, HWND aHwnd) + { + SCROLLINFO scrollinfo; + scrollinfo.cbSize=sizeof(scrollinfo); + + //save for later + scrollinfo.fMask=SIF_POS; + GetScrollInfo(aHwnd, SB_HORZ, &scrollinfo); + TInt oldX=scrollinfo.nPos; + + if(aPosition<0) + { + scrollinfo.nPos = 0; + } + else if( (aPosition+GetViewportWidth())>GetMaxWidth()) + { + scrollinfo.nPos = max(0,GetMaxWidth() - GetViewportWidth() ); + } + else + { + scrollinfo.nPos=aPosition; + } + + SetViewportOffsetX(scrollinfo.nPos); + scrollinfo.fMask=SIF_POS; + SetScrollInfo(aHwnd,SB_HORZ, &scrollinfo, TRUE ); + ScrollWindowEx(aHwnd, oldX-scrollinfo.nPos, 0, 0, 0, NULL, NULL, SW_INVALIDATE); + + UpdateChildPos(aHwnd); + } + +//Forward declaration +LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin); + +/** +Move the child window to it's correct position. + +@param aHwnd The HWND of the parent window +*/ +void TViewport::UpdateChildPos(HWND aHwnd) + { + TInt screenNumber = ::ScreenFromHWND(aHwnd,TheWin); + HWND childWin = TheChildWin[screenNumber]; + + switch (iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + MoveWindow( + childWin, + iScreenProps->iScreenOffsetX - GetViewportOffsetX(), + iScreenProps->iScreenOffsetY - GetViewportOffsetY(), + iScreenProps->iScreenWidth, + iScreenProps->iScreenHeight, + TRUE + ); + break; + case EEmulatorFlipInvert: + MoveWindow( + childWin, + iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth) - GetViewportOffsetX(), + iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetY(), + iScreenProps->iScreenWidth, + iScreenProps->iScreenHeight, + TRUE + ); + break; + case EEmulatorFlipLeft: + MoveWindow( + childWin, + iScreenProps->iScreenOffsetY - GetViewportOffsetX(), + iScreenProps->iXYInputWidth-(iScreenProps->iScreenOffsetX+iScreenProps->iScreenWidth)- GetViewportOffsetY(), + iScreenProps->iScreenHeight, + iScreenProps->iScreenWidth, + TRUE + ); + break; + case EEmulatorFlipRight: + MoveWindow( + childWin, + iScreenProps->iXYInputHeight-(iScreenProps->iScreenOffsetY+iScreenProps->iScreenHeight) - GetViewportOffsetX(), + iScreenProps->iScreenOffsetX - GetViewportOffsetY(), + iScreenProps->iScreenHeight, + iScreenProps->iScreenWidth, + TRUE + ); + break; + } + + } + +/** +Update the range of the horizontal scrollbar, +to take account of the current viewport width. + +@param aHwnd The window to be updated +*/ +void TViewport::UpdateScrollBarH(HWND aHwnd) + { + + SCROLLINFO scrollinfoHor; + scrollinfoHor.cbSize=sizeof(scrollinfoHor); + scrollinfoHor.fMask=SIF_RANGE|SIF_PAGE; + scrollinfoHor.nMin=0; + scrollinfoHor.nMax= GetMaxWidth()-1; + + + TInt newPage = GetViewportWidth() ; + TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image. + if ( newPage>= scrollinfoHor.nMax -GetSystemMetrics(SM_CXVSCROLL) + && newPage < scrollinfoHor.nMax+1) + { + redraw=ETrue; + newPage=GetMaxWidth(); + + } + scrollinfoHor.nPage= newPage; + + SetScrollInfo(aHwnd,SB_HORZ, &scrollinfoHor, TRUE ); + if(redraw) + { + ScrollToX(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar + InvalidateRect(aHwnd, NULL, TRUE); + } + } + +/** +Update the range of the vertical scrollbar, +to take account of the current viewport width. + +@param aHwnd The window to be updated +*/ +void TViewport::UpdateScrollBarV(HWND aHwnd) + { + SCROLLINFO scrollinfoVer; + scrollinfoVer.cbSize=sizeof(scrollinfoVer); + scrollinfoVer.fMask=SIF_RANGE|SIF_PAGE; + scrollinfoVer.nMin=0; + scrollinfoVer.nMax= GetMaxHeight()-1; + + TInt newPage = GetViewportHeight() ; + TBool redraw=EFalse; //redraw window if a resize has caused a scrollbar to disappear and reveal image. + if ( newPage>= scrollinfoVer.nMax -GetSystemMetrics(SM_CYHSCROLL) + && newPage < scrollinfoVer.nMax+1) + { + redraw=ETrue; + newPage=GetMaxHeight(); + } + scrollinfoVer.nPage= newPage; + + SetScrollInfo(aHwnd,SB_VERT, &scrollinfoVer, TRUE ); + if(redraw) + { + ScrollToY(0, aHwnd); //in case egde of fascia was against edge of vertical scrollbar + InvalidateRect(aHwnd, NULL, TRUE); + } + } + +/** +Returns the max width for the viewport window (non-client area) so that it +may be bounded. Takes account of scrollbar. + +@return Max width +*/ +TInt TViewport::GetMaxWindowWidth() const + { + + RECT rect = {0,0,0,0}; + + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + rect.right=iScreenProps->iXYInputWidth; + rect.bottom=iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + rect.right=iScreenProps->iXYInputHeight; + rect.bottom=iScreenProps->iXYInputWidth; + break; + } + } + AdjustWindowRect(//take account of window decorations + &rect, + KWinStyle, + FALSE + ); + + + return (rect.right-rect.left); + } + +/** +Returns the max height for the viewport window (non-client area) so that it +may be bounded. Takes account of scrollbar. + +@return Max height +*/ +TInt TViewport::GetMaxWindowHeight() const + { + + RECT rect ={0,0,0,0}; + + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + rect.right=iScreenProps->iXYInputWidth; + rect.bottom=iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + rect.right=iScreenProps->iXYInputHeight; + rect.bottom=iScreenProps->iXYInputWidth; + break; + } + } + AdjustWindowRect(//take account of window decorations + &rect, + KWinStyle, + FALSE + ); + return (rect.bottom-rect.top); + } + +/** +Returns the maximum width for the viewport (client area only). +Allowing for the orientation of the emulator. + +@return Max width +*/ +TInt TViewport::GetMaxWidth() const + { + TInt width=0; + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + width = iScreenProps->iXYInputWidth; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + width = iScreenProps->iXYInputHeight; + break; + } + } + + return width; + } + +/** +Returns the maximum height for the viewport (client area only). +Allowing for the orientation of the emulator. + +@return Max height +*/ +TInt TViewport::GetMaxHeight() const + { + TInt height=0; + switch(iScreenProps->iScreenRotation) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + { + height = iScreenProps->iXYInputHeight; + break; + } + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + { + height = iScreenProps->iXYInputWidth; + break; + } + } + + return height; + + } + +/** +Sets the X offset of the viewport from the edge of the input area +@param aOffset The X offset +*/ +void TViewport::SetViewportOffsetX(TInt aOffset) + { + iViewportOffsetX = aOffset; + } + +/** +Sets the Y offset of the viewport from the edge of the input area +@param aOffset The Y offset +*/ +void TViewport::SetViewportOffsetY(TInt aOffset) + { + iViewportOffsetY = aOffset; + } + +TInt TViewport::GetViewportOffsetX() const + { + return iViewportOffsetX; + } +TInt TViewport::GetViewportOffsetY() const + { + return iViewportOffsetY; + } + +/** +Sets the viewport width, this is equal to the width +of the window's client area +@param aWidth The width +*/ +void TViewport::SetViewportWidth(TInt aWidth) + { + iViewportWidth=aWidth; + } + +/** +Sets the viewport height, this is equal to the height +of the window's client area +@param aHeight The height +*/ +void TViewport::SetViewportHeight(TInt aHeight) + { + iViewportHeight=aHeight; + } + +TInt TViewport::GetViewportWidth() const + { + return iViewportWidth; + } +TInt TViewport::GetViewportHeight() const + { + return iViewportHeight; + } + +// the UI class + +DWinsUi::DWinsUi() + :iVirtualKeys(10), + iControlHotKeys(10) + {} + +/// Returns the current mode's depth. Remember current mode is never set! +TUint DWinsUi::ColorDepth(TInt aScreenNumber) + { + TVideoInfoV01 info; + VideoInfo(aScreenNumber, info); + return info.iBitsPerPixel; + } + +TInt DWinsUi::SetFlip(TEmulatorFlip aFlip, TInt aScreenNumber) + { + if(TUint(aScreenNumber)>=TUint(systemIni->iScreens.Count())) + return KErrArgument; + int r1 = PostMessageA(TheChildWin[aScreenNumber],WM_FLIP_MESSAGE,(TUint)aFlip,NULL); + return r1 ? KErrNone : KErrGeneral; + } + +void DWinsUi::Info(TVariantInfoV01& aInfo) + { + aInfo.iLedCapabilities=0x3; + } + +HWND DWinsUi::HWnd() + { + return TheControlWin; + } + +TInt DWinsUi::SetupProperties(TInt aId) + +// +// load UI settings from the emulator properties +// + { + //setup the screens + TInt screens = Property::GetInt("[screens]", 1); + + for (TInt x = 0; x < screens; ++x) + { + DScreenProperties * pScr = new DScreenProperties(); + if (!pScr) + return KErrNoMemory; + + TInt ret = pScr->SetupProperties(aId,x); + if (KErrNone == ret) + ret = iScreens.Append(pScr); + + if (KErrNone != ret) + { + delete pScr; + return ret; + } + } +// + char property[50]; + wsprintfA(property, "Configuration[%d]LedSize",aId); + iLedSize = Property::GetInt(property, KLedSize); + wsprintfA(property, "Configuration[%d]LedArrangeVertically",aId); + iLedVertical = Property::GetBool(property, KLedVertical); + wsprintfA(property, "Configuration[%d]LedArrangeHorizontally",aId); + if (Property::GetBool(property)) + iLedVertical = EFalse; + wsprintfA(property, "Configuration[%d]LedOffsetX",aId); + iLedOffsetX = Property::GetInt(property, KLedLeft); + wsprintfA(property, "Configuration[%d]LedOffsetY",aId); + iLedOffsetY = Property::GetInt(property, KLedTop); + wsprintfA(property, "Configuration[%d]LedGap",aId); + iLedGap = Property::GetInt(property, KLedGap); +// + wsprintfA(property, "Configuration[%d]PointerType",aId); + const char* pointer = Property::GetString(property, "Pen"); + if (_stricmp(pointer, "None") == 0) + { + iPointerType=_S8("NONE"); + iXYInputType=EXYInputNone; + } + else if (_stricmp(pointer,"Pen") == 0) + { + iPointerType=_S8("PEN"); + iXYInputType=EXYInputPointer; + } + else if (_stricmp(pointer,"Mouse") == 0) + { + iPointerType=_S8("MOUSE"); + iXYInputType=EXYInputMouse; + } + else if (_stricmp(pointer,"Delta-Mouse") == 0) + { + iPointerType=_S8("MOUSE"); + iXYInputType=EXYInputDeltaMouse; + } + else + return KErrArgument; +// + wsprintfA(property, "Configuration[%d]DigitizerOffsetX",aId); + iDigitizerOffsetX = Property::GetInt(property, -iScreens[0]->iScreenOffsetX); + wsprintfA(property, "Configuration[%d]DigitizerOffsetY",aId); + iDigitizerOffsetY = Property::GetInt(property, -iScreens[0]->iScreenOffsetY); + wsprintfA(property, "Configuration[%d]DigitizerWidth",aId); + iDigitizerWidth = Property::GetInt(property,-1); + wsprintfA(property, "Configuration[%d]DigitizerHeight",aId); + iDigitizerHeight = Property::GetInt(property,-1); + wsprintfA(property, "Configuration[%d]DisableDigitizer",aId); + iDigitizerEnabled = !Property::GetBool(property); +// To enable the multitouch + wsprintfA(property, "EnableMultiTouch"); + iMultiTouchEnabled = Property::GetBool(property,EFalse); + wsprintfA(property, "SYMBIAN_BASE_USE_GCE"); + iGCEEnabled = Property::GetBool(property,EFalse); + wsprintfA(property, "MultiTouchProximityStep"); + iMultiTouchProximityStep = Property::GetInt(property,-1); + wsprintfA(property, "MultiTouchPressureStep"); + iMultiTouchPressureStep = Property::GetInt(property,-1); +// + strcpy(iSysIniFileName, Property::GetString("EmulatorDataPath")); + strcat(iSysIniFileName, "emulator\\"); + if (!Emulator::CreateAllDirectories(iSysIniFileName)) + return Emulator::LastError(); + strcat(iSysIniFileName, Property::GetString("MachineName")); + strcat(iSysIniFileName, ".sys.ini"); +// + TInt r = iKeyboard.Init(aId); + if (r != KErrNone) + return r; + + wsprintfA(property, "Configuration[%d]VirtualKey",aId); + r = MultiProperty(&DWinsUi::DoDefineVirtualKey, this, property); + if (r != KErrNone) + return r; +// + + wsprintfA(property, "Configuration[%d]NoVersionInfo",aId); + iDisplayVersionInfo = !Property::GetBool(property); + + wsprintfA(property, "Configuration[%d]WindowTitle",aId); + const char * p = Property::GetString(property); + if (p && (strlen(p) <= KMaxNameSize)) + strcpy(iWindowTitle, p); + else + strcpy(iWindowTitle, DefaultWindowTitle); + + if (iDisplayVersionInfo) + { + TInt wtLen = strlen(iWindowTitle); + TInt vtLen = strlen(VersionText); + if ((wtLen + vtLen) > KMaxNameSize) + iWindowTitle[KMaxNameSize-vtLen] = '\0'; + strcat(iWindowTitle, VersionText); + } + + wsprintfA(property, "Configuration[%d]OnActivation",aId); + pointer = Property::GetString(property); + //example OnActivation 270 EKeyScreenDimension1 + //params are rotation(int) and key(string) + if (pointer) + { + char * next; + + //skip any white space + const char* beg = skipws(pointer); + + //get the number + long rotation = strtol(beg, &next, 0); + if (next == beg) + return KErrArgument; + + switch (rotation) + { + case 0: + iScreens[0]->iScreenRotation = EEmulatorFlipRestore; + break; + case 90: + iScreens[0]->iScreenRotation = EEmulatorFlipRight; + break; + case 180: + iScreens[0]->iScreenRotation = EEmulatorFlipInvert; + break; + case 270: + iScreens[0]->iScreenRotation = EEmulatorFlipLeft; + break; + default: + r = KErrArgument; + } + if (r != KErrNone) + return r; + + beg = skipws(next); + + //beg should now point to the keycode + TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, strlen(beg))); + if (key == KErrNotFound) + return key; + iInitialFlipMsg = key; + } + + //EmulatorControl messages are a bit like virtual keys + wsprintfA(property, "Configuration[%d]EmulatorControl",aId); + r = MultiProperty(&DWinsUi::DoDefineEmulatorControl, this, property); + if (r != KErrNone) + return r; + + wsprintfA(property, "Configuration[%d]EmulatorControlHotKey",aId); + r = MultiProperty(&DWinsUi::DoDefineEmulatorControlHotKey, this, property); + if (r != KErrNone) + return r; + + return KErrNone; + } + +TInt DWinsUi::NumberOfScreens() + { + return iScreens.Count(); + } + +/** +Return the highest bit depth from an emulator mode mask. +@param aModeMask A bitwise combination of KEmul... display mode mask values. +@return A color depth in bits per pixel. +*/ +LOCAL_C TInt MaximumBitDepthFromMask(TInt aModeMask) + { + // Choose the highest bits per pixel based on the display mode mask. + if (aModeMask & KEmulColor16M) + { + return 24; + } + if (aModeMask & KEmulColor64K) + { + return 16; + } + if (aModeMask & KEmulColor4K) + { + return 12; + } + + // Lower bit depths are not supported, so use the default + return 24; + } + + +/** +Return the TDisplayRotation corresponding to the given TEmulatorFlip. +@param aFlip A screen rotation as a TEmulatorFlip. +@return The screen rotation as a TDisplayRotation. +*/ +LOCAL_C RDisplayChannel::TDisplayRotation FlipToDisplayRotation(TEmulatorFlip aFlip) + { + switch (aFlip) + { + case EEmulatorFlipLeft: + return RDisplayChannel::ERotation90CW; + case EEmulatorFlipInvert: + return RDisplayChannel::ERotation180; + case EEmulatorFlipRight: + return RDisplayChannel::ERotation270CW; + } + return RDisplayChannel::ERotationNormal; + } + + +TInt DWinsUi::SetDisplayChannel(TInt aScreenNumber, DDisplayChannel* aDisplay) + { + return systemIni->SetDisplayChannelImpl(aScreenNumber,aDisplay); + } + + +TInt DWinsUi::SetDisplayChannelImpl(TInt aScreenNumber, DDisplayChannel* aDisplay) + { + if (TUint(aScreenNumber) >= TUint(NumberOfScreens())) + { + // Screen number is either negative or too big. + return KErrArgument; + } + + TInt r = KErrNone; + HWND hWnd = TheChildWin[aScreenNumber]; + TBufferSet& buffer = masterIni->iBufferSet[aScreenNumber]; + + if (aDisplay) + { + // Display driver connecting + DScreenProperties* screen = iScreens[aScreenNumber]; + RDisplayChannel::TDisplayInfo info; + + TInt pixelBytes = 2; + info.iBitsPerPixel = MaximumBitDepthFromMask(screen->iColorDepth); + + switch (info.iBitsPerPixel) + { + case 12: // XRGB4444 + info.iPixelFormat = EUidPixelFormatXRGB_4444; + break; + case 16: // RGB565 + info.iPixelFormat = EUidPixelFormatRGB_565; + break; + default: + // Force anything else to packed RGB888 + pixelBytes = 4; + info.iBitsPerPixel = 24; + info.iPixelFormat = EUidPixelFormatXRGB_8888; + break; + } + + TInt width = screen->iMaxScreenWidth; + TInt height = screen->iMaxScreenHeight; + + info.iRefreshRateHz = screen->iRefreshRateHz; + info.iAvailableRotations = RDisplayChannel::ERotationNormal | RDisplayChannel::ERotation90CW | + RDisplayChannel::ERotation180 | RDisplayChannel::ERotation270CW; + info.iNormal.iWidth = width; + info.iNormal.iHeight = height; + // Windows requires rounding up to 4-bytes words + info.iNormal.iOffsetBetweenLines = _ALIGN_UP(width * pixelBytes, 4); + info.iFlipped.iWidth = height; + info.iFlipped.iHeight = width; + // Windows requires rounding up to 4-bytes words + info.iFlipped.iOffsetBetweenLines = _ALIGN_UP(height * pixelBytes, 4); + + TInt maxSize=0; + //ensure legacy buffer is large enough for all supported modes. + //It would be a very strange setup for the max size to not be the max bpp, + //but we don't know which mode is max bpp anyway! + TVideoInfoV01 videoInfo; + for (TInt mode=0,maxMode=screen->iMaxModes;modeVideoInfoForDisplayDriver(aScreenNumber,mode, videoInfo)) //can't actually fail currently + { + TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iHeight; + if (dwSize>maxSize) + maxSize=dwSize; + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + //rotated mode may use more RAM?? Height may be >Width or may not be a multiple of stride quantum + if (systemIni->VideoInfoForDisplayDriver(aScreenNumber,mode|KModeFlagFlipped, videoInfo)) //can't actually fail currently + { + TInt dwSize=videoInfo.iOffsetToFirstPixel+videoInfo.iOffsetBetweenLines*videoInfo.iSizeInPixels.iWidth; + if (dwSize>maxSize) + { + maxSize=dwSize; + } + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + } + + masterIni->iMaxSizeInBytes = maxSize; + if (__e32_atomic_add_ord32(&buffer.iDisplayDriverCount, 1) == 0) + { + // First driver to connect, allocate frame buffers. + // +1 frame buffer is ui legacy buffer at [0], so does need to take account of stride and offset + r = masterIni->AllocateFrameBuffers(aScreenNumber, screen->iCompositionBuffers + 1, maxSize); + } + + if (r == KErrNone) + { + buffer.iScreenBuffer.iDisplayBufferOffset = 0; + masterIni->iBufferSet[aScreenNumber].iDisplayChannel = aDisplay; + masterIni->InitBitmapHeader(*screen, &buffer.iInfo); + masterIni->InitBufferFormat(*screen, buffer.iBufferFormat); + if(systemIni->VideoInfoForDisplayDriver(aScreenNumber,screen->iCurrentMode, videoInfo, ETrue)) + { + r = aDisplay->Initialize(info, + FlipToDisplayRotation(screen->iScreenRotation), + hWnd, buffer.iScreenBuffer.iFrameBuffers, + buffer.iScreenBuffer.iMemChunks, + buffer.iDsaBuffer, + videoInfo.iSizeInPixels,videoInfo.iSizeInTwips, + masterIni->iSupportedPixelFormatTable, + masterIni->iSupportedPixelFormatTableSize, + buffer.iBufferFormat); + } + else + { + Fault(EGuiVideoInfoUnavailable); + } + } + + if (r != KErrNone && __e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1) + { + // Release any that were allocated + masterIni->ReleaseFrameBuffers(aScreenNumber); + } + } + else + { + // Display driver disconnected + if (__e32_atomic_tas_ord32(&buffer.iDisplayDriverCount, 1, -1, 0) == 1) + { + // All drivers disconnected, deallocate memory. + masterIni->ReleaseFrameBuffers(aScreenNumber); + } + } + + return r; + } + + +void DWinsUi::SetVirtualKey(const TBool aProcessing, const TInt aCommandData, const TEmulCommand aCommand) + { + iProcessingVirtualKey = aProcessing; + iFakedVirtualKey = aCommandData; + iVirtualKeyCommand = aCommand; + } + +TBool DWinsUi::WasVirtualKey(TInt& aCommandData, TEmulCommand& aCommand) + { + if (iProcessingVirtualKey) + { + + aCommandData = iFakedVirtualKey; + aCommand = iVirtualKeyCommand; + } + return iProcessingVirtualKey; + } + + +TInt DWinsUi::DoDefineEmulatorControl(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineEmulatorControl(aValue); + } + + +TInt DWinsUi::DefineEmulatorControl(const char* aValue) + { + + //example EmulatorControl SelectConfig 2 rect 223,640 29,22 + //example EmulatorControl NextConfig rect 223,640 29,22 + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt err = KErrNone; + + TEmulCommand command = ENoCommand; + TInt data = 0; + if (_strnicmp(beg, "SelectConfig", end-beg) == 0) + { + //get the int param which is the config to switch to + beg = end; + char * e; + data = strtol(beg, &e,0); + if (beg == e) + err = KErrArgument; + end = e; + command = ESelectConfig; + } + else if(_strnicmp(beg, "NextConfig", end-beg) == 0) + + { + command = ENextConfig; + } + else + err = KErrArgument; + + if (err != KErrNone) + return err; + + //get the shape + beg = skipws(end); + end = skiptok(beg); + if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0) + return KErrArgument; + + // get the parameters + beg = skipws(end); + char* end2; + TInt x = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt y = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + beg = skipws(end2); + TInt w = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt h = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + + VKRect* pRect = new VKRect(data, command, x, y, w, h); + if (!pRect) + return KErrNoMemory; + return iVirtualKeys.Append(pRect); + + } + + +TInt DWinsUi::DoDefineVirtualKey(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineVirtualKey(aValue); + } + +TInt DWinsUi::DefineVirtualKey(const char* aValue) + { + // Get the key to map + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt key = iKeyboard.GetEPOCKeyCode(TPtrC8((const TUint8*)beg, end-beg)); + if (key == KErrNotFound) + return key; + + //get the shape + beg = skipws(end); + end = skiptok(beg); + if (end - beg != 4 || _strnicmp(beg, "rect", 4) != 0) + return KErrArgument; + + // get the parameters + beg = skipws(end); + char* end2; + TInt x = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt y = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + beg = skipws(end2); + TInt w = strtol(beg, &end2, 10); + if (beg == end2 || *end2++ != ',') + return KErrArgument; + beg = end2; + TInt h = strtol(beg, &end2, 10); + if (beg == end2) + return KErrArgument; + + VKRect* pRect = new VKRect(key, EKey, x, y, w, h); + if (!pRect) + return KErrNoMemory; + return iVirtualKeys.Append(pRect); + } + + +LOCAL_C TInt readBitmapInfo(PBITMAPINFOHEADER aHeader, const char* aFileName) + { + PBITMAPFILEHEADER pbmfh=NULL; + PBITMAPINFOHEADER pbmih=NULL; + TInt bfOffBits; + + HANDLE fh=CreateFileA(aFileName,GENERIC_READ,NULL,NULL,OPEN_EXISTING,NULL,NULL); + if (!fh || fh==INVALID_HANDLE_VALUE) + return KErrNotFound; + + TInt r=KErrNone; + + // read in the bitmap file header. save the offset to bits. + pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER)); + if (pbmfh==NULL) + { + r=KErrNotFound; + goto exit; + } + DWORD bytesRead; + ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER), &bytesRead, NULL); + bfOffBits=pbmfh->bfOffBits; + + // read in the bitmap info header and the color table right after it. + pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER)); + if (pbmih==NULL) + { + r=KErrNotFound; + goto exit; + } + ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + *aHeader=*pbmih; +exit: + LocalFree(LocalHandle ((LPSTR)pbmih)); + LocalFree(LocalHandle ((LPSTR)pbmfh)); + CloseHandle(fh); + return r; + } + +HBITMAP readBitmap(HDC aHdc, const char* aFileName) +// +// reads a BMP file from disk and returns a HBITMAP +// + { + HBITMAP hbm=NULL; + PBITMAPFILEHEADER pbmfh=NULL; + PBITMAPINFOHEADER pbmih=NULL; + TUint8 *pBits=NULL; + TInt bfOffBits; + TInt nbytes; + + HANDLE fh=CreateFileA(aFileName, GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL); + if (!fh || fh==INVALID_HANDLE_VALUE) + return NULL; + + nbytes=GetFileSize((HANDLE)fh, NULL); + // read in the bitmap file header. save the offset to bits. + pbmfh = (PBITMAPFILEHEADER)LocalAlloc(LPTR, sizeof(BITMAPFILEHEADER)); + if (pbmfh==NULL) + goto exit; + DWORD bytesRead; + ReadFile(fh, (LPVOID)pbmfh, sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + bfOffBits=pbmfh->bfOffBits; + + // read in the bitmap info header and the color table right after it. + pbmih = (PBITMAPINFOHEADER)LocalAlloc(LPTR, bfOffBits- sizeof(BITMAPFILEHEADER)); + if (pbmih==NULL) + goto exit; + ReadFile(fh, (LPVOID)pbmih, bfOffBits-sizeof(BITMAPFILEHEADER),&bytesRead,NULL); + + // finally read in the bit data. + pBits = (PBYTE)LocalAlloc (LPTR, (nbytes - bfOffBits)); + if (pBits==NULL) + goto exit; + ReadFile(fh, (LPVOID)pBits, nbytes-bfOffBits,&bytesRead,NULL); + + hbm=CreateDIBitmap(aHdc, pbmih, CBM_INIT, pBits,(PBITMAPINFO) pbmih, DIB_RGB_COLORS); +exit: + LocalFree(LocalHandle ((LPSTR)pBits)); + LocalFree(LocalHandle ((LPSTR)pbmih)); + LocalFree(LocalHandle ((LPSTR)pbmfh)); + CloseHandle(fh); + return hbm; + } + +void LoadFasciaBitmap(TInt aScreen) + { + HDC hdc=GetDC(TheWin[aScreen]); + RECT windowRect = {0}; + windowRect.right=systemIni->iScreens[aScreen]->iXYInputWidth; + windowRect.bottom=systemIni->iScreens[aScreen]->iXYInputHeight; + HBITMAP screenBitmap=readBitmap(hdc, systemIni->iScreens[aScreen]->iFasciaFileName); + if (screenBitmap==NULL) + { + screenBitmap=CreateCompatibleBitmap(hdc, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top); + HDC hdcMem=CreateCompatibleDC(hdc); + SelectObject(hdcMem, screenBitmap); + PatBlt(hdcMem, 0, 0, windowRect.right-windowRect.left, windowRect.bottom-windowRect.top, BLACKNESS); + DeleteDC(hdcMem); + } + __ASSERT_ALWAYS(screenBitmap!=NULL,Fault(EGuiCreateBitmap)); + TheScreenBitmap[aScreen]=screenBitmap; + + DrawLeds(); + + ReleaseDC(TheWin[aScreen], hdc); + } +TBool DWinsUi::MultiTouchEnabled() const + { + return iMultiTouchEnabled; + } + +TBool DWinsUi::GCEEnabled() const + { + return iGCEEnabled; + } + +TInt DWinsUi::MultiTouchProximityStep() const + { + return iMultiTouchProximityStep; + } + +TInt DWinsUi::MultiTouchPressureStep() const + { + return iMultiTouchPressureStep; + } + +TBool DWinsUi::OnDigitizer(TInt aX, TInt aY) const + { + if (!iDigitizerEnabled) + return EFalse; + switch(CurrentFlipState[0]) + { + case EEmulatorFlipRestore: + { + aX -= iDigitizerOffsetX; + aY -= iDigitizerOffsetY; + break; + } + case EEmulatorFlipInvert: + { + aX -= systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth; + aY -= systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight; + break; + } + case EEmulatorFlipRight: + { + TInt oldY = aY; + aY = aX - (systemIni->iScreens[0]->iScreenHeight - iDigitizerOffsetY - iDigitizerHeight); + aX = oldY - iDigitizerOffsetX; + break; + } + case EEmulatorFlipLeft: + { + TInt oldY = aY; + aY = aX - iDigitizerOffsetY; + aX = oldY - (systemIni->iScreens[0]->iScreenWidth - iDigitizerOffsetX - iDigitizerWidth); + break; + } + } + return (TUint(aX) < TUint(iDigitizerWidth) && TUint(aY) < TUint(iDigitizerHeight)); + } + +LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos) +// +// Add a mouse event. +// + { + if (systemIni->OnDigitizer(aXpos, aYpos)) + { + TRawEvent v; + v.Set(aType,aXpos,aYpos); + TheEventQ.Add(v); + } + } + +LOCAL_C void addMouseEvent(TRawEvent::TType aType,TInt aXpos,TInt aYpos,TInt aZpos, TInt aPointerId=0) +// +// Add a multitouch mouse event. +// + { + if (systemIni->OnDigitizer(aXpos, aYpos)) + { + TRawEvent v; + v.Set(aType,aXpos,aYpos, aZpos); + v.SetPointerNumber(static_cast(aPointerId)); + TheEventQ.Add(v); + } + } +LOCAL_C void addKeyEvent(TRawEvent::TType aType,TInt aKey) + { + TRawEvent v; + v.Set(aType, aKey); + TheEventQ.Add(v); + } + + +LOCAL_C void SwitchConfiguration(TInt aData, TBool aSendFlipKey = ETrue) + { + if (aData < 0 || aData >= masterIni->iSystemInis.Count()) + return; + + CurrentConfiguration = aData; + systemIni = masterIni->iSystemInis[aData]; + + //get the correct fascia bitmaps + TInt screens=systemIni->iScreens.Count(); + TInt i; + TUint disabledWinType=ENormalResolution; + for(i=0;iiBufferSet[i].iDisplayState!=ENormalResolution) + { + disabledWinType=masterIni->iBufferSet[i].iDisplayState; + } + } + + //update the window title + if (disabledWinType!=ENormalResolution && disabledWinType < 4) //hardwired 4 because the code below is hardwired + { //string may be multi-part indexed by disable type, or it may not + CHAR* firstsemi=strchr(systemIni->iWindowTitle,';'); + CHAR* secondsemi=NULL; + if (firstsemi) + { + secondsemi=strchr(firstsemi+1,';'); + } + if (firstsemi&&secondsemi) + { + *firstsemi='\0'; + *secondsemi='\0'; + char* ptr[4]={0,systemIni->iWindowTitle,firstsemi+1,secondsemi+1}; + SetWindowTextA(TheControlWin, ptr[disabledWinType]); + *firstsemi=';'; + *secondsemi=';'; + } + else + { + SetWindowTextA(TheControlWin, systemIni->iWindowTitle); + } + + } + else + { + SetWindowTextA(TheControlWin, systemIni->iWindowTitle); + } + //resize and repaint the current window anyway. + //the text window server doesn't respond to orientation messages + for(i=0;iiScreens[i]->iScreenRotation,0); + } + + //pass on the orientation key to the windows server + if (aSendFlipKey) + { + if (!WinsGuiPowerHandler->iStandby) + { + addKeyEvent(TRawEvent::EKeyDown, systemIni->iInitialFlipMsg); + addKeyEvent(TRawEvent::EKeyUp, systemIni->iInitialFlipMsg); + } + else + { + //remember the flip message so we can send it to the window server when we come out of standby + SavedFlipMessage = systemIni->iInitialFlipMsg; + } + } + } +/** +Sets the specified screen to the given width and height, if available. + +The configurations are searched to find a match, taking the display state into +account. If no configuration is available, the request is ignored. + +@param aScreenNumber the screen index +@param aWidth the desired width +@param aHeight the desired height +**/ +void DMasterIni::SetDisplaySize(TInt aDisplayNumber, TInt aWidth, TInt aHeight) + { + TInt displayCount = iBufferSet.Count(); + + if (aDisplayNumber < 0 || aDisplayNumber >= displayCount) + { + // Invalid screen number, discard. + return; + } + + if (iBufferSet[aDisplayNumber].iDisplayState != ENormalResolution) + { + // No (non-zero) resolutions available, discard. + return; + } + + TInt count = iSystemInis.Count(); + TInt index; + for (index = 0; index < count; index++) + { + DWinsUi* newIni = masterIni->iSystemInis[index]; + DScreenProperties* newProps = newIni->iScreens[aDisplayNumber]; + + if (newProps->iScreenWidth == aWidth && newProps->iScreenHeight == aHeight) + { + // Found a potential match. Check other screens match their current size. + if (newIni == systemIni) + { + // Current configuration, already in use. Nothing to do. + break; + } + + TInt display; + for (display = 0; display < displayCount; display++) + { + if (display == aDisplayNumber) + { + // No need to check the display we are changing + continue; + } + + DScreenProperties* currentPropsN = systemIni->iScreens[display]; + DScreenProperties* newPropsN = newIni->iScreens[display]; + + if (newPropsN->iScreenWidth != currentPropsN->iScreenWidth || + newPropsN->iScreenHeight != currentPropsN->iScreenHeight) + { + // Resolution mismatch, try next configuration. + break; + } + } + + if (display == displayCount) + { + // Match found, switch to this configuration and stop. Force + // rotation to the same as the current rotation. + newProps->iScreenRotation = systemIni->iScreens[aDisplayNumber]->iScreenRotation; + SwitchConfiguration(index); + break; + } + } + } + } + + +void DMasterIni::SetBufferFormat(TInt aDisplayNumber, TUint aAggregateSize, RDisplayChannel::TPixelFormat aPixelFormat) + { + TInt displayCount = iBufferSet.Count(); + + if (aDisplayNumber < 0 || aDisplayNumber >= displayCount) + { + // Invalid screen number, discard. + return; + } + + LPBITMAPV4HEADER info = &iBufferSet[aDisplayNumber].iInfo; + + // update the bitmap header taking in consideration the new pixel format + switch (aPixelFormat) + { + case EUidPixelFormatXRGB_4444: + case EUidPixelFormatARGB_4444: + info->bV4BitCount=16; + info->bV4V4Compression = BI_BITFIELDS; + info->bV4RedMask = 0x0F00; + info->bV4GreenMask = 0x00F0; + info->bV4BlueMask = 0x000F; + break; + case EUidPixelFormatRGB_565: + info->bV4BitCount=16; + info->bV4V4Compression = BI_BITFIELDS; + info->bV4RedMask = 0xF800; + info->bV4GreenMask = 0x07E0; + info->bV4BlueMask = 0x001F; + break; + case EUidPixelFormatXRGB_8888: // Really 32bpp, but top 8 unused + case EUidPixelFormatARGB_8888: + case EUidPixelFormatARGB_8888_PRE: + info->bV4BitCount=32; + info->bV4V4Compression = BI_RGB; + // Mask is implicit for BI_RGB compression + break; + default: + // We got an error, it seems. Let's ignore the message + return; + } + iBufferSet[aDisplayNumber].iBufferFormat.iPixelFormat = aPixelFormat; + + // taking advantage of limiting the width and size to KMaxTInt16 + TInt width = aAggregateSize & 0x0000ffff; + TInt height = (aAggregateSize >> 16) & 0x0000ffff; + + // let's deal with the new size just received + iBufferSet[aDisplayNumber].iBufferFormat.iSize.iWidth = width; + iBufferSet[aDisplayNumber].iBufferFormat.iSize.iHeight = height; + + // update the bitmap header, taking in consideration the rotation + switch (CurrentFlipState[aDisplayNumber]) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + info->bV4Width = width; + info->bV4Height = -height; + break; + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + info->bV4Width = height; + info->bV4Height = -width; + break; + } + // finally, update the image size + SetImageSize(aDisplayNumber); + } + +void DMasterIni::SetImageSize(TInt aScreenNumber) + { + TInt displayCount = iBufferSet.Count(); + + if (aScreenNumber >= 0 && aScreenNumber < displayCount) + { + LPBITMAPV4HEADER info = &iBufferSet[aScreenNumber].iInfo; + TInt bpp = _ALIGN_UP(info->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32 + TInt widthInBpp = info->bV4Width * bpp; + //rounding to 32 bits (4 octets) and converting, then, bits to octets; + TInt scanLineInBytes = _ALIGN_UP(widthInBpp, 32) >> 3; + // info->bV4Height is negative or zero + info->bV4SizeImage = -info->bV4Height * scanLineInBytes; + } + } + +LOCAL_C void NextConfiguration() + { + TInt config = CurrentConfiguration; + if (++config == masterIni->iSystemInis.Count()) + config = 0; + SwitchConfiguration(config); + } + + + +LOCAL_C TBool ProcessedByEmulatorKey(TInt aScanCode, HWND hWnd,TUint message,TUint wParam,TUint lParam) + { + + TBool rVal = EFalse; + rVal = ETrue; + for (TInt i=0;iiControlHotKeys.Count();i++)//check key combinations + { + if (systemIni->iControlHotKeys[i]->CheckCombinationPressed()) + { + switch (systemIni->iControlHotKeys[i]->iCommand) + { + + case ENextConfig: + NextConfiguration(); + break; + + case ESelectConfig: + SwitchConfiguration(systemIni->iControlHotKeys[i]->iData); + break; + + } + return ETrue; + } + } + switch (aScanCode) + { + + case EStdKeyF4: + { + // Simulate a change of media card + TInt irq = NKern::DisableAllInterrupts(); + if (*Wins::MediaDoorOpenPtr()) + { + *Wins::CurrentPBusDevicePtr() += 1; + if (*Wins::CurrentPBusDevicePtr() == 2) + { + *Wins::CurrentPBusDevicePtr() = -1; + } + } + NKern::RestoreInterrupts(irq); + + // pass on to the windows system so that if + // Alt-F4 is pressed the window will close + if (hWnd) + DefWindowProcA(hWnd,message,wParam,lParam); + break; + } + + default: + rVal = EFalse; + break; + } + return rVal; + } + +LOCAL_C void MultiChildWndPointer(TUint aMessage,TInt aXpos,TInt aYpos, TInt aZ, TInt aPointerId) +// +// Handle a multi-touch pointer event in the Symbian OS screen window +// + { + TRawEvent::TType eventType=TRawEvent::ENone; + CHAR buf[50]; + + if (aZ <= TheMultiTouch->iZMaxRange) //negative + { + eventType = TRawEvent::EPointer3DOutOfRange; + wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("Out Of Range")); + SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf)); + } + else + { + wsprintf((LPTSTR)buf, (LPCTSTR)TEXT("%d: %d,%d,%d"), aPointerId, aXpos,aYpos,aZ); + SendMessage(hwndStatus, SB_SETTEXT, aPointerId , (LPARAM)(buf)); + switch (aMessage) + { + case WM_MOUSEMOVE: + { + eventType=TRawEvent::EPointerMove; + break; + } + case WM_LBUTTONDOWN: + { + SetCapture(TheChildWin[0]); + eventType = TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + { + ReleaseCapture(); + eventType = TRawEvent::EButton1Up; + break; + } + case WM_RBUTTONDOWN: + { + eventType = TRawEvent::EButton3Down; + break; + } + case WM_RBUTTONUP: + { + eventType = TRawEvent::EButton3Up; + break; + } + case WM_MOUSEWHEEL: + { + eventType = TRawEvent::EPointerMove; + break; + } + default: + return; + } + } + + if (!WinsGuiPowerHandler->iStandby) + { + addMouseEvent(eventType, aXpos, aYpos, aZ, aPointerId); + } + } + +LOCAL_C void ChildWndPointer(TUint message,TInt aXpos,TInt aYpos) +// +// Handle a pointer event in the Symbian OS screen window +// + { + // Enable the multitouch if the cursor is inside the main client window + if (DMultiTouch::iMultiTouchCreated) + { + RECT client; + WINDOWINFO info; + GetWindowInfo(TheChildWin[0], &info); + POINT pt = {aXpos+(TInt)info.rcClient.left, aYpos+(TInt)info.rcClient.top}; + if (GetWindowRect(TheChildWin[0], &client) && + (PtInRect(&client,pt)!=NULL) && !DMultiTouch::iMultiTouchTempEnabled) // within the window + { + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled()) + { + if(TheMultiTouch->Register()) // Register successfully + { + DMultiTouch::iMultiTouchTempEnabled = TRUE; + //Show the status bars at the bottom of the emulator + SetWindowPos(hwndStatus,0,0,0,0,0,SWP_SHOWWINDOW); + SetFocus(TheWin[0]); + SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512))); + } + } + } + } + TRawEvent::TType eventType=TRawEvent::ENone; + switch (message) + { + case WM_MOUSEMOVE: + eventType=TRawEvent::EPointerMove; + break; + case WM_LBUTTONDOWN: + { + SetCapture(TheChildWin[0]); + eventType=TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + ReleaseCapture(); + eventType=TRawEvent::EButton1Up; + break; + case WM_RBUTTONDOWN: + eventType=TRawEvent::EButton3Down; + break; + case WM_RBUTTONUP: + eventType=TRawEvent::EButton3Up; + break; + case WM_MBUTTONDOWN: + eventType=TRawEvent::EButton2Down; + break; + case WM_MBUTTONUP: + eventType=TRawEvent::EButton2Up; + break; + } + if (!WinsGuiPowerHandler->iStandby) + { + addMouseEvent(eventType, aXpos, aYpos); + } + } + +LOCAL_C void FrameWndPointer(TUint message,TInt aXpos,TInt aYpos, TInt aScreenNumber, TInt aPointerId = 0) +// +// Handle a frame wnd pointer event. +// + { + static bool processingScreenOn=FALSE; + TEmulCommand command = ENoCommand; + TInt commandData = 0; + TBool mouseEvent = ETrue; + + TRawEvent::TType eventType=TRawEvent::ENone; + + TViewport& viewport = systemIni->iScreens[aScreenNumber]->iViewport; + aXpos += viewport.GetViewportOffsetX(); // make mouse-coords relative to fascia edge even if window is scrolled + aYpos += viewport.GetViewportOffsetY(); + + switch (message) + { + case WM_MOUSEMOVE: + { + TInt newX, newY; + systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY); + + if (aPointerId == 0) + { // only system pointer changes shape + if (systemIni->GetVirtualKey(command, newX, newY) >= 0) + { + HMODULE hmodule = GetModuleHandleA("winsgui.dll"); + SetCursor(LoadCursorA((HINSTANCE)hmodule,MAKEINTRESOURCEA(OVERKEY))); //hand cursor + } + else + SetCursor(LoadCursorA(NULL,MAKEINTRESOURCEA(32512))); //ICD_ARROW + } + + eventType=TRawEvent::EPointerMove; + + } + break; + case WM_LBUTTONDOWN: + { + SetCapture(TheWin[0]); + //check the configuration + TInt newX, newY; + + //if the emulator screen is rotated, rotate/flip the current mouse cursor position + //so it can be checked to see if it is in a key region. + systemIni->TranslateMouseCoords(CurrentFlipState[0], aXpos, aYpos, systemIni->iScreens[0]->iXYInputWidth, systemIni->iScreens[0]->iXYInputHeight, newX, newY); + commandData = systemIni->GetVirtualKey(command, newX, newY); + + if (commandData >= 0) + { + eventType=TRawEvent::EKeyDown; + mouseEvent = EFalse; + systemIni->SetVirtualKey(ETrue, commandData, command); + } + else + eventType=TRawEvent::EButton1Down; + } + break; + case WM_LBUTTONUP: + ReleaseCapture(); + if (processingScreenOn) + { + // ignore button up - button down was switching things on + processingScreenOn=FALSE; + return; + } + if (systemIni->WasVirtualKey(commandData, command)) + { + eventType=TRawEvent::EKeyUp; + mouseEvent = EFalse; + systemIni->SetVirtualKey(EFalse, EStdKeyNull, ENoCommand); + } + else + eventType=TRawEvent::EButton1Up; + break; + case WM_RBUTTONDOWN: + eventType=TRawEvent::EButton3Down; + break; + case WM_RBUTTONUP: + eventType=TRawEvent::EButton3Up; + break; + case WM_MBUTTONDOWN: + eventType=TRawEvent::EButton2Down; + break; + case WM_MBUTTONUP: + eventType=TRawEvent::EButton2Up; + break; + } + if (mouseEvent) + { + + if (!WinsGuiPowerHandler->iStandby) + { + /* + mouse events are relative to the child window position + and are clipped to the digitzer region in addMouseEvent + so all the mouse clicks are passed on here after being translated + to the child window coordinate system (under the current rotation) + */ + TInt newX, newY; + switch (CurrentFlipState[0]) + { + case EEmulatorFlipRestore: + default: + newX = aXpos - systemIni->iScreens[0]->iScreenOffsetX; + newY = aYpos - systemIni->iScreens[0]->iScreenOffsetY; + break; + case EEmulatorFlipInvert: + newX = aXpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX); + newY = aYpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY); + break; + case EEmulatorFlipLeft: + newX = aXpos - systemIni->iScreens[0]->iScreenOffsetY; + newY = aYpos - (systemIni->iScreens[0]->iXYInputWidth - systemIni->iScreens[0]->iScreenWidth - systemIni->iScreens[0]->iScreenOffsetX); + break; + case EEmulatorFlipRight: + newX = aXpos - (systemIni->iScreens[0]->iXYInputHeight - systemIni->iScreens[0]->iScreenHeight - systemIni->iScreens[0]->iScreenOffsetY); + newY = aYpos - systemIni->iScreens[0]->iScreenOffsetX; + break; + } + addMouseEvent(eventType, newX, newY); + } + } + else if ((((message == WM_LBUTTONDOWN && command == EKey) && !ProcessedByEmulatorKey((TUint8)commandData,0,0,0,0))) + || (message == WM_LBUTTONUP)) + { + switch (command) + { + case EKey: + if (!WinsGuiPowerHandler->iStandby) + addKeyEvent(eventType, (TUint8)commandData); + break; + + case ENextConfig: + NextConfiguration(); + break; + + case ESelectConfig: + SwitchConfiguration(commandData); + break; + } + } + } + +LOCAL_C TInt ScreenFromHWND(HWND aHwnd,HWND* pWin) + { + TInt screens=systemIni->iScreens.Count(); + TInt r=-1; + for(TInt i=0;iUnRegister()) + { + SetWindowPos(hwndStatus,0,0,0,0,0,SWP_HIDEWINDOW); + } + } + FrameWndPointer(message, aXpos-info.rcClient.left, aYpos-info.rcClient.top, 0, aPointerId); + } + } + } + } + +LOCAL_C DScreenProperties* ScreenPropsFromHWND(HWND aHwnd, HWND* pWin) + { + TInt screenNumber = ScreenFromHWND(aHwnd, pWin); + + if(screenNumber >=0) + { + return systemIni->iScreens[screenNumber]; + } + return NULL; + + } + + +TInt APIENTRY childWinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The child window function. +// + { + TInt screenNumber = 0; + TRawEvent v; + switch (message) + { + case WM_FLIP_MESSAGE: // pass the flip message onto the parent window + { + screenNumber =ScreenFromHWND(hWnd,TheChildWin); + if(TUint(screenNumber) < TUint(systemIni->iScreens.Count())) + PostMessageA(TheWin[screenNumber],WM_FLIP_MESSAGE,wParam,NULL); + break; + } + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MOUSEMOVE: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + { + if (DMultiTouch::iMultiTouchTempEnabled) + { + DMultiTouch::iMultiTouchTempEnabled = FALSE; + } + screenNumber=ScreenFromHWND(hWnd,TheChildWin); + if(screenNumber==0) + { + ChildWndPointer(message,(TInt16)(lParam&0xFFFF),(TInt16)((lParam>>16)&0xFFFF)); + } + break; + } + case WM_PAINT: + if (!PaintWindowFromBuffer(hWnd)) + { + // Original behaviour + ValidateRect(hWnd,NULL); + v.Set(TRawEvent::ERedraw); + TheEventQ.Add(v); + } + break; + case WM_ACTIVATE: + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + case WM_SYSKEYUP: + case WM_KEYUP: + Fault(EGuiChildWinProc); + break; + case WM_DESTROY: + break; + + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + break; + + case WMU_SET_DISPLAY_BUFFER: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + if (TUint(screenNumber) < TUint(systemIni->iScreens.Count())) + { + masterIni->iBufferSet[screenNumber].iDisplayBuffer = (LPVOID)lParam; + } + break; + case WMU_SET_DISPLAY_SIZE: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + masterIni->SetDisplaySize(screenNumber, wParam, lParam); + break; + + case WMU_SET_BUFFER_FORMAT: + screenNumber = ScreenFromHWND(hWnd, TheChildWin); + masterIni->SetBufferFormat(screenNumber, wParam, (RDisplayChannel::TPixelFormat) lParam); + break; + + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + } + + +LOCAL_C TBool PaintWindowFromBuffer(HWND hWnd) + { + TInt screenNumber = ScreenFromHWND(hWnd,TheChildWin); + if (TUint(screenNumber) >= TUint(masterIni->iBufferSet.Count())) + { + return EFalse; + } + + LPVOID displayBuffer = masterIni->iBufferSet[screenNumber].iDisplayBuffer; + if (!displayBuffer) + { + return EFalse; + } + + TInt frameOffset = masterIni->iBufferSet[screenNumber].iScreenBuffer.iDisplayBufferOffset; + displayBuffer=LPVOID(frameOffset+(char*)displayBuffer); + + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + + // Paint directly from the buffer to the window + LPBITMAPINFO info = (LPBITMAPINFO)&masterIni->iBufferSet[screenNumber].iInfo; + WORD width = (WORD)info->bmiHeader.biWidth; + WORD height = (WORD)-info->bmiHeader.biHeight; // stored -ve in info + SetDIBitsToDevice(ps.hdc, + 0, 0, // Dst X, Y + width, height, // Src W, H + 0, 0, // Src X, Y + 0, // Src offset to first line + height, // Src lines available + displayBuffer, // Src pointer to pixels + info, // Src info + DIB_RGB_COLORS); + + EndPaint(hWnd, &ps); + + return TRUE; + } + + +LOCAL_C void CalcTextPos(TInt aScreen, TInt& aX, TInt& aY) + { + switch (CurrentFlipState[aScreen]) + { + case EEmulatorFlipInvert: + aX = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth); + aY = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight); + break; + case EEmulatorFlipLeft: + aX = systemIni->iScreens[aScreen]->iScreenOffsetY; + aY = systemIni->iScreens[aScreen]->iXYInputWidth-(systemIni->iScreens[aScreen]->iScreenOffsetX+systemIni->iScreens[aScreen]->iScreenWidth); + break; + case EEmulatorFlipRight: + aX = systemIni->iScreens[aScreen]->iXYInputHeight-(systemIni->iScreens[aScreen]->iScreenOffsetY+systemIni->iScreens[aScreen]->iScreenHeight); + aY = systemIni->iScreens[aScreen]->iScreenOffsetX; + break; + case EEmulatorFlipRestore: + default: + aX = systemIni->iScreens[aScreen]->iScreenOffsetX; + aY = systemIni->iScreens[aScreen]->iScreenOffsetY; + break; + } + //subtract viewport offset here + aX -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetX(); + aY -= systemIni->iScreens[aScreen]->iViewport.GetViewportOffsetY(); + } + +TInt APIENTRY ctrlwinProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The control window function +// + { + switch(message) + { + case WM_SYSCOMMAND: + { + switch(wParam) + { + case 1: + { + NextConfiguration(); + return 0; + } + case SC_MINIMIZE: + case SC_RESTORE: + { + if (wParam == SC_RESTORE) + Active(); + for(TInt ix=0;ixiScreens.Count();ix++) + { + SendMessage(TheWin[ix],message,wParam,lParam); + } + if (wParam == SC_MINIMIZE) + Inactive(); + } + } + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + case WM_CLOSE: // tell all emulator screen windows to close + { + for(TInt i=0;iiScreens.Count();i++) + { + DestroyWindow(TheWin[i]); + } + DestroyWindow(hWnd); + break; + } + case WM_DESTROY: + { + // save the main window position information + HANDLE hSysIni; + hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); + DScreenProperties* screenProps; + if (hSysIni != INVALID_HANDLE_VALUE) + { + DWORD numWritten; + //write an identifier into file so that program can avoid loading old version + WriteFile(hSysIni, &KDatFileVersion, sizeof(TInt), &numWritten, 0); + + //record current configuration at start of file. + WriteFile(hSysIni, &CurrentConfiguration, sizeof(TInt), &numWritten, 0); + + //Write out the state for each window. + for(TInt i=0;iiScreens.Count();i++) + { + screenProps= systemIni->iScreens[i]; + + TWindowState winState= screenProps->GetWindowState(); + WriteFile(hSysIni, &winState, sizeof(TWindowState), &numWritten, 0); + + + } + } + CloseHandle(hSysIni); + + PostQuitMessage(KErrNone); + break; + } + case WM_INPUT: + { + if (!DMultiTouch::iMultiTouchTempEnabled) + { + for(TInt ix=0;ixiScreens.Count();ix++) + { + DMultiTouch::iMultiTouchTempEnabled = TRUE; + + SendMessage(TheWin[ix],message,wParam,lParam); + } + } + else if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled()) + { + TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[0]); + } + else + { + Fault(EGuiInvalidMultiTouch); + } + break; + } + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + } + +TInt APIENTRY winProc(HWND hWnd,TUint message,TUint wParam,TUint lParam) +// +// The border window function. +// + { + + TRawEvent v; + + switch (message) + { + case WM_GETMINMAXINFO: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + + MINMAXINFO* minMaxInfo = reinterpret_cast(lParam); + minMaxInfo->ptMaxTrackSize.x = screenProps->iViewport.GetMaxWindowWidth(); + minMaxInfo->ptMaxTrackSize.y = screenProps->iViewport.GetMaxWindowHeight(); + + minMaxInfo->ptMaxSize.x = minMaxInfo->ptMaxTrackSize.x; + minMaxInfo->ptMaxSize.y = minMaxInfo->ptMaxTrackSize.y; + DefWindowProcA(hWnd, message, wParam, lParam); + + break; + } + + + + case WM_SIZE: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + //update size of viewport + viewport.SetViewportWidth(LOWORD(lParam)); + viewport.SetViewportHeight(HIWORD(lParam)); + + + //If resize goes beyond boundary of emulator then scroll to compensate + TInt ox = viewport.GetViewportOffsetX(); + TInt xs = ox + LOWORD(lParam) - viewport.GetMaxWidth(); + if (xs>0) + { + viewport.ScrollToX(ox-xs, hWnd); + } + + TInt oy = viewport.GetViewportOffsetY(); + TInt ys = oy + HIWORD(lParam) - viewport.GetMaxHeight(); + if (ys>0) + { + viewport.ScrollToY(oy-ys, hWnd); + } + + //Adjust ranges of scroll bars + viewport.UpdateScrollBarH(hWnd); + viewport.UpdateScrollBarV(hWnd); + + + + break; + } + case WM_HSCROLL: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + + switch (LOWORD(wParam)) + { + case SB_THUMBTRACK: + { + viewport.ScrollToX(HIWORD(wParam),hWnd); + break; + } + case SB_PAGELEFT: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() - viewport.GetViewportWidth(), hWnd ); + break; + } + case SB_PAGERIGHT: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() + viewport.GetViewportWidth() , hWnd); + break; + } + case SB_LINEUP: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() - 1, hWnd); + break; + } + case SB_LINEDOWN: + { + viewport.ScrollToX(viewport.GetViewportOffsetX() + 1, hWnd); + break; + } + + } + + + break; + } + + case WM_VSCROLL: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + + + switch (LOWORD(wParam)) + { + case SB_THUMBTRACK: + { + viewport.ScrollToY(HIWORD(wParam), hWnd); + break; + } + case SB_PAGELEFT: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() - viewport.GetViewportHeight() , hWnd); + break; + } + case SB_PAGERIGHT: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() + viewport.GetViewportHeight(), hWnd ); + break; + } + case SB_LINEUP: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() - 1, hWnd); + break; + } + case SB_LINEDOWN: + { + viewport.ScrollToY(viewport.GetViewportOffsetY() + 1, hWnd); + break; + } + + } + + break; + + } + + + case WM_FLIP_MESSAGE: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + + } + + TViewport& viewport = screenProps->iViewport; + RECT windowRect={0,0,0,0}; + GetClientRect(hWnd, &windowRect); + + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count())) + break; + PBITMAPV4HEADER info = &masterIni->iBufferSet[screenNumber].iInfo; + CurrentFlipState[screenNumber]=(TEmulatorFlip)wParam; + TBufferSet* bufferSet = &masterIni->iBufferSet[screenNumber]; + switch (CurrentFlipState[screenNumber]) + { + case EEmulatorFlipRestore: + case EEmulatorFlipInvert: + windowRect.right=systemIni->iScreens[screenNumber]->iXYInputWidth; + windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputHeight; + info->bV4Width = bufferSet->iBufferFormat.iSize.iWidth; + info->bV4Height = -bufferSet->iBufferFormat.iSize.iHeight; + break; + case EEmulatorFlipLeft: + case EEmulatorFlipRight: + windowRect.right=systemIni->iScreens[screenNumber]->iXYInputHeight; + windowRect.bottom=systemIni->iScreens[screenNumber]->iXYInputWidth; + info->bV4Width = bufferSet->iBufferFormat.iSize.iHeight; + info->bV4Height = -bufferSet->iBufferFormat.iSize.iWidth; + break; + } + AdjustWindowRect(&windowRect,KWinStyle,FALSE); + + + viewport.ScrollToX(0, hWnd); + viewport.ScrollToY(0, hWnd); + + + screenProps->iScreenRotation = (TEmulatorFlip)wParam; + + + RECT currentWindowRect; + GetWindowRect(hWnd,¤tWindowRect); + InvalidateRect(hWnd,NULL,FALSE); + MoveWindow( + TheWin[screenNumber], + max(currentWindowRect.left,0), // so the window doesn't disappear off the screen + max(currentWindowRect.top,0), + windowRect.right-windowRect.left, + windowRect.bottom-windowRect.top, + TRUE + ); + // move the child window + screenProps->iViewport.UpdateChildPos(hWnd); + + viewport.UpdateScrollBarH(hWnd); + viewport.UpdateScrollBarV(hWnd); + + InvalidateRect(hWnd,NULL,TRUE); + UpdateWindow(hWnd); + + break; + } + case WM_SYSKEYDOWN: + case WM_KEYDOWN: + if (!(HIWORD(lParam)&KF_REPEAT)) + { + + + TUint scanCode=DWinsKeyboard::ScanCodeToStandardKey(HIWORD(lParam)); + TUint newScanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam)); + MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()}; + TranslateMessage(&msg); + TUint charCode=0; + // look in the message queue to get character associated with keypress + // so long as the control, shift and alt keys aren't depressed + if (!(HIBYTE(GetKeyState(VK_CONTROL)) && HIBYTE(GetKeyState(VK_MENU)) && HIBYTE(GetKeyState(VK_SHIFT)))) + if (PeekMessageA(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE) && + scanCode == newScanCode) //no remapping + charCode=msg.wParam; + // Pass the character as the HIWORD of the Epoc scan code + + scanCode = newScanCode; + v.Set(TRawEvent::EKeyDown,(charCode<<16)|scanCode); + if (!ProcessedByEmulatorKey(scanCode,hWnd,message,wParam,lParam)) + TheEventQ.Add(v); + + } + break; + case WM_TIMER: + break; + case WM_EMUL_POWER_ON: + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(TUint(screenNumber) >= TUint(systemIni->iScreens.Count())) + break; +// HWND win = systemIni->iSecureDisplay ? TheSecureChildWin : TheChildWin; + HWND win = TheChildWin[screenNumber]; + if (wParam==TRUE) + { + ShowWindow(win, SW_HIDE); + ShowWindow(win, SW_SHOWNORMAL); + if (SavedFlipMessage) + { + addKeyEvent(TRawEvent::EKeyDown, SavedFlipMessage); + addKeyEvent(TRawEvent::EKeyUp, SavedFlipMessage); + SavedFlipMessage = 0; + } + } + else + { + ShowWindow(win, SW_SHOWNORMAL); + ShowWindow(win, SW_HIDE); + } + } + break; + case WM_SYSKEYUP: + case WM_KEYUP: + { + //get the key code, this will pick up if it has been remapped or not. + TUint scanCode = systemIni->iKeyboard.ScanCodeToRemappedKey(HIWORD(lParam)); + /* + * We could do this to support generation of special characters using Alt+KeyPadNum + * combinations, but we would need to find a way to suppress the generation of + * home/end scancodes etc., so leave it for the moment. + MSG msg={hWnd,message,wParam,lParam,GetMessageTime(),GetMessagePos()}; + TranslateMessage(&msg); + TUint charCode=0; + // look in the message queue to get character associated with keypress + if (PeekMessageU()(&msg,hWnd,WM_CHAR,WM_CHAR,PM_NOREMOVE)) + charCode=msg.wParam; + // Pass the character as the HIWORD of the Epoc scan code + v.Set(TRawEvent::EKeyUp,(charCode<<16)|scanCode); + */ + v.Set(TRawEvent::EKeyUp,scanCode); + TheEventQ.Add(v); + break; + } + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + { + //only handle mouse clicks on screen 0 + TInt xpos=((TInt16)(lParam&0xffff)); + TInt ypos = (TInt16)((lParam>>16)&0xFFFF); + if (DMultiTouch::iMultiTouchTempEnabled) + { + MultiChildWndPointer(message,xpos,ypos,0,0); + DMultiTouch::iMultiTouchTempEnabled = FALSE; + } + else + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(screenNumber!=0) + break; + FrameWndPointer(message,xpos,ypos,screenNumber); + } + break; + } + case WM_PAINT: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + TViewport& viewport = screenProps->iViewport; + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + + PAINTSTRUCT p; + + BeginPaint(hWnd,&p); + HDC hdcBits; + BITMAP bm; + hdcBits=CreateCompatibleDC(p.hdc); + GetObjectA(TheScreenBitmap[screenNumber],sizeof(BITMAP),&bm); + SelectObject(hdcBits,TheScreenBitmap[screenNumber]); + + RECT windowRect; + GetClientRect(TheWin[screenNumber],&windowRect); + + viewport.SetViewportHeight(windowRect.bottom); + viewport.SetViewportWidth(windowRect.right); + + + switch (CurrentFlipState[screenNumber]) + { + case EEmulatorFlipRestore: + { + BitBlt(p.hdc,0,0,windowRect.right,windowRect.bottom,hdcBits, + viewport.GetViewportOffsetX(),viewport.GetViewportOffsetY(),SRCCOPY); + break; + } + case EEmulatorFlipInvert: + { + TInt sourceX = screenProps->iXYInputWidth - viewport.GetViewportWidth() - viewport.GetViewportOffsetX(); + if(sourceX<0) + sourceX=0; + TInt sourceY = screenProps->iXYInputHeight - viewport.GetViewportHeight() - viewport.GetViewportOffsetY(); + if(sourceY<0) + sourceY=0; + TInt sourceWidth = viewport.GetMaxWidth()-sourceX - viewport.GetViewportOffsetX(); + TInt sourceHeight = viewport.GetMaxHeight()-sourceY - viewport.GetViewportOffsetY(); + + //when inverted it is necessary to translate the image by 1 pixel up and to the left, + //to avoid a glitch when scrolling using ScrollWindowEx() + POINT arrayPoints[3]={ + {sourceWidth-1,sourceHeight-1}, + {-1,sourceHeight-1}, + {sourceWidth-1,-1} + }; + PlgBlt(p.hdc,arrayPoints,hdcBits,sourceX,sourceY,sourceWidth,sourceHeight,NULL,NULL,NULL); + break; + } + case EEmulatorFlipLeft: + { + TInt offsetX = screenProps->iXYInputWidth- viewport.GetViewportHeight() - viewport.GetViewportOffsetY(); + TInt offsetY = viewport.GetViewportOffsetX(); + + POINT arrayPoints[3]={{0,windowRect.bottom},{0,0},{windowRect.right,windowRect.bottom}}; + PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL); + break; + } + case EEmulatorFlipRight: + { + TInt offsetX = viewport.GetViewportOffsetY(); + TInt offsetY = screenProps->iXYInputHeight - viewport.GetViewportWidth() - viewport.GetViewportOffsetX(); + + POINT arrayPoints[3]={{windowRect.right,0},{windowRect.right,windowRect.bottom},{0,0}}; + PlgBlt(p.hdc,arrayPoints,hdcBits,offsetX,offsetY,viewport.GetViewportHeight(),viewport.GetViewportWidth(),NULL,NULL,NULL); + break; + } + } + + + DeleteDC(hdcBits); + if (WinsGuiPowerHandler->iStandby) + { + TInt x,y; + CalcTextPos(screenNumber, x, y); + TextOutA(p.hdc, x, y, "Standby", 7); + } + else if (systemIni->iScreens[screenNumber]->iScreenOff) + { + TInt x,y; + CalcTextPos(screenNumber, x, y); + TextOutA(p.hdc, x, y, "Screen Off", 10); + } + EndPaint(hWnd,&p); + break; + } + case WM_ACTIVATE: + //Added so that change in modifier keys can be detected without sending + //EActive/EInActive to wserv as it results in switching the timers + if((wParam & 0xffff)!= WA_INACTIVE) + UpdateModifiers(); + break; + case WM_CHAR: + case WM_SYSCHAR: + case WM_DEADCHAR: + case WM_SYSDEADCHAR: + break; + case WM_CLOSE: //pass on message to control window, it will then destroy all e,ulator windows + SendMessage(TheControlWin,WM_CLOSE, NULL, NULL); + break; + case WM_DESTROY: + { + DScreenProperties* screenProps = ScreenPropsFromHWND(hWnd, TheWin); + if(screenProps == NULL) + { + return DefWindowProcA(hWnd, message, wParam, lParam); + } + + // save window's position information + screenProps->iWinPlace.length = sizeof(WINDOWPLACEMENT); + GetWindowPlacement(hWnd, &screenProps->iWinPlace); + + break; + } + case WM_INPUT: + { + if (systemIni->MultiTouchEnabled() && DMultiTouch::iMultiTouchSupported && systemIni->GCEEnabled()) + { + TInt screenNumber=ScreenFromHWND(hWnd,TheWin); + if(screenNumber==0) + { + TheMultiTouch->OnWmInput(hWnd, message, wParam, lParam,TheChildWin[screenNumber]); + } + } + else + { + Fault(EGuiInvalidMultiTouch); + } + break; + } + default: + return(DefWindowProcA(hWnd,message,wParam,lParam)); + } + return(FALSE); + + } + +void SetStatusBarFont(HWND& aStatusBar) + { + int statwidths[] = {100,200,300,400,500,600,700,800}; + SendMessage(aStatusBar, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths); + HFONT hOrigFont = (HFONT) SendMessage(aStatusBar, WM_GETFONT, 0, 0); + SetProp(aStatusBar, TEXT("PROP_ORIGINAL_FONT"), (HANDLE) hOrigFont); + LOGFONT lf; + GetObject(hOrigFont, sizeof(lf), &lf); + lf.lfHeight = (long)(lf.lfHeight / 1.5); + lf.lfWeight = FW_NORMAL; + HFONT hFont = CreateFontIndirect(&lf); + SetProp(aStatusBar, TEXT("PROP_ITALIC_FONT"), (HANDLE) hFont); + hFont = (HFONT) GetProp(hwndStatus, TEXT("PROP_ITALIC_FONT")); + SendMessage(aStatusBar, WM_SETFONT, (WPARAM) hFont, FALSE); + } + +DWORD WINAPI KernelWindowThread(LPVOID aArg) +// +// The kernel window thread. +// + { + HMODULE hmodule = GetModuleHandleA("winsgui.dll"); + __ASSERT_ALWAYS(hmodule!=NULL,Fault(EGuiGetModuleHandle)); + + WNDCLASSA w; + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC|CS_VREDRAW|CS_HREDRAW; + w.lpfnWndProc=(WNDPROC)ctrlwinProc; + w.hInstance=(HINSTANCE)aArg; + w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON)); + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszClassName="E32KernelControlWindow"; + + ATOM a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow)); + + RECT ctlrwindowRect={0,0,270,0}; + AdjustWindowRect(&ctlrwindowRect,KControlWinStyle,FALSE); + TInt ctrlwindowWidth=ctlrwindowRect.right-ctlrwindowRect.left; + TInt ctrlwindowHeight=ctlrwindowRect.bottom-ctlrwindowRect.top; + + TheControlWin=CreateWindowA( + "E32KernelControlWindow", + systemIni->iWindowTitle, + KInvisibleControlWinStyle, + KWinPosX, + KWinPosY, + ctrlwindowWidth, + ctrlwindowHeight, + (HWND)NULL, + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheControlWin!=NULL,Fault(EGuiKernelWindowCreate)); + + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC; + w.lpfnWndProc=(WNDPROC)winProc; + w.hInstance=(HINSTANCE)aArg; + w.hIcon=LoadIconA((HINSTANCE)hmodule,MAKEINTRESOURCEA(EPOC_ICON)); + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszClassName="E32KernelWindow"; + + a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterWindow)); + + memclr(&w, sizeof(WNDCLASSA)); + w.style=CS_OWNDC; + w.lpfnWndProc=(WNDPROC)childWinProc; + w.hInstance=(HINSTANCE)aArg; + w.hCursor=LoadCursorA(NULL,MAKEINTRESOURCEA(32512)); //ICD_ARROW + w.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH); + w.lpszMenuName=NULL; + w.lpszClassName="E32KernelChildWindow"; + a=RegisterClassA(&w); + __ASSERT_ALWAYS(a!=0,Fault(EGuiRegisterChildWindow)); + + if (masterIni && masterIni->iSystemInis.Count() > 1) + { + //add Configuration Items to the system menu if there's > 1 config + HMENU hMenu = GetSystemMenu(TheControlWin, FALSE); + InsertMenu(hMenu,5, MF_BYPOSITION|MF_SEPARATOR,0,NULL); + InsertMenuA(hMenu,6, MF_BYPOSITION|MF_STRING, 1, "Next Config..."); + } + + ShowWindow(TheControlWin,SW_SHOWDEFAULT); + UpdateWindow(TheControlWin); + + //Create frame windows and child windows + for(TInt screen=0;screeniScreens.Count();screen++) + { + + RECT windowRect={0,0,systemIni->iScreens[screen]->iXYInputWidth,systemIni->iScreens[screen]->iXYInputHeight}; + AdjustWindowRect(&windowRect,KWinStyle,FALSE); + TInt windowWidth=windowRect.right-windowRect.left; + TInt windowHeight=windowRect.bottom-windowRect.top; + + CHAR title[20]; + wsprintfA(title, "Screen %d", screen); + + TheWin[screen]=CreateWindowA( + "E32KernelWindow", + title, + KInvisibleWinStyle, + KWinPosX, + KWinPosY, + windowWidth, + windowHeight, + (HWND)NULL, + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheWin[screen]!=NULL,Fault(EGuiKernelWindowCreate)); + + LoadFasciaBitmap(screen); + + TheChildWin[screen]=CreateWindowA( + "E32KernelChildWindow", + "", + WS_CHILDWINDOW|WS_VISIBLE|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, + systemIni->iScreens[screen]->iScreenOffsetX, + systemIni->iScreens[screen]->iScreenOffsetY, + systemIni->iScreens[screen]->iScreenWidth, + systemIni->iScreens[screen]->iScreenHeight, + TheWin[screen], + NULL, + (HINSTANCE)aArg, + (LPSTR)NULL + ); + __ASSERT_ALWAYS(TheChildWin[screen]!=NULL,Fault(EGuiKernelChildWindowCreate)); + + // Create status bars + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled()) + { + HMODULE hmodComCtl = LoadLibrary(TEXT("comctl32.dll")); + typedef int (WINAPI* FNINITCC)(); + FNINITCC pfnInitCommonControls = GetProcAddress(hmodComCtl, "InitCommonControls"); + pfnInitCommonControls(); + hwndStatus = CreateWindowExA(0, STATUSCLASSNAMEA, NULL, + WS_CHILD | WS_VISIBLE | CCS_BOTTOM , + 0,0,0,0, + TheWin[0], NULL, GetModuleHandle(NULL), NULL); + SetStatusBarFont(hwndStatus); + SetWindowPos(hwndStatus,NULL, 0,0,0,0,SWP_HIDEWINDOW); + } + } + + //Restore window data from ini file if it exists. + HANDLE hSysIni = CreateFileA(systemIni->iSysIniFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); + TBool success=(hSysIni != INVALID_HANDLE_VALUE) ? ETrue : EFalse; + + DWORD numRead; + TInt fileVersion=0; + if(success) + { + ReadFile(hSysIni, &fileVersion, sizeof(TInt), &numRead, 0); + } + + //Check we are using a dat file created by this version of the program. + if(success && (fileVersion==KDatFileVersion) ) + { + + TInt savedConfiguration=0; //set this to default configuration + + if(ReadFile(hSysIni, &savedConfiguration, sizeof(TInt), &numRead, 0) && (numRead>0) ) + { + //Don't restore the saved configuration, see INC114502. + //This could be reenabled in future as an optional operation + //dependent on an entry in the epoc.ini file. + + //SwitchConfiguration(savedConfiguration); + } + + //restore each window to saved state + for(TInt screen=0;screeniScreens.Count();screen++) + { + + // If the .ini file was opened, get the saved settings for the windows position the last time + // this emulator was run, if any, and move the window accordingly. + + TWindowState savedState; + + TBool stateLoaded = ReadFile(hSysIni, &savedState, sizeof(TWindowState), &numRead, 0) && (numRead>0); + + if (stateLoaded) + { + //only allow window to be restored to + //maximized or normal mode, + //this prevents it being restored in minimized mode + //or others. + if(savedState.iWinPlace.showCmd != SW_MAXIMIZE) + savedState.iWinPlace.showCmd= SW_NORMAL; + + //if starting in same configuration and/or rotation as last time emulator was run + //it makes sense to restore scroll offset, window position, + //and dimensions, if not, only restore position and window (ie. maximized/normal) state. + if(savedConfiguration == CurrentConfiguration && + savedState.iFlipstate == CurrentFlipState[screen]) + { + //Restore window placement + SetWindowPlacement(TheWin[screen], &savedState.iWinPlace); + + TViewport& viewport = systemIni->iScreens[screen]->iViewport; + + viewport.ScrollToX(savedState.iXoffset, TheWin[screen]); + viewport.ScrollToY(savedState.iYoffset, TheWin[screen]); + } + else + { + + RECT oldRect; + GetWindowRect(TheWin[screen], &oldRect); + //save default window dimensions + TInt width=oldRect.right-oldRect.left; + TInt height=oldRect.bottom - oldRect.top; + + //restore position and window state from file + SetWindowPlacement(TheWin[screen], &savedState.iWinPlace); + + RECT currentRect; + GetWindowRect(TheWin[screen], ¤tRect); + //keep default size. + MoveWindow(TheWin[screen],currentRect.left, currentRect.top, width, height, TRUE); + + } + + + // Check that enough of the recorded window position is visible on the screen + + TBool enoughVisible = false; + + // vague values for ensuring we have enough of the window title bar to grab + // if the window is partly off screen + const TInt KTitleBarGrabX=80; + const TInt KTitleBarGrabY=50; + + //inspect dimensions of the window to be restored. + RECT savedRect; + GetWindowRect(TheWin[screen], &savedRect); + + SystemMonitors monitors; + + if (monitors.Count() == 1) /* Original algorithm */ + { + RECT rcIntersect, rcScreen; + + SetRect(&rcScreen, KTitleBarGrabX, savedRect.bottom-savedRect.top, + GetSystemMetrics(SM_CXSCREEN)-KTitleBarGrabX, GetSystemMetrics(SM_CYSCREEN)-KTitleBarGrabY); + + enoughVisible = IntersectRect(&rcIntersect, &savedRect, &rcScreen); + } + else /* > 1 monitor; do it differently */ + { + RECT cornerBox1, cornerBox2; + + // The top-left corner box + SetRect(&cornerBox1, savedRect.left, savedRect.top, + savedRect.left + KTitleBarGrabX, savedRect.top + KTitleBarGrabY); + + // The top-right corner box + SetRect(&cornerBox2, savedRect.right - KTitleBarGrabX, savedRect.top, + savedRect.right, savedRect.top + KTitleBarGrabY); + + // Require one of these rectangles to be all on one monitor + enoughVisible = monitors.RectAllOnOne(cornerBox1) || monitors.RectAllOnOne(cornerBox2); + } + + if (!enoughVisible) + { + SetWindowPos(TheWin[screen], HWND_TOP, 0,0,0,0, SWP_NOSIZE); + } + + } + else //if there was no stored info for this screen + { + ShowWindow(TheWin[screen],SW_MAXIMIZE); + } + } + } + else + { + //use default configuration and make windows visible + SwitchConfiguration(CurrentConfiguration); + for(TInt screen=0;screeniScreens.Count();screen++) + { + ShowWindow(TheWin[screen],SW_MAXIMIZE); + UpdateWindow(TheWin[screen]); + } + } + + //close file if it was opened + if(success) + { + CloseHandle(hSysIni); + } + + + if (systemIni->iInitialFlipMsg != 0) + { + addKeyEvent(TRawEvent::EKeyDown,systemIni->iInitialFlipMsg); + addKeyEvent(TRawEvent::EKeyUp,systemIni->iInitialFlipMsg); + } + + SetFocus(TheWin[0]); + + MSG m; + while (GetMessageA(&m,NULL,0,0)) + { + DispatchMessageA(&m); + } + + ExitProcess(m.wParam); + return 0; + } + +SystemMonitors::SystemMonitors(void) + { + TInt n; + + iCount = 1; + iHaveMultiMonFunctions = false; + + if ((n = GetSystemMetrics(SM_CMONITORS)) <= 1) + { + return; + } + + HMODULE huser32 = GetModuleHandleA("user32.dll"); + + // Get pointers to the APIs we want + if (huser32 == NULL || + (ipMonitorFromRect = + (HMONITOR (WINAPI *)(LPCRECT lprcScreenCoords, UINT uFlags)) + GetProcAddress(huser32, "MonitorFromRect")) == NULL || + (ipGetMonitorInfo = + (BOOL (WINAPI *)(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)) + GetProcAddress(huser32, "GetMonitorInfoA")) == NULL) + { + return; + } + + iCount = n; + iHaveMultiMonFunctions = true; + } + +TBool SystemMonitors::RectAllOnOne(RECT& rect) + { + HMONITOR monitor = MonitorFromRect(rect); + if (monitor == NULL) + { + return false; + } + + MONITORINFO monInfo; + monInfo.cbSize = sizeof(MONITORINFO); + + if (! GetMonitorInfo(monitor, &monInfo)) + { + return false; + } + + RECT overlap; + + if (IntersectRect(&overlap, &rect, &monInfo.rcWork) && + EqualRect(&overlap, &rect)) + { + return true; + } + + return false; + } + +HMONITOR SystemMonitors::MonitorFromRect(const RECT& rect, UINT flags) + { + if (! iHaveMultiMonFunctions) + { + return NULL; + } + + return (*ipMonitorFromRect)(&rect, flags); + } + +TBool SystemMonitors::GetMonitorInfo(HMONITOR monitor, LPMONITORINFO pMonInfo) + { + if (! iHaveMultiMonFunctions) + { + return false; + } + + return (*ipGetMonitorInfo)(monitor, pMonInfo); + } + +void DrawLeds() + { + HDC winDC = GetDC(TheWin[0]); + HDC hdcBits; + hdcBits=CreateCompatibleDC(winDC); + SelectObject(hdcBits,TheScreenBitmap[0]); + HPEN pen=CreatePen(PS_SOLID,0,RGB(0,0,0)); + SelectObject(hdcBits,pen); + HBRUSH brush; + LOGBRUSH redbrush={BS_SOLID, RGB(0xff,0,0)}; + LOGBRUSH greenbrush={BS_SOLID, RGB(0,0xff,0)}; + LOGBRUSH blackbrush={BS_SOLID, RGB(0,0,0)}; + // red + if (LedMask & KLedMaskRed1) + brush=CreateBrushIndirect(&redbrush); + else + brush=CreateBrushIndirect(&blackbrush); + SelectObject(hdcBits,brush); + DWinsUi *ini=systemIni; + Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY, ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize); + DeleteObject(brush); + // green + if (LedMask & KLedMaskGreen1) + brush=CreateBrushIndirect(&greenbrush); + else + brush=CreateBrushIndirect(&blackbrush); + SelectObject(hdcBits,brush); + if (ini->iLedVertical) + Ellipse(hdcBits, ini->iLedOffsetX, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap, + ini->iLedOffsetX+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize); + else + Ellipse(hdcBits, ini->iLedOffsetX+ini->iLedSize+ini->iLedGap, ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize, ini->iLedOffsetY+ini->iLedSize); + DeleteObject(brush); + DeleteObject(pen); + DeleteDC(hdcBits); + ReleaseDC(TheWin[0], winDC); + if (ini->iLedVertical) + { + RECT r={ini->iLedOffsetX, + ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize, + ini->iLedOffsetY+ini->iLedSize+ini->iLedGap+ini->iLedSize}; + InvalidateRect(TheWin[0], &r, FALSE); + } + else + { + RECT r={ini->iLedOffsetX, + ini->iLedOffsetY, + ini->iLedOffsetX+ini->iLedSize+ini->iLedGap+ini->iLedSize, + ini->iLedOffsetY+ini->iLedSize}; + InvalidateRect(TheWin[0], &r, FALSE); + } + } + +void DWinsUi::ScreenInfo(TScreenInfoV01& aInfo) +// +// Return screen 0 info to the window server. +// + { + aInfo.iWindowHandleValid=ETrue; + aInfo.iWindowHandle=TheChildWin[0]; + aInfo.iScreenAddressValid=EFalse; + aInfo.iScreenAddress=NULL; + aInfo.iScreenSize.iWidth = iScreens[0]->iMaxScreenWidth; + aInfo.iScreenSize.iHeight = iScreens[0]->iMaxScreenHeight; + } + + +TBool DWinsUi::VideoInfo(TInt aScreenNumber, TVideoInfoV01& aInfo) + { + return VideoInfo(aScreenNumber,iScreens[aScreenNumber&KMaskScreenNum]->iCurrentMode,aInfo); + } + +/// Could fail if flip mode is not supported +TBool DWinsUi::VideoInfo(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo) + { + aScreenNumber &= KMaskScreenNum; + if (aScreenNumber>=iScreens.Count()) + return EFalse; + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aScreenNumber].iDisplayDriverCount > 0) + { + return VideoInfoForDisplayDriver(aScreenNumber,aModeNumber,aInfo); + } + else + { + if ((aModeNumber&KMaskModeNum)>=1) + return EFalse; //non-gce emulator doesn't support changing the mode number. + DScreenProperties* screenProperties=iScreens[aScreenNumber]; + aInfo.iSizeInPixels.iWidth = screenProperties->iMaxScreenWidth; + aInfo.iSizeInPixels.iHeight = screenProperties->iMaxScreenHeight; + aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ? screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + aInfo.iIsMono = EFalse; + aInfo.iIsPalettized = EFalse; + aInfo.iDisplayMode=screenProperties->iCurrentMode; + aInfo.iIsPixelOrderRGB = ETrue; + aInfo.iIsPixelOrderLandscape=ETrue; + + aInfo.iVideoAddress = (TInt)TheChildWin[aScreenNumber]; + aInfo.iBitsPerPixel = screenProperties->iColorDepth; + aInfo.iOffsetToFirstPixel=0; + aInfo.iOffsetBetweenLines=0; + } + return ETrue; + } + +/** Could fail if flip mode is not supported. + Note that this method is inteneded to be called directly to parameterise the setting up of the display driver, + so it must survive absense of the display driver installation! +**/ + +TBool DWinsUi::VideoInfoForDisplayDriver(TInt aScreenNumber,TInt aModeNumber, TVideoInfoV01& aInfo, TBool aRealWidthAndHeight) + { + aScreenNumber &= KMaskScreenNum; + DScreenProperties* screenProperties = iScreens[aScreenNumber]; + if ((aModeNumber&KMaskModeNum) >= screenProperties->iMaxModes) + { + return EFalse; + } + + aInfo.iSizeInPixels.iWidth = aRealWidthAndHeight ? screenProperties->iScreenWidth : screenProperties->iMaxScreenWidth; + aInfo.iSizeInPixels.iHeight = aRealWidthAndHeight ? screenProperties->iScreenHeight : screenProperties->iMaxScreenHeight; + + if (aRealWidthAndHeight==EFalse) + { + aInfo.iSizeInTwips.iWidth = screenProperties->iMaxPhysicalScreenWidth ? screenProperties->iMaxPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iMaxPhysicalScreenHeight ? screenProperties->iMaxPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + } + else + { + aInfo.iSizeInTwips.iWidth = screenProperties->iPhysicalScreenWidth ? screenProperties->iPhysicalScreenWidth : TInt(screenProperties->iScreenWidth*KDefaultPixelsToTwipsX); + aInfo.iSizeInTwips.iHeight = screenProperties->iPhysicalScreenHeight ? screenProperties->iPhysicalScreenHeight : TInt(screenProperties->iScreenHeight*KDefaultPixelsToTwipsY); + } + + aInfo.iIsMono = EFalse; + aInfo.iIsPalettized = EFalse; + aInfo.iDisplayMode=screenProperties->iCurrentMode; + aInfo.iIsPixelOrderRGB = ETrue; + aInfo.iIsPixelOrderLandscape=ETrue; + + // Set memory to iVideoAddress to NULL to trigger the HAL code into querying the video address + // separately + aInfo.iVideoAddress = NULL; + + TInt bpp=screenProperties->iModeDepths[aModeNumber&KMaskModeNum]; + aInfo.iBitsPerPixel=bpp; + if (bpp>8) + { + bpp=(bpp+15)&-16; //12 & 16 --> 16 ; 24 & 32 --> 32 + } + + aInfo.iOffsetToFirstPixel=0; +#ifdef TEST_GCE_VARIABLE_START_EXTRA + aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*(1+aModeNumber&KMaskScreenModeNum); + if ((aModeNumber& KModeFlagFlipped) + { +#ifndef ASSYMETRIC_SQUARE_STRIDE + if (aInfo.iSizeInPixels.iWidth!=aInfo.iSizeInPixels.iHeight) +#endif + aInfo.iOffsetToFirstPixel+= TEST_GCE_VARIABLE_START_EXTRA*KEmulMaxNumModes; + } +#endif + if (aModeNumber& KModeFlagFlipped) + { + // we calculate the number of bytes per scanline that MUST be a multiple of 32 bits word (alignment) + // screenProperties->iMaxScreenHeight * bpp represnts the number of bits per scanline + // +31 is the ceiling + // we shift right (>>3) because there are 8 bits/byte + // we mask with ~3 because we are intrested in the octet value + aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenHeight * bpp + 31) >> 3) & ~3; + } + else + { + // please see the comment above + aInfo.iOffsetBetweenLines=((screenProperties->iMaxScreenWidth * bpp + 31) >> 3) & ~3; + } +#ifdef TEST_GCE_VARIABLE_STRIDE_EXTRA + aInfo.iOffsetBetweenLines+=TEST_GCE_VARIABLE_STRIDE_EXTRA; +#endif + + return ETrue; + } + +TInt DMasterIni::DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2) + { + return masterIni->HalFunction((TInt)aPtr,aFunction,a1,a2); + } + + +TInt DMasterIni::HalFunction(TInt aDeviceNumber, TInt aFunction, TAny* a1, TAny* a2) + { + if (TUint(aDeviceNumber) >= TUint(systemIni->iScreens.Count())) + return KErrArgument; + + TInt mode; + TInt maxMode=1; + TInt r=KErrNone; + switch(aFunction) + { + case EDisplayHalScreenInfo: + { + TPckgBuf vPckg; + systemIni->ScreenInfo(vPckg()); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + break; + } + case EDisplayHalWsRegisterSwitchOnScreenHandling: + WsSwitchOnScreen=(TBool)a1; + break; + case EDisplayHalSetState: + { + if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState"))) + return KErrPermissionDenied; + if ((TBool)a1) + WinsGuiPowerHandler->ScreenOn(aDeviceNumber); + else + WinsGuiPowerHandler->ScreenOff(aDeviceNumber); + } + break; + + case EDisplayHalState: + *(TInt*)a1=!systemIni->iScreens[aDeviceNumber]->iScreenOff; + break; + case EDisplayHalWsSwitchOnScreen: + WinsGuiPowerHandler->ScreenOn(); + break; + case EDisplayHalMaxDisplayContrast: + kumemput32(a1,&KMaxDisplayContrast,sizeof(KMaxDisplayContrast)); + break; + case EDisplayHalDisplayContrast: + kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iDisplayContrast,sizeof(systemIni->iScreens[aDeviceNumber]->iDisplayContrast)); + break; + case EDisplayHalSetDisplayContrast: + if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayContrast"))) + return KErrPermissionDenied; + if (TUint(a1) <= TUint(KMaxDisplayContrast)) + systemIni->iScreens[aDeviceNumber]->iDisplayContrast = TInt(a1); + else + r = KErrArgument; + break; + case EDisplayHalBacklightOn: + { + TBool c = EFalse; + kumemput32(a1,&c,sizeof(TBool)); + } + break; + + case EDisplayHalCurrentModeInfo: + { + //a1 has ptr to buffer for results + TPckgBuf vPckg; + if (systemIni->VideoInfo(aDeviceNumber, vPckg())) + Kern::InfoCopy(*(TDes8*)a1,vPckg); + else + r=KErrNotSupported; + } + break; + + case EDisplayHalSpecifiedModeInfo: + { + kumemget32(&mode, a1, sizeof(mode)); + TPckgBuf vPckg; + if (!systemIni->VideoInfo(aDeviceNumber, mode, vPckg())) + return KErrArgument; + Kern::InfoCopy(*(TDes8*)a2, vPckg); + } + break; + + case EDisplayHalSetMode: +// if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode"))) +// return KErrPermissionDenied; + + //Note that at present the HAL mode does not apparently get set when the CFbsScreenDevice requires a different mode. + //At least in the emulator and default h4 implementation... + + mode=KMaskModeNum&(TInt) a1; + maxMode=1; + //can't avoid this behaviour change test against gce loaded + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0) + maxMode=systemIni->iScreens[aDeviceNumber]->iMaxModes; + if (mode >=maxMode || mode<0) + { + r = KErrArgument; + break; + } + //Harmless/Pointless in vanilla wins mode. + systemIni->iScreens[aDeviceNumber]->iCurrentMode=mode; + + break; + + case EDisplayHalMode: + { + //This is always 0 in non-gce emulator + kumemput32(a1,&systemIni->iScreens[aDeviceNumber]->iCurrentMode,sizeof(systemIni->iScreens[aDeviceNumber]->iCurrentMode)); + } + break; + + case EDisplayHalModeCount: + { + //Need to actually count them here! + //GCE will ignore modes<=8 + TInt encodedMode=1; + if (masterIni->iBufferSet.Count() && masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount > 0) + encodedMode=systemIni->iScreens[aDeviceNumber]->iMaxModes; + kumemput32(a1,&encodedMode,sizeof(encodedMode)); + } + break; + + case EDisplayHalColors: + { + TInt deepestMode=0; + if (masterIni->iBufferSet.Count()==0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0) + { + deepestMode = KMaxDisplayColors; //I could try and work it out, but this is what used to happen! + } + else + { + TInt maxBpp=0; + for (TInt i=0,maxI=systemIni->iScreens[aDeviceNumber]->iMaxModes;iiScreens[aDeviceNumber]->iModeDepths[i]>maxBpp) + maxBpp=systemIni->iScreens[aDeviceNumber]->iModeDepths[i]; + deepestMode= 1<iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 )) + { + r = masterIni->DisplayMemoryHandle(aDeviceNumber, val); + } + else + { + r = KErrArgument; + } + NKern::ThreadLeaveCS(); + } + kumemput32(a1, &val, sizeof(TInt)); + + } + break; + + case EDisplayHalGetDisplayMemoryAddress: + { + TInt val = 0; + TInt passedIn = 0; + kumemget32(&passedIn, a1, sizeof(TInt)); + if (passedIn != -1) //not from a getall + { + if (!(masterIni->iBufferSet.Count() == 0 || masterIni->iBufferSet[aDeviceNumber].iDisplayDriverCount <= 0 )) + { + r = masterIni->DisplayMemoryAddress(aDeviceNumber, val); + } + else + { + r = KErrArgument; + } + } + kumemput32(a1, &val, sizeof(TInt)); + } + break; + + case EDisplayHalNumberOfResolutions: + { + r = NumberOfResolutions(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalSpecificScreenInfo: + { + r = SpecificScreenInfo(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalCurrentScreenInfo: + { + r = CurrentScreenInfo(aDeviceNumber, a1, a2); + } + break; + case EDisplayHalSetDisplayState: + { + //increase the spinner at both beginning and end of resetting the display state + NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount); + kumemget32(&iBufferSet[aDeviceNumber].iDisplayState, a1, sizeof(TInt)); + + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: + case EDisconnect: + case ESingleResolution: + // the fascia effect of 0x0 resolution + SetDisplaySize(aDeviceNumber, 0, 0); + break; + } + + NKern::LockedInc(iBufferSet[aDeviceNumber].iStateChangeCount); + } + break; + case EDisplayHalGetStateSpinner: + { + kumemput32(a1,&iBufferSet[aDeviceNumber].iStateChangeCount, + sizeof(iBufferSet[aDeviceNumber].iStateChangeCount)); + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::NumberOfResolutions(TInt aDeviceNumber, TAny* a1, TAny* a2) + { + TInt numberOfConfigs; + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: + { + numberOfConfigs = 0; + } + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: + { + numberOfConfigs = 1; + } + break; + case ENormalResolution: + default: + { + numberOfConfigs = iSystemInis.Count(); + if (numberOfConfigs > 1) + { + TVideoInfoV01 info1; + TVideoInfoV01 info2; + iSystemInis[0]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info1, ETrue); + iSystemInis[1]->VideoInfoForDisplayDriver(aDeviceNumber, 0, info2, ETrue); + if (info1.iSizeInPixels.iWidth == info2.iSizeInPixels.iWidth && + info1.iSizeInPixels.iHeight == info2.iSizeInPixels.iHeight) + { + numberOfConfigs = 1; //It looks like all resolutions for this device are the same + } + } + } + } + kumemput32(a1,&numberOfConfigs,sizeof(numberOfConfigs)); + if(a2) + { + kumemput32(a2,&(iBufferSet[aDeviceNumber].iStateChangeCount),sizeof(iBufferSet[aDeviceNumber].iStateChangeCount)); + } + return KErrNone; + } + +TInt DMasterIni::SpecificScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* a2) + { + TInt config; + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: //Do Nothing + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: //fill (0,0) as the only element in resolution array + { + if(*(TInt*)a1 == 0) + { + TVideoInfoV01 info; + info.iSizeInPixels.iHeight = 0; + info.iSizeInPixels.iWidth = 0; + info.iSizeInTwips.iHeight = 0; + info.iSizeInTwips.iWidth = 0; + TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info)); + Kern::InfoCopy(*(TDes8*)a2, infoPtr); + } + } + break; + case ENormalResolution: + default: + { + kumemget32(&config, a1, sizeof(config)); + TPckgBuf vPckg; + iSystemInis[config]->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue); + Kern::InfoCopy(*(TDes8*)a2,vPckg); + } + } + return KErrNone; + } + +TInt DMasterIni::CurrentScreenInfo(TInt aDeviceNumber, TAny* a1, TAny* /*a2*/) + { + switch(iBufferSet[aDeviceNumber].iDisplayState) + { + case ENoResolution: //Do Nothing + break; + case EDisconnect: + { + return KErrDisconnected; + } + break; + case ESingleResolution: //fill (0,0) + { + TVideoInfoV01 info; + info.iSizeInPixels.iHeight = 0; + info.iSizeInPixels.iWidth = 0; + info.iSizeInTwips.iHeight = 0; + info.iSizeInTwips.iWidth = 0; + TPtr8 infoPtr((TUint8*)&info, sizeof(info), sizeof(info)); + Kern::InfoCopy(*(TDes8*)a1, infoPtr); + } + break; + case ENormalResolution: + default: + { + TPckgBuf vPckg; + systemIni->VideoInfoForDisplayDriver(aDeviceNumber, 0, vPckg(), ETrue); + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + } + return KErrNone; + } + +TInt DMasterIni::DoXYHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2) + { + return static_cast(aThis)->XYHalFunction(aFunction,a1,a2); + } + +TInt DMasterIni::XYHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/) + { + TInt r=KErrNone; + switch(aFunction) + { + case EDigitiserHalXYInfo: + { + if(systemIni->iXYInputType==EXYInputPointer) + { + TPckgBuf vPckg; + TDigitiserInfoV01& xyinfo=vPckg(); + xyinfo.iDigitiserSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX); + xyinfo.iDigitiserSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY); + xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX; + xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY; + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + else + r=KErrNotSupported; + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::DoMouseHalFunction(TAny* aThis, TInt aFunction, TAny* a1, TAny* a2) + { + return static_cast(aThis)->MouseHalFunction(aFunction,a1,a2); + } + +TInt DMasterIni::MouseHalFunction(TInt aFunction, TAny* a1, TAny* /*a2*/) + { + TInt r=KErrNone; + switch(aFunction) + { + case EMouseHalMouseInfo: + { + if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse) + { + TPckgBuf vPckg; + TMouseInfoV01& xyinfo=vPckg(); + xyinfo.iMouseButtons=2; + xyinfo.iMouseAreaSize.iWidth=max(systemIni->iScreens[0]->iXYInputWidth,systemIni->iScreens[0]->iMaxScreenWidth+systemIni->iScreens[0]->iScreenOffsetX); + xyinfo.iMouseAreaSize.iHeight=max(systemIni->iScreens[0]->iXYInputHeight,systemIni->iScreens[0]->iMaxScreenHeight+systemIni->iScreens[0]->iScreenOffsetY); + xyinfo.iOffsetToDisplay.iX=systemIni->iScreens[0]->iScreenOffsetX; + xyinfo.iOffsetToDisplay.iY=systemIni->iScreens[0]->iScreenOffsetY; + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + else + r=KErrNotSupported; + } + break; + default: + r=KErrNotSupported; + break; + } + return r; + } + +TInt DMasterIni::DoKbdHalFunction(TAny* /*aThis*/, TInt aFunction, TAny* /*a1*/, TAny* /*a2*/) + { + // don't actually do anything, just enough to report a Keyboard is present + TInt r=KErrNone; + if(aFunction!=EKeyboardHalKeyboardInfo) + r=KErrNotSupported; + return r; + } + +void Inactive() +// +// Window has been minimised. +// + { + + TRawEvent v; + v.Set(TRawEvent::EInactive); + TheEventQ.Add(v); + } + +void UpdateModifiers() +//Updates the modifier key states and sends an event to wserv about the +//change in state + { + TRawEvent v; + TInt modifiers=0; + if(GetKeyState(VK_SCROLL)&1) + modifiers|=EModifierScrollLock; + if(GetKeyState(VK_NUMLOCK)&1) + modifiers|=EModifierNumLock; + if(GetKeyState(VK_CAPITAL)&1) + modifiers|=EModifierCapsLock; + v.Set(TRawEvent::EUpdateModifiers,modifiers); + TheEventQ.Add(v); + } + +void Active() +// +// Window has been restored. +// Update the toggling modifiers, reset any others +// + { + TRawEvent v; + UpdateModifiers(); + v.Set(TRawEvent::EActive); + TheEventQ.Add(v); + } + + +void ClearScreen() + { + + } + + +TInt DWinsUi::GetVirtualKey(TEmulCommand& aCommand, TInt aX, TInt aY) + { + //if the point is in the list of shapes, set the key and return true + for (TInt keyCount = iVirtualKeys.Count(); --keyCount >= 0; ) + { + const VirtualKey& vk = *iVirtualKeys[keyCount]; + if (vk.Contains(aX, aY)) + { + aCommand = vk.Command(); + return vk.Value(); + } + } + return -1; + } + +void DWinsUi::TranslateMouseCoords(const TEmulatorFlip aFlipState, const TInt aX, const TInt aY, const TInt aRegionWidth, const TInt aRegionHeight, TInt& aNewX, TInt& aNewY) + { + switch (aFlipState) + { + case EEmulatorFlipRestore: + aNewX = aX; + aNewY = aY; + break; + + case EEmulatorFlipInvert: + aNewX = aRegionWidth - aX; + aNewY = aRegionHeight - aY; + break; + + case EEmulatorFlipLeft: + aNewX = aRegionWidth - aY; + aNewY = aX; + break; + + case EEmulatorFlipRight: + aNewX = aY; + aNewY = aRegionHeight - aX; + break; + } + } + + +TBool DWinsUi::OnScreen(TInt aScreen, TInt ax, TInt ay) const +// +// Checks if a point within the Emulator window is on the screen +// + { + return (TUint(ax) < TUint(systemIni->iScreens[aScreen]->iScreenWidth) && TUint(ay) < TUint(systemIni->iScreens[aScreen]->iScreenHeight)); + } + +TInt DWinsUi::Create(TInt aId) + { + TInt r = SetupProperties(aId); + if (r != KErrNone) + return r; + TInt screen; + DScreenProperties* currentScreen = NULL; + for(screen=0;screeniFasciaFileName) == KErrNone) + { + currentScreen->iXYInputWidth=bitmapinfo.biWidth; + currentScreen->iXYInputHeight=bitmapinfo.biHeight; + } + currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,currentScreen->iScreenWidth+currentScreen->iScreenOffsetX); + currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,currentScreen->iScreenHeight+currentScreen->iScreenOffsetY); + } + + currentScreen = iScreens[0]; + //note digitizer offsets are relative to EPOC screen 0 + if (-1 == iDigitizerWidth) + iDigitizerWidth = currentScreen->iXYInputWidth - + (currentScreen->iScreenOffsetX + iDigitizerOffsetX); + else + currentScreen->iXYInputWidth=max(currentScreen->iXYInputWidth,iDigitizerWidth); + + if (-1 == iDigitizerHeight) + iDigitizerHeight = currentScreen->iXYInputHeight - + (currentScreen->iScreenOffsetY + iDigitizerOffsetY); + else + currentScreen->iXYInputHeight=max(currentScreen->iXYInputHeight,iDigitizerHeight); + + return r; + } + +const RDisplayChannel::TPixelFormat DMasterIni::iSupportedPixelFormatTable[] = + { + EUidPixelFormatXRGB_8888, + EUidPixelFormatARGB_8888, + EUidPixelFormatARGB_8888_PRE, + EUidPixelFormatXRGB_4444, + EUidPixelFormatARGB_4444, + EUidPixelFormatRGB_565 + }; + +const TInt DMasterIni::iSupportedPixelFormatTableSize = static_cast(sizeof(iSupportedPixelFormatTable)/ + sizeof(iSupportedPixelFormatTable[0])); + +void DMasterIni::InitBufferFormat(DScreenProperties& aScreenProperties, RDisplayChannel::TBufferFormat& aBufferFormat) + { + TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth); + + aBufferFormat.iSize.iWidth = aScreenProperties.iMaxScreenWidth; + aBufferFormat.iSize.iHeight = aScreenProperties.iMaxScreenHeight; + switch (bitsPerPixel) + { + case 12: // XRGB4444 + aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_4444; + break; + case 16: // RGB565 + aBufferFormat.iPixelFormat = EUidPixelFormatRGB_565; + break; + case 24: // Really 32bpp, but top 8 unused + case 32: // While 32bpp, top 8 will not be used + default: + aBufferFormat.iPixelFormat = EUidPixelFormatXRGB_8888; + break; + } + } + +TInt DMasterIni::Create() + { + TInt configurations = Property::GetInt("ConfigCount", 0); + if (configurations == 0) + return KErrGeneral; + + // the pixel formats table is, at present, configuration independent + TInt count; + TInt r = KErrNone; + for (count = 0; count < configurations && r == KErrNone; ++count) + { + DWinsUi* dwi = new DWinsUi; + if (dwi) + r = dwi->Create(count); + + if (r == KErrNone) + iSystemInis.Append(dwi); + } + if (r != KErrNone) + return r; + + systemIni = masterIni->iSystemInis[0]; + + WinsGuiPowerHandler = DWinsGuiPowerHandler::New(); + if (!WinsGuiPowerHandler) + return KErrNoMemory; + + TheWin=new HWND[systemIni->iScreens.Count()]; + TheChildWin=new HWND[systemIni->iScreens.Count()]; + TheScreenBitmap=new HBITMAP[systemIni->iScreens.Count()]; + CurrentFlipState=new TEmulatorFlip[systemIni->iScreens.Count()]; + + if(!TheWin || !TheChildWin || !TheScreenBitmap || !CurrentFlipState) + return KErrNoMemory; + memset(CurrentFlipState,EEmulatorFlipRestore,systemIni->iScreens.Count()); + + TBufferSet buffer; + buffer.iDisplayDriverCount = 0; + buffer.iDisplayState = ENormalResolution; + buffer.iDisplayBuffer = 0; + buffer.iDisplayChannel = NULL; + + + TInt i; + for(i=0;iiScreens.Count();i++) + { + DScreenProperties *pScr = systemIni->iScreens[i]; + + masterIni->InitBitmapHeader(*pScr, &buffer.iInfo); + masterIni->InitBufferFormat(*pScr, buffer.iBufferFormat); + + r = masterIni->iBufferSet.Append(buffer); + if (r != KErrNone) + return r; + } + + if (CreateWin32Thread(EThreadEvent, &KernelWindowThread, NULL, ETrue) == NULL) + return KErrGeneral; + + for(i=0;iiScreens.Count();i++) + { + r = Kern::AddHalEntry(EHalGroupDisplay,&DoHalFunction,(TAny*)i,i); + if (r != KErrNone) + return r; + } + + // should really come from Keyboard driver, but not doing it now... + r = Kern::AddHalEntry(EHalGroupKeyboard,&DoKbdHalFunction,this); + if (r != KErrNone) + return r; + + if(systemIni->iXYInputType==EXYInputPointer) + { + r = Kern::AddHalEntry(EHalGroupDigitiser,&DoXYHalFunction,this); + if (r != KErrNone) + return r; + } + else if(systemIni->iXYInputType==EXYInputMouse || systemIni->iXYInputType==EXYInputDeltaMouse) + { + r = Kern::AddHalEntry(EHalGroupMouse,&DoMouseHalFunction,this); + if (r != KErrNone) + return r; + } + + return r; + } + +void DMasterIni::InitBitmapHeader(DScreenProperties& aScreenProperties, LPBITMAPV4HEADER aInfo) + { + TInt width = aScreenProperties.iMaxScreenWidth; + TInt height = aScreenProperties.iMaxScreenHeight; + TUint bitsPerPixel = MaximumBitDepthFromMask(aScreenProperties.iColorDepth); + + memset(aInfo, 0, sizeof(BITMAPV4HEADER)); + + switch (bitsPerPixel) + { + case 12: // XRGB4444 + aInfo->bV4BitCount = 16; + aInfo->bV4V4Compression = BI_BITFIELDS; + aInfo->bV4RedMask = 0x0F00; + aInfo->bV4GreenMask = 0x00F0; + aInfo->bV4BlueMask = 0x000F; + break; + case 16: // RGB565 + aInfo->bV4BitCount = 16; + aInfo->bV4V4Compression = BI_BITFIELDS; + aInfo->bV4RedMask = 0xF800; + aInfo->bV4GreenMask = 0x07E0; + aInfo->bV4BlueMask = 0x001F; + break; + case 24: // Really 32bpp, but top 8 unused + case 32: // While 32bpp, top 8 will not be used + default: + aInfo->bV4BitCount = 32; + aInfo->bV4V4Compression = BI_RGB; + // Mask is implicit for BI_RGB compression + break; + } + + aInfo->bV4Size = sizeof(BITMAPV4HEADER); + aInfo->bV4Width = width; + aInfo->bV4Height = -height; // Bitmap runs top to bottom + aInfo->bV4Planes = 1; + + TInt bpp = _ALIGN_UP(aInfo->bV4BitCount, 16); //12 & 16 --> 16 ; 24 & 32 --> 32 + TInt widthInPixel = aInfo->bV4Width * bpp; + //rounding to 32 bits (4 octets) and converting, then, bits to octets; + TInt scanLineInBytes = _ALIGN_UP(widthInPixel, 32) >> 3; + aInfo->bV4SizeImage = -aInfo->bV4Height * scanLineInBytes; + + // Set color space as uncalibrated. All other members are then ignored. +#if defined(LCS_DEVICE_RGB) + aInfo->bV4CSType = LCS_DEVICE_RGB; +#elif defined(LCS_sRGB) + aInfo->bV4CSType = LCS_sRGB; +#endif + } + +// Helper function that allocates a single frame buffer. +static TInt AllocateOneFrameBuffer(TInt aSize, TScreenBuffer &aScreenBuffer) + { + // Open shared chunk to the composition framebuffer + DChunk* chunk = 0; + // round to page size + if (aSize <= 0) + return KErrArgument; + TUint round = Kern::RoundToPageSize(aSize); + TLinAddr chunkKernelAddr = 0; + TUint32 physicalAddress = 0; + TUint32 chunkMapAttr = 0; + + // create shared chunk + NKern::ThreadEnterCS(); + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = round; + info.iMapAttr = 0; + info.iOwnsMemory = ETrue; + info.iDestroyedDfc = 0; + + TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); + if (r == KErrNone) + { + // map our chunk to specific + r = Kern::ChunkCommitContiguous(chunk, 0, aSize, physicalAddress); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + } + } + + if (r == KErrNone) + { + TBufferAddressA* bufferAddress = new TBufferAddressA; + if (!bufferAddress) + { + r = KErrNoMemory; + } + else + { + bufferAddress->iAddress = (TAny*)chunkKernelAddr; + bufferAddress->iChunk = chunk; + + if ((r = aScreenBuffer.iFrameBuffers.Append(bufferAddress->iAddress)) == KErrNone) + { + r = aScreenBuffer.iMemChunks.Append(bufferAddress); + } + } + } + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + } + NKern::ThreadLeaveCS(); + return KErrNone; + } + +TInt DMasterIni::AllocateFrameBuffers(TInt aScreenNumber, TInt aCount, TInt aSize) + { + while (aCount--) + { + TInt r = AllocateOneFrameBuffer(aSize, masterIni->iBufferSet[aScreenNumber].iScreenBuffer); + if (r != KErrNone) + { + return r; + } + } + return KErrNone; + } + +void DMasterIni::ReleaseFrameBuffers(TInt aScreenNumber) + { + RPointerArray& frameBuffers = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iFrameBuffers; + RPointerArray& memChunks = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iMemChunks; + RPointerArray& dsaChunks = masterIni->iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks; + + NKern::ThreadEnterCS(); + TInt index; + TInt count = memChunks.Count(); + for (index = 0; index < count; index++) + { + Kern::ChunkClose(memChunks[index]->iChunk); + } + count = dsaChunks.Count(); + for (index = 0; index < count; index++) + { + Kern::ChunkClose(dsaChunks[index]->iChunk); + } + NKern::ThreadLeaveCS(); + + frameBuffers.Reset(); + memChunks.Reset(); + dsaChunks.Reset(); + } + + +TProcessAddrEntry::TProcessAddrEntry(DProcess *aProcess, TUint8* aAddress): + iProcess(aProcess), iAddress(aAddress) + { + } + + +/** +Contruct a Shared Chunk cleanup object which will be used to clean up +after the process/address table entry. +*/ +TChunkCleanup::TChunkCleanup(DProcess* aProcess, TInt aScreenNumber) + : TDfc((TDfcFn)TChunkCleanup::ChunkDestroyed,this,Kern::SvMsgQue(),0) + , iProcess(aProcess) + , iScreenNumber(aScreenNumber) + , iIndex(-1) + {} + +/** +Cancel the action of the cleanup object. +*/ +void TChunkCleanup::Cancel() + { + // Clear iProcess which means that when the DFC gets queued on chunk destruction + // our ChunkDestroyed method will do nothing other than cleanup itself. + iProcess = NULL; + } + +/** +Callback function called when the DFC runs, i.e. when a chunk is destroyed. +*/ +void TChunkCleanup::ChunkDestroyed(TChunkCleanup* aSelf) + { + DProcess* process = aSelf->iProcess; + TInt screenNumber = aSelf->iScreenNumber; + TUint index = aSelf->iIndex; + // If we haven't been Cancelled... + if(process && index != -1) + { + if (masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess == process) + { + masterIni->iBufferSet[screenNumber].iProcAddrTable[index].iProcess = 0; + } + else + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Oops! Someone has messed up our process index!")); + } + } + + // We've finished so now delete ourself + delete aSelf; + } + + +TInt DMasterIni::DisplayMemoryHandle(TInt aScreenNumber, TInt& aHandle) + { + if (iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks.Count() == 0) + { + int r; + r = AllocateOneFrameBuffer(iMaxSizeInBytes, iBufferSet[aScreenNumber].iDsaBuffer); + if (KErrNone != r) + { + return r; + } + __ASSERT_DEBUG(iBufferSet[aScreenNumber].iDisplayChannel, Fault(EGuiNoDisplayChannel)); + iBufferSet[aScreenNumber].iDisplayChannel->SetLegacyBuffer(iBufferSet[aScreenNumber].iDsaBuffer.iFrameBuffers[0]); + } + + aHandle = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), + iBufferSet[aScreenNumber].iDsaBuffer.iMemChunks[0]->iChunk); + + if (aHandle < 0) + { + return aHandle; + } + + return KErrNone; + } + + + +// Find the address of the display memory. +TInt DMasterIni::DisplayMemoryAddress(TInt aScreenNumber, TInt& aAddress) + { + TBufferSet &bufferSet = iBufferSet[aScreenNumber]; + DProcess *process = &Kern::CurrentProcess(); + TInt firstFree = -1; + NKern::FMWait(&iLock); + TUint count = bufferSet.iProcAddrTable.Count(); + for(TUint i = 0; i < count; ++i) + { + DProcess *curProcess = bufferSet.iProcAddrTable[i].iProcess; + if (curProcess == process) + { + aAddress = reinterpret_cast(bufferSet.iProcAddrTable[i].iAddress); + NKern::FMSignal(&iLock); + return KErrNone; + } + if (curProcess == 0 && firstFree == -1) + { + firstFree = i; + } + } + NKern::FMSignal(&iLock); + // If we get here, we couldn't find the process in the iProcAddrTable. + // Create a new Process Address entry. + // Step 1 + // Create a dummy chunk so that we can detect when the process dies, + // give a handle to the user [but don't actually let the process KNOW what the handle is + // so the user process can't do anything silly with the chunk]. Close our side of the + // chunk to make sure there is only one reference to it. + DChunk* chunk = 0; + // find page size for one page. + TUint round = Kern::RoundToPageSize(1); + TLinAddr chunkKernelAddr = 0; + TUint32 chunkMapAttr = 0; + + // create shared chunk + NKern::ThreadEnterCS(); + // Cleanup object, used to issue a DFC when the chunk is closed (and + // as the handle of the chunk is not given to the process, it can only + // be closed when the process terminates!) + TChunkCleanup *cleanup = new TChunkCleanup(process, aScreenNumber); + if (!cleanup) + { + NKern::ThreadLeaveCS(); + return KErrNoMemory; + } + + TChunkCreateInfo info; + info.iType = TChunkCreateInfo::ESharedKernelMultiple; + info.iMaxSize = round; + info.iMapAttr = 0; + info.iOwnsMemory = ETrue; + info.iDestroyedDfc = cleanup; + + TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr); + + if (r != KErrNone) + { + delete cleanup; + NKern::ThreadLeaveCS(); + return r; + } + + + // Create a new handle for the user thread. + r = Kern::MakeHandleAndOpen(&Kern::CurrentThread(), chunk); + Kern::ChunkClose(chunk); + if (r <= 0) + { + NKern::ThreadLeaveCS(); + return r; + } + + // Step 2 + // Create a second handle for the chunk to the DSA buffer. + // First part: Make sure there is a DisplayMemoryHandle; + TInt handle = 0; + r = DisplayMemoryHandle(aScreenNumber, handle); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return r; + } + + DChunk *dsaChunk = bufferSet.iDsaBuffer.iMemChunks[0]->iChunk; + + // Step 3 + // Get the base addrss and insert into table. + TUint8* baseAddress = Kern::ChunkUserBase(dsaChunk, &Kern::CurrentThread()); + NKern::FMWait(&iLock); + // Optimistically, the place we found earlier in the table is still free. + if (firstFree != -1 && bufferSet.iProcAddrTable[firstFree].iProcess != 0) + { + // If not, we go find another one. + firstFree = -1; + TUint count = bufferSet.iProcAddrTable.Count(); + for(TUint i = 0; i < count; ++i) + { + if (bufferSet.iProcAddrTable[i].iProcess == 0) + { + firstFree = i; + break; + } + } + } + // Check if there is a free entry - if so, re-use it. + if (firstFree != -1) + { + bufferSet.iProcAddrTable[firstFree].iProcess = process; + bufferSet.iProcAddrTable[firstFree].iAddress = baseAddress; + cleanup->SetIndex(firstFree); + NKern::FMSignal(&iLock); + } + else + { + // No free entry. Append it to the list. + NKern::FMSignal(&iLock); + TProcessAddrEntry entry(process, baseAddress); + r = bufferSet.iProcAddrTable.Append(entry); + if (r != KErrNone) + { + Kern::ChunkClose(chunk); + NKern::ThreadLeaveCS(); + return r; + } + // We added it at the end - so we start from the back and check for the + // process, as some other process COULD have added one after us, so we + // can't just use the count for index! + TUint index; + for(index = bufferSet.iProcAddrTable.Count()-1; index; --index) + { + if (bufferSet.iProcAddrTable[index].iProcess == process + && bufferSet.iProcAddrTable[index].iAddress != baseAddress) + { + break; + } + } + cleanup->SetIndex(index); + } + aAddress = reinterpret_cast(baseAddress); + + NKern::ThreadLeaveCS(); + return KErrNone; + } + +EXPORT_C TInt WinsGui::CurrentConfiguration() + { + return ::CurrentConfiguration; + } + +GLDEF_C void Fault(TGuiPanic aPanic) + { + Kern::Fault("WINS-UI",aPanic); + } + +DECLARE_STANDARD_EXTENSION() + { + __KTRACE_OPT(KEXTENSION,Kern::Printf("Starting Emulator GUI")); + + // if NoGui property == true do nothing + if (Property::GetBool("NoGui",EFalse)) + return KErrNone; + + // create keyboard driver + TInt r=KErrNoMemory; + masterIni = new DMasterIni; + if (masterIni) + { + r = masterIni->Create(); + if (r!= KErrNone) + { + return r; + } + } + + DMultiTouch::iMultiTouchSupported = DMultiTouch::Init(); + + // Create multitouch when necessary + if (systemIni->MultiTouchEnabled() && systemIni->GCEEnabled() && DMultiTouch::iMultiTouchSupported) + { + TheMultiTouch = new DMultiTouch(systemIni->MultiTouchProximityStep(),systemIni->MultiTouchPressureStep()); + if(!TheMultiTouch) + { + r = KErrNoMemory; + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + } + DMultiTouch::iMultiTouchCreated = TRUE; + } + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Returns %d",r)); + return r; + } + +TInt DWinsUi::DoDefineEmulatorControlHotKey(TAny* aPtr, const char* aValue) + { + return static_cast(aPtr)->DefineEmulatorControlHotKey(aValue); + } + + +TInt DWinsUi::DefineEmulatorControlHotKey(const char* aValue) + { + const char* beg = skipws(aValue); + const char* end = skiptok(beg); + TInt err = KErrNone; + + TEmulCommand command = ENoCommand; + TInt data = 0; + if (_strnicmp(beg, "SelectConfig", end-beg) == 0) + { + //get the int param which is the config to switch to + beg = end; + char * e; + data = strtol(beg, &e,0); + if (beg == e) + err = KErrArgument; + end = e; + command = ESelectConfig; + } + else if(_strnicmp(beg, "NextConfig", end-beg) == 0) + { + command = ENextConfig; + } + else + { + err = KErrArgument; + } + if (err != KErrNone) + return err; + + // get the keys + KeyCombination* pCombination = new KeyCombination(data, command); + if (!pCombination) + return KErrNoMemory; + + beg = skipws(end); + const char* end2; + for (TInt i=0;iAddKey((TStdScanCode)key); + + if (beg == end2 || *end2++ != ',') + break; + beg = end2; + } + return iControlHotKeys.Append(pCombination); + }