--- /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 <emulator.h>
+#include <assp.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+#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;ix<systemIni->iScreens.Count();ix++)
+ ScreenOff(ix);
+ }
+
+void DWinsGuiPowerHandler::ScreenOn()
+ {
+ for(TInt ix=0;ix<systemIni->iScreens.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<EventQ*>(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<KMaxHotKeyCombinationLength;i++)
+ {
+ iCombination[i]=EStdKeyNull;
+ }
+}
+
+TBool KeyCombination::CheckCombinationPressed()
+{
+ for (TInt j=0;(j<KMaxHotKeyCombinationLength && iCombination[j]!=0);j++)
+ {
+ if (GetAsyncKeyState(MapVirtualKey(iCombination[j],1))>=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<KMaxHotKeyCombinationLength;i++)
+ {
+ if (iCombination[i]==EStdKeyNull)
+ break;
+ }
+ if (KMaxHotKeyCombinationLength==i)
+ return EFalse;
+ else
+ iCombination[i]=aKey;
+
+ return ETrue;
+}
+
+
+DScreenProperties::DScreenProperties()
+ {
+ memset(this,0,sizeof(DScreenProperties));
+ iColorDepth=KDefaultColorDepth;
+
+ iViewport = TViewport(this);
+ }
+
+
+LOCAL_C TInt MaskGceOnly(TInt aModeBits)
+ { //All HAL modes are now reported. The GCE may refuse to register the surfaces.
+ return aModeBits&KEmulModes; //previous useful settings: //(KEmulPixPerLong2|KEmulPixPerLong1); //|KEmulPixPerLong4;
+ }
+
+LOCAL_C TInt BitsForSingleMode(TInt aModeColor)
+ { //only 1 bit should be set in aModeColor
+ switch (aModeColor)
+ {
+ case KEmulGray2: return 1;
+ case KEmulGray4: return 2;
+ case KEmulGray16: return 4;
+ case KEmulGray256: return 8;
+ case KEmulColor16: return 4;
+ case KEmulColor256: return 8;
+ case KEmulColor4K: return 12;
+ case KEmulColor64K: return 16;
+ case KEmulColor16M: return 24;
+ default: return 32;
+ }
+
+ }
+
+DScreenProperties::~DScreenProperties()
+ {
+ }
+
+TWindowState DScreenProperties::GetWindowState()
+ {
+ TWindowState state;
+ state.iWinPlace = iWinPlace;
+ state.iFlipstate = iScreenRotation;
+ state.iXoffset = iViewport.GetViewportOffsetX();
+ state.iYoffset = iViewport.GetViewportOffsetY();
+ return state;
+ }
+
+TInt DScreenProperties::SetupProperties(TInt aConf, TInt aScreen)
+ {
+ char property[50];
+
+ // Calculate maximum dimensions
+ TInt configurations = Property::GetInt("ConfigCount", 0);
+ if (configurations == 0)
+ return KErrGeneral;
+
+ TInt count, screenWidth, screenHeight, physicalScreenWidth, physicalScreenHeight;
+ for (count = 0; count < configurations; ++count)
+ {
+ wsprintfA(property, "Configuration[%d][%d]ScreenWidth", count, aScreen);
+ screenWidth = Property::GetInt(property, KScreenWidth);
+ screenWidth = (screenWidth + 3) & ~3;
+ if (screenWidth > 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;mode<maxMode;mode++)
+ {
+ if (systemIni->VideoInfoForDisplayDriver(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<DWinsUi*>(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<DWinsUi*>(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<const TUint8>(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;i<screens;i++)
+ {
+ DeleteObject(TheScreenBitmap[i]);
+ LoadFasciaBitmap(i);
+ if (masterIni->iBufferSet[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;i<screens;i++)
+ {
+ InvalidateRect(TheWin[i], NULL, false);
+ SendMessage(TheWin[i], WM_FLIP_MESSAGE, systemIni->iScreens[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;i<systemIni->iControlHotKeys.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;i<screens;i++)
+ {
+ if(pWin[i]==aHwnd)
+ {
+ r=i;
+ break;
+ }
+ }
+ return r;
+ }
+void MultiTouchWndPointer(TUint message,TInt aXpos,TInt aYpos, TInt aZ, TInt aPointerId)
+ {
+ WINDOWINFO info;
+ info.cbSize = sizeof(WINDOWINFO);
+ if (GetWindowInfo(TheWin[0], &info))
+ {
+ POINT pt = {aXpos,aYpos};
+ if (PtInRect(&info.rcWindow,pt))
+ {
+ RECT client;
+ if (GetWindowRect(TheChildWin[0], &client) && PtInRect(&client,pt)) // within the window
+ {
+ MultiChildWndPointer(message, aXpos-client.left, aYpos-client.top, aZ, aPointerId);
+ }
+ else
+ {
+ // Disable the multitouch if the cursor is outside the application window
+ if (DMultiTouch::iMultiTouchTempEnabled) // within the window
+ {
+ DMultiTouch::iMultiTouchTempEnabled = FALSE;
+ if(TheMultiTouch->UnRegister())
+ {
+ 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;ix<systemIni->iScreens.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;i<systemIni->iScreens.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;i<systemIni->iScreens.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;ix<systemIni->iScreens.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<MINMAXINFO*>(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;screen<systemIni->iScreens.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;screen<systemIni->iScreens.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;screen<systemIni->iScreens.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<TScreenInfoV01> 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<TVideoInfoV01> vPckg;
+ if (systemIni->VideoInfo(aDeviceNumber, vPckg()))
+ Kern::InfoCopy(*(TDes8*)a1,vPckg);
+ else
+ r=KErrNotSupported;
+ }
+ break;
+
+ case EDisplayHalSpecifiedModeInfo:
+ {
+ kumemget32(&mode, a1, sizeof(mode));
+ TPckgBuf<TVideoInfoV01> 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;i<maxI;i++)
+ if (systemIni->iScreens[aDeviceNumber]->iModeDepths[i]>maxBpp)
+ maxBpp=systemIni->iScreens[aDeviceNumber]->iModeDepths[i];
+ deepestMode= 1<<maxBpp;
+ }
+
+ kumemput32(a1,&deepestMode,sizeof(deepestMode));
+ }
+ break;
+ case EDisplayHalGetDisplayMemoryHandle:
+ {
+ TInt val = 0;
+ TInt passedIn = 0;
+ kumemget32(&passedIn, a1, sizeof(TInt));
+ if (passedIn != -1) //not from a getall
+ {
+ NKern::ThreadEnterCS();
+ if (!(masterIni->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<TVideoInfoV01> 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<TVideoInfoV01> 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<DMasterIni*>(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<TDigitiserInfoV01> 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<DMasterIni*>(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<TMouseInfoV01> 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;screen<iScreens.Count();screen++)
+ {
+ BITMAPINFOHEADER bitmapinfo;
+ currentScreen = iScreens[screen];
+ if (readBitmapInfo(&bitmapinfo, currentScreen->iFasciaFileName) == 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<TInt>(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;i<systemIni->iScreens.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;i<systemIni->iScreens.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<TAny>& frameBuffers = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iFrameBuffers;
+ RPointerArray<TBufferAddressA>& memChunks = masterIni->iBufferSet[aScreenNumber].iScreenBuffer.iMemChunks;
+ RPointerArray<TBufferAddressA>& 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<TInt>(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<TInt>(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<DWinsUi*>(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;i<KMaxHotKeyCombinationLength;i++)
+ {
+ TInt key=KErrNotFound;
+ end2 = skiptok(beg);
+ TPtrC8 name((const TUint8*)beg, end2-beg);
+ if ((key=iKeyboard.GetScanCode(name))!=KErrNotFound)
+ pCombination->AddKey((TStdScanCode)key);
+
+ if (beg == end2 || *end2++ != ',')
+ break;
+ beg = end2;
+ }
+ return iControlHotKeys.Append(pCombination);
+ }