diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/plugins/openwfcrs/src/displaypolicy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/plugins/openwfcrs/src/displaypolicy.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1309 @@ +// Copyright (c) 2008-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: +// + +#include +#include +#include +#include "displaypolicy.h" +#include "panic.h" + +CDisplayPolicy::CDisplayPolicy():iLastAppMode(KErrNotReady),iSmallestAppMode(KErrNotReady) + { + // No implementation required + } + +CDisplayPolicy::~CDisplayPolicy() + { + } + +CDisplayPolicy* CDisplayPolicy::NewLC(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber) + { + CDisplayPolicy* self = new (ELeave)CDisplayPolicy(); + CleanupStack::PushL(self); + self->ConstructL(aEnv,aScreen,aScreenNumber); + return self; + } + +CDisplayPolicy* CDisplayPolicy::NewL(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber) + { + CDisplayPolicy* self=CDisplayPolicy::NewLC(aEnv,aScreen,aScreenNumber); + CleanupStack::Pop(); // self; + return self; + } + +void CDisplayPolicy::ConstructL(MWsGraphicDrawerEnvironment* aEnv,MWsScreen* aScreen,TInt aScreenNumber) + { + iScreenIniFile=aEnv->ObjectInterface(); + if (iScreenIniFile) + { + _LIT(KScale,"DP_SCALING"); + //_LIT(KScaleNone,"none"); + _LIT(KScaleInteger,"integer"); + _LIT(KScaleIsotropic,"isotropic"); + _LIT(KScaleAnisotropic,"anisotropic"); + _LIT(KScreenDisconnected,"SIMULATE_STARTUP_DISCONNECTED"); + + iUiScaling = ENone; + TPtrC scalingModeName; + if (iScreenIniFile->FindVar(aScreenNumber,KScale,scalingModeName)) + { + if (scalingModeName == KScaleInteger) + { + iUiScaling = EInteger; + } + else if (scalingModeName == KScaleIsotropic) + { + iUiScaling = EIsotropic; + } + else if (scalingModeName == KScaleAnisotropic) + { + iUiScaling = EAnisotropic; + } + } + + if (iScreenIniFile->FindVar(aScreenNumber,KScreenDisconnected)) + { + //Simulate starting up with this screen disconnected + TDisplayConnectState displayState = EDisconnect; + TInt err = UserSvr::HalFunction(EHalGroupDisplay | (aScreenNumber<<16), EDisplayHalSetDisplayState, &displayState, NULL); + STD_ASSERT_ALWAYS(err == KErrNone, EPluginPanicHalSetDisplayState); + } + } + + iScreen=aScreen; + } + +void CDisplayPolicy::NewAppModesAvailable() + { + //This notification allows the list to be first populated after Wserv has finished initialising itself + //It also allows for the WServ debug method CWsScreenDevice::SetCurrentScreenModeAttributes + GetAppModeList(); //get the app size mode list again because some settings have changed + } + +void CDisplayPolicy::GetModeInfoL(const MWsScreenConfigList& aList,TInt aIndex,TPoint& aOffset,TSize& aSize,TAppMode& aMode)const + { + aOffset=aList.OriginL(aIndex); + aSize=aList.ScreenModeSizeInPixelsL(aIndex); + aMode.iPixels=TRect(aOffset,aSize); + aMode.iTwips=aList.ScreenModeSizeInTwipsL(aIndex); + aMode.iOrientations=aList.AvailableOrientationsL(aIndex); + } + +void CDisplayPolicy::GetAppModeList() + { + if (iScreen) + { + iSmallestAppMode = KErrNotFound; + iSmallestAppSize = TSize(10000,10000); + MWsScreenConfigList* screenConfigList=iScreen->ObjectInterface(); + iNumNormalAppModes=0; + TSize largestAppMode; + if (screenConfigList) + { + RArray goodModeIndices; + if (screenConfigList->GetScreenSizeModeList(goodModeIndices)!=KErrNone) + { + //If reserve fails then list is empty later - we can't change display res from app mode request, just use current and try to centre app area + iAppModes.Reserve(goodModeIndices.Count()); + + //iScreenIniFile: First time in, it should be a good pointer from which to extract the basicFlags + //Repeat calls only update the values inside app mode list entries, and the ini file should not be read again. + //Specify some basic flags by reading ini file for this screen number? + TInt basicFlags=0; + + //Our demo policy uses the app mode list to generate a list of virtual resolutions. + + for (TInt modeIndex=0;modeIndexModeFlagsL(modeNum)); //we know modeNum is valid-wont leave + //any further flags to read from ini file for this appmode on this screen number? + + //Probably should ignore modes flagged with Hal or Dynamic + // at the moment we want all modes in the list! + + TInt err = KErrNone; + TRAP(err,GetModeInfoL(*screenConfigList,goodModeIndices[modeIndex],offset,size,mode)); + if (err == KErrNone) //should never fail - we never ask for info for a bad mode + { + if (1<largestAppMode.iWidth) + largestAppMode.iWidth=borderedSize.iWidth; + if (borderedSize.iHeight>largestAppMode.iHeight) + largestAppMode.iHeight=borderedSize.iHeight; + iNumNormalAppModes++; + } + + //find the smallest appmode. this will be used when display is disconnected + if (!(mode.iFlags&(MWsScreenConfigList::EDynamic|MWsScreenConfigList::EHalDefault))) + { + TSize borderedSize=offset.AsSize()+size; + if(borderedSize.iWidth*borderedSize.iHeight < iSmallestAppSize.iWidth*iSmallestAppSize.iHeight) + { + iSmallestAppSize = borderedSize; + iSmallestAppMode = modeNum; + } + } + } + + } + } + goodModeIndices.Close(); + } + iMinUiBufferSize=largestAppMode; + } + iScreenIniFile=NULL; + } + +TInt CDisplayPolicy::MapCompositionToUi(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const + { + // only scaling is involved in mapping from composition to UI + // no offset change + TFraction widthFraction; + TFraction heightFraction; + if ( iCompositionSizePixels.iWidth<=0 + || iUiSizePixels.iWidth<=0 + || iCompositionSizePixels.iHeight<=0 + || iUiSizePixels.iHeight<=0) + { + aTarget=aSource; + return KErrNotReady; + } + if(aIsReverseMapping) + { + //Ui to composition + widthFraction.iNumer = iCompositionSizePixels.iWidth; + widthFraction.iDenom = iUiSizePixels.iWidth; + heightFraction.iNumer = iCompositionSizePixels.iHeight; + heightFraction.iDenom = iUiSizePixels.iHeight; + } + else + { + //composition to ui + widthFraction.iNumer = iUiSizePixels.iWidth; + widthFraction.iDenom = iCompositionSizePixels.iWidth; + heightFraction.iNumer = iUiSizePixels.iHeight; + heightFraction.iDenom = iCompositionSizePixels.iHeight; + } + + aTarget.iTl.iX = widthFraction * aSource.iTl.iX; + aTarget.iBr.iX = widthFraction * aSource.iBr.iX; + aTarget.iTl.iY = heightFraction * aSource.iTl.iY; + aTarget.iBr.iY = heightFraction * aSource.iBr.iY; + return KErrNone; + } + +void CDisplayPolicy::MapUiToApplication(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const + { + // only offset is involved in mapping from Ui to App + // no scaling + TPoint offset = iAppSizePixels.iTl;; + + if(aIsReverseMapping) + { + //App to ui + aTarget.iTl = aSource.iTl + offset; + aTarget.iBr = aSource.iBr + offset; + } + else + { + //Ui to App + aTarget.iTl = aSource.iTl - offset; + aTarget.iBr = aSource.iBr - offset; + } + + } + +TInt CDisplayPolicy::MapUiToDSA(const TRect& aSource, TRect& aTarget, TBool aIsReverseMapping) const + { + //only offset is involved in mapping from Ui to DSA + //no scaling + TPoint dsaOffset(0, 0); + + MWsScreenConfig *screenConfig = iScreen->ObjectInterface(); + if(screenConfig) + { + dsaOffset = screenConfig->Origin(); + } + TRect rectInApp; + if(aIsReverseMapping) + { + //DSA to ui + //DSA to App first + rectInApp.iTl = aSource.iTl - dsaOffset; + rectInApp.iBr = aSource.iBr - dsaOffset; + //then app to UI + MapUiToApplication(rectInApp, aTarget, ETrue); + } + else + { + //Ui to DSA + //Ui to App first + MapUiToApplication(aSource, rectInApp, EFalse); + //then app to DSA + aTarget.iTl = rectInApp.iTl + dsaOffset; + aTarget.iBr = rectInApp.iBr + dsaOffset; + } + return KErrNone; + } +TInt CDisplayPolicy::MapCoordinates(TCoordinateSpace aSourceSpace, const TRect& aSource, TCoordinateSpace aTargetSpace, TRect& aTarget) const + { + TInt returnCode=KErrNone; + switch (aSourceSpace) + { + case ECompositionSpace: + { + if(aTargetSpace == ECompositionSpace) + { + aTarget = aSource; + } + else if(aTargetSpace == EFullScreenSpace) + { + //composition to Ui + returnCode=MapCompositionToUi(aSource, aTarget, EFalse); + } + else if(aTargetSpace == EApplicationSpace) + { + //composition to App + TRect rectInUi; + returnCode=MapCompositionToUi(aSource, rectInUi, EFalse); + MapUiToApplication(rectInUi, aTarget, EFalse); + } + else if(aTargetSpace == EDirectScreenAccessSpace) + { + //composition to DSA + TRect rectInUi; + returnCode=MapCompositionToUi(aSource, rectInUi, EFalse); + if(returnCode < 0) + break; + returnCode=MapUiToDSA(rectInUi, aTarget, EFalse); + } + else + { + return KErrNotSupported; + } + } + break; + case EFullScreenSpace: + { + if(aTargetSpace == ECompositionSpace) + { + //Ui to composition + returnCode=MapCompositionToUi(aSource, aTarget, ETrue); + } + else if(aTargetSpace == EFullScreenSpace) + { + aTarget = aSource; + } + else if(aTargetSpace == EApplicationSpace) + { + //Ui to app + MapUiToApplication(aSource, aTarget, EFalse); + } + else if(aTargetSpace == EDirectScreenAccessSpace) + { + //Ui to DSA + returnCode = MapUiToDSA(aSource, aTarget, EFalse); + } + else + { + return KErrNotSupported; + } + } + break; + case EApplicationSpace: + { + if(aTargetSpace == ECompositionSpace) + { + //App to composition + TRect rectInUi; + MapUiToApplication(aSource, rectInUi, ETrue); + returnCode=MapCompositionToUi(rectInUi, aTarget, ETrue); + } + else if(aTargetSpace == EFullScreenSpace) + { + //App to Ui + MapUiToApplication(aSource, aTarget, ETrue); + } + else if(aTargetSpace == EApplicationSpace) + { + aTarget = aSource; + } + else if(aTargetSpace == EDirectScreenAccessSpace) + { + //App to DSA + TRect rectInUi; + MapUiToApplication(aSource, rectInUi, ETrue); + returnCode = MapUiToDSA(rectInUi, aTarget, EFalse); + } + else + { + return KErrNotSupported; + } + } + break; + case EDirectScreenAccessSpace: + { + if(aTargetSpace == ECompositionSpace) + { + //DSA to composition + TRect rectInUi; + returnCode = MapUiToDSA(aSource, rectInUi, ETrue); + if(returnCode < KErrNone) + break; + returnCode = MapCompositionToUi(rectInUi, aTarget, ETrue); + } + else if(aTargetSpace == EFullScreenSpace) + { + //DSA to Ui + returnCode = MapUiToDSA(aSource, aTarget, ETrue); + } + else if(aTargetSpace == EApplicationSpace) + { + //DSA to app + TRect rectInUi; + returnCode = MapUiToDSA(aSource, rectInUi, ETrue); + MapUiToApplication(rectInUi, aTarget, EFalse); + } + else if(aTargetSpace == EDirectScreenAccessSpace) + { + aTarget = aSource; + } + else + { + return KErrNotSupported; + } + break; + } + default: + returnCode= KErrNotSupported; + } + return returnCode; + } + +CDisplayPolicy::TFraction::TFraction():iNumer(0),iDenom(1) + {} + +TInt CDisplayPolicy::TFraction::operator*(TInt aInt) const + { + if (iDenom == 0 || iNumer == 0 || aInt == 0) + { + return 0; + } + TInt aNumer = iNumer<<1; + TInt aDenom = iDenom; + TInt returnValue = (aNumer*aInt)/aDenom; + returnValue ++; + return returnValue>>1; + } + +void CDisplayPolicy::CalculateMinBufferSize(RArray& aResolutions, TInt aConnectionStatus) + { + iConnectionStatus = aConnectionStatus; + //preq2102: aResolutions is likely to be changed (in future) + if(iUiScaling == ENone) + { + //this function is currently only used with no scaling + //should not be called when display is disconnected + //with scaling iMinUiBufferSize is calculated in CDisplayPolicy::GetAppModeList() + TSize largestPhysicalRes = iMinUiBufferSize; + for(TInt i = 0;i < aResolutions.Count(); i++) + { + if(aResolutions[i].iPixelSize.iWidth > largestPhysicalRes.iWidth) + { + largestPhysicalRes.iWidth = aResolutions[i].iPixelSize.iWidth; + } + if(aResolutions[i].iPixelSize.iHeight > largestPhysicalRes.iHeight) + { + largestPhysicalRes.iHeight = aResolutions[i].iPixelSize.iHeight; + } + } + + iMinUiBufferSize = largestPhysicalRes; + } + } + +void CDisplayPolicy::AdjustStageBufferSize(const TSize& /*aOldSize*/,TSize& aNewSize) + { + if (iMinUiBufferSize.iWidth==0) + { + //just in case, should never happen + iMinUiBufferSize=TSize(1,1); + } + + if ((aNewSize.iWidth == 0 || aNewSize.iHeight == 0 + || iConnectionStatus <= 0) && iUiScaling != ENone + && iSmallestAppMode >= 0) // if detached or turned off (iUiScaling != ENone) and smallestAppMode is found + { + aNewSize = iSmallestAppSize; + return; + } + + if (aNewSize.iWidth < iMinUiBufferSize.iWidth) + { + aNewSize.iWidth = iMinUiBufferSize.iWidth; + } + if (aNewSize.iHeight < iMinUiBufferSize.iHeight) + { + aNewSize.iHeight = iMinUiBufferSize.iHeight; + } + } + +void CDisplayPolicy::AddVirtualResolutionCount(TInt& aDisplayCount) const + { + if (iUiScaling != ENone && aDisplayCount>0) + { + aDisplayCount += iNumNormalAppModes; + } + } + +TInt CDisplayPolicy::AddVirtualResolutions(RArray& aResolutions) const + { + if (aResolutions.Count()==0 || iUiScaling == ENone) + { + return KErrNone; + } + if (aResolutions.Count()==1 && aResolutions[0].iPixelSize==TSize(0,0)) + { + return KErrNone; + } + + TInt appModeCount = iAppModes.Count(); + if (appModeCount == 0) + { + return KErrNone; + } + TInt resolutionCount = aResolutions.Count(); + TInt error = aResolutions.Reserve(iNumNormalAppModes + resolutionCount); + if (error < KErrNone) + { + aResolutions.Reset(); + return error; //could fail to reserve if out of memory + } + for (TInt appMode = 0; appMode < appModeCount; appMode++) + { + if (!(iAppModes[appMode].iFlags&(MWsScreenConfigList::EDynamic|MWsScreenConfigList::EHalDefault))) + { + MDisplayControlBase::TResolution virtualResolution = AppModeToResolution(aResolutions,appMode); + aResolutions.Append(virtualResolution); + } + } + return KErrNone; + } + +MDisplayControlBase::TResolution CDisplayPolicy::AppModeToResolution(RArray& aResolutions,TInt appMode)const + { + TAppMode mode = iAppModes[appMode]; + TBool notComplete = ETrue; + TInt bestIndex; + TInt bestScale; + MDisplayControlBase::TResolution tempResolution(TSize(0,0),TSize(0,0)); + TSize appBestSize; + while (notComplete) + { + TBool modeFit = FindVirtualMode(aResolutions,mode,appBestSize,bestIndex,bestScale); + + TSize uiSize; + if (iUiScaling == EInteger || iUiScaling == EIsotropic) + { + uiSize = ResolutionSize(aResolutions,appBestSize,bestIndex,bestScale); + } + else if (iUiScaling == EAnisotropic) + { + TBool swapAxis = EFalse; + TBool fitsAppMode = EFalse; + while (!fitsAppMode) + { + if (iAppModes[appMode].iFlags&MWsScreenConfigList::ETwipsSpecified) + { + //virtualResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize; + //calculate based on twips + uiSize = ResolutionSizeFromTwips(aResolutions,appMode,appBestSize,bestIndex,swapAxis); + } + else + { + //assume square pixels + //virtualResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize; + uiSize = ResolutionSizeFromAssumedTwips(aResolutions,appBestSize,bestIndex,swapAxis,bestScale); + } + + //if pixelsize found is larger than resolution mode its designed for, try scaling using other axis + if (uiSize.iWidth > aResolutions[bestIndex].iPixelSize.iWidth || + uiSize.iHeight > aResolutions[bestIndex].iPixelSize.iHeight) + { + if (!modeFit) //no other mode it could fit, to avoid infinite loop,say it fits the mode - will be scaled down + { + fitsAppMode = ETrue; + } + else + { + STD_ASSERT_DEBUG(swapAxis == EFalse, EPluginPanicTemp); + swapAxis = ETrue; + } + } + else + { + fitsAppMode = ETrue; + } + } + //if pixelsize found does not fit app mode, must retry with an appmode larger than the one found + if (uiSize.iWidth < iAppModes[appMode].iPixels.iBr.iX || + uiSize.iHeight < iAppModes[appMode].iPixels.iBr.iY) + { + mode.iPixels.iBr.iX = aResolutions[bestIndex].iPixelSize.iWidth+1; + mode.iPixels.iBr.iY = aResolutions[bestIndex].iPixelSize.iHeight+1; + continue; + } + } + + //MDisplayControlBase::TResolution virtualResolution(TSize(0,0),TSize(0,0)); + + //only supports rotations supported by both sizemode and hardware + tempResolution.iFlags = iAppModes[appMode].iOrientations&aResolutions[bestIndex].iFlags.iFlags; + tempResolution.iFlags.Set(MDisplayControlBase::TResolution::EIsVirtual); + tempResolution.iTwipsSize = aResolutions[bestIndex].iTwipsSize; + tempResolution.iPixelSize = uiSize; + + notComplete = EFalse; //found a resolution that fits! + } + return tempResolution; + } + +TBool CDisplayPolicy::MatchConfigToResolutions(const RArray& aResolutions, + const TDisplayConfiguration& aConfig, TInt aStartIndex, TInt& aResolutionIndex)const + { + if (aStartIndex < 0 || aStartIndex >= aResolutions.Count()) + { + return EFalse; + } + aResolutionIndex = -1; + for (TInt i = aStartIndex; i < aResolutions.Count(); i++) + { + if (aConfig.IsDefined(TDisplayConfigurationBase::EResolution)) + { + TSize resolution; + aConfig.GetResolution(resolution); + if (resolution != aResolutions[i].iPixelSize) + { + continue; + } + } + if (aConfig.IsDefined(TDisplayConfigurationBase::EResolutionTwips)) + { + TSize twips; + aConfig.GetResolutionTwips(twips); + if (twips != aResolutions[i].iTwipsSize) + { + continue; + } + } + + if (aConfig.IsDefined(TDisplayConfigurationBase::ERotation)) + { + TDisplayConfiguration1::TRotation rotation; + aConfig.GetRotation(rotation); + if (aResolutions[i].iFlags.IsClear(rotation)) + { + continue; + } + } + aResolutionIndex = i; + return ETrue; + } + return EFalse; + } + +/* + Checks if specified appmode is compatible with TResolution specified + Returns ETrue if succeeded (and fills aConfig with TResolution + Return EFalse if they are not compatible (will not touch the config) +*/ +TBool CDisplayPolicy::SetConfigToResolution(TInt aAppMode, MDisplayControlBase::TResolution aResolution, TDisplayConfiguration& aConfig)const + { + //find intersection of appmode and hardware rotations + TDisplayConfiguration1::TRotation configRotation; + TInt compatibleRotations; + if (aConfig.GetRotation(configRotation)) + { + compatibleRotations = iAppModes[aAppMode].iOrientations&aResolution.iFlags.iFlags&0xF&(1< 0) + { //set first compatible rotation we find + if (1<& aResolutions, + TInt aScreenSizeMode, TDisplayConfiguration& aConfig, TRect& aSizeModePosition) const + { + //find appMode corresponding to screensizemode + TInt appMode; + TInt appModeCount = iAppModes.Count(); + for (appMode = 0; appMode < appModeCount; appMode++) + { + if (iAppModes[appMode].iModeIndex == aScreenSizeMode) + { + break; + } + } + if (appModeCount == appMode) + { + return KErrArgument; //invalid screen size mode + } + if (!aConfig.IsDefined(TDisplayConfigurationBase::EResolution)&& + !aConfig.IsDefined(TDisplayConfigurationBase::EResolutionTwips)) + { + if (iAppModes[appMode].iFlags&MWsScreenConfigList::EDynamic) + { + TSize resSize = iCompositionSizePixels; + TSize twipsSize = iCompositionSizeTwips; + if (iLastCompositionRotation&TDisplayConfiguration::ERotation90CW || + iLastCompositionRotation&TDisplayConfiguration::ERotation270CW) + { + TInt tempVal = resSize.iWidth; + resSize.iWidth = resSize.iHeight; + resSize.iHeight = tempVal; + tempVal = twipsSize.iWidth; + twipsSize.iWidth = twipsSize.iHeight; + twipsSize.iHeight = tempVal; + } + aConfig.SetResolution(resSize); + aConfig.SetResolutionTwips(twipsSize); + } + else + { + MDisplayControlBase::TResolution virtualResolution = AppModeToResolution(aResolutions,appMode); + aConfig.SetResolution(virtualResolution.iPixelSize); + aConfig.SetResolutionTwips(virtualResolution.iTwipsSize); + } + } + + //check config is valid from set of resolutions (inc virtual) + TInt error = AddVirtualResolutions(aResolutions); + if (error < KErrNone) + { + return error; + } + TInt startIndex=0; + while (startIndex < aResolutions.Count()) + { + TInt resolutionIndex; + TBool boolError = MatchConfigToResolutions(aResolutions,aConfig,startIndex,resolutionIndex); + if (boolError == EFalse) + { + return KErrArgument; + } + + //if is larger than current app mode and same rotation,we have found a match and can break; + TBool boolSet = SetConfigToResolution(appMode,aResolutions[resolutionIndex],aConfig); + if (boolSet) + { //new configuration is compatible with app mode and has been set + //center appmode within the UI + if (iAppModes[appMode].iFlags&MWsScreenConfigList::EDynamic) + { + aSizeModePosition = aResolutions[resolutionIndex].iPixelSize; + } + else + { + CenteredAppInUi(aResolutions[resolutionIndex].iPixelSize,iAppModes[appMode].iPixels,aSizeModePosition); + } + + TDisplayConfiguration::TRotation tempRot; + aConfig.GetRotation(tempRot); + if (tempRot&1) + { + aSizeModePosition = TRect(aSizeModePosition.iTl.iY,aSizeModePosition.iTl.iX, + aSizeModePosition.iBr.iY,aSizeModePosition.iBr.iX); + } + + return KErrNone; + } + //otherwise + startIndex = resolutionIndex+1; //match found will not fit current size mode, continue looking + if (startIndex == aResolutions.Count()) + { + return KErrArgument; + } + } + STD_ASSERT_DEBUG(EFalse, EPluginPanicTemp); + return KErrGeneral; //shouldnt be able to get here + } + +void CDisplayPolicy::CenteredAppInUi(const TSize& aUiSize,const TRect& aAppExtent,TRect& aSizeModePosition) const + { + if (aUiSize.iWidth > aAppExtent.Width()) + { + aSizeModePosition.iTl.iX = (aUiSize.iWidth - aAppExtent.Width()) / 2; + if (aSizeModePosition.iTl.iX < aAppExtent.iTl.iX) + { //we want to obey screenmode offset as a minumum, so cannot center on this axis + aSizeModePosition.iTl.iX = aAppExtent.iTl.iX; + aSizeModePosition.iBr.iX = aAppExtent.iBr.iX; + } + else + { + aSizeModePosition.iBr.iX = aSizeModePosition.iTl.iX + aAppExtent.Width(); + } + } + else + { + aSizeModePosition.iTl.iX = aAppExtent.iTl.iX; + aSizeModePosition.iBr.iX = aAppExtent.iBr.iX; + } + + if (aUiSize.iHeight > aAppExtent.Height()) + { + aSizeModePosition.iTl.iY = (aUiSize.iHeight - aAppExtent.Height()) / 2; + if (aSizeModePosition.iTl.iY < aAppExtent.iTl.iY) + { //we want to obey screenmode offset as a minumum, so cannot center on this axis + aSizeModePosition.iTl.iY = aAppExtent.iTl.iY; + aSizeModePosition.iBr.iY = aAppExtent.iBr.iY; + } + else + { + aSizeModePosition.iBr.iY = aSizeModePosition.iTl.iY + aAppExtent.Width(); + } + } + else + { + aSizeModePosition.iTl.iY = aAppExtent.iTl.iY; + aSizeModePosition.iBr.iY = aAppExtent.iBr.iY; + } + } + +TInt CDisplayPolicy::GetSizeModeConfiguration(TInt aScreenSizeMode,TDisplayConfiguration& aConfig, TRect& aSizeModePosition) + { + //This function is used when display is disconnected. Set UI size same as app mode. We don't care about rotation + + //find appMode corresponding to screensizemode + TInt appMode; + TInt appModeCount = iAppModes.Count(); + for (appMode = 0; appMode < appModeCount; appMode++) + { + if (iAppModes[appMode].iModeIndex == aScreenSizeMode) + { + break; + } + } + if (appModeCount == appMode) + { + return KErrArgument; //invalid screen size mode + } + + if (1<ObjectInterface()->OrientationL(aScreenSizeMode)); + aConfig.SetRotation(TDisplayConfiguration::TRotation(cFbsOrientation)); + aSizeModePosition = iAppModes[appMode].iPixels; + return KErrNone; + } + +TBool CDisplayPolicy::SettingConfiguration(const RArray& aResolutions,TDisplayConfiguration& aConfig)const + { //converts configuration to appmode + if (iUiScaling == ENone) + { + if (aConfig.IsDefined(aConfig.EResolution)) + { + TSize res; + aConfig.GetResolution(res); + TInt index; + for (index=0;index& aResolutions, + const CDisplayPolicy::TAppMode& aAppMode,TSize& aFullAppModeSize,TInt& aIndex,TInt& aBestScale) const + { + const TInt KBestFit = 0x7000000; //a really big number that should get reduced during the search. + TInt bestFit=KBestFit; + TInt resDiffX; + TInt resDiffY; + TInt64 biggestArea(0); + TInt biggestAreaIndex=0; + TBool fullAppSize; + + if (aAppMode.iPixels.iTl.iX == 0 && aAppMode.iPixels.iTl.iY == 0) + { //no point trying again with a border on only 2 sides, as there is no border anyway! + fullAppSize = EFalse; + } + else + { + fullAppSize = ETrue; + } + aFullAppModeSize = TSize(aAppMode.iPixels.iBr.iX + aAppMode.iPixels.iTl.iX, + aAppMode.iPixels.iBr.iY + aAppMode.iPixels.iTl.iY); //try fitting with border all 4 sides + + while(1) + { + //find hardware mode that fits this best + for (TInt j = 0; j < aResolutions.Count(); j++) + { + if (bestFit == 0) + { //found a perfect match + break; + } + if (aResolutions[j].iFlags[MDisplayControlBase::TResolution::EIsVirtual]) + { //ignore virtual resolutions + continue; + } + TInt maxScaling = 1; + if (iUiScaling == EInteger) + { + maxScaling = 4; + } + for (TInt k = maxScaling; k > 0; k--) + { //for every avalable integer scale + if (bestFit == 0) + { //found a perfect match + break; + } + TInt64 area=TInt64(aResolutions[j].iPixelSize.iWidth)*aResolutions[j].iPixelSize.iHeight; + if (area>biggestArea) + { + biggestArea=area; + biggestAreaIndex=j; + } + resDiffX = (aResolutions[j].iPixelSize.iWidth/k) - aFullAppModeSize.iWidth; + resDiffY = (aResolutions[j].iPixelSize.iHeight/k) - aFullAppModeSize.iHeight; + + if (resDiffX < 0 || resDiffY < 0) + { //app mode too large for this resolution + continue; + } + if (resDiffX+resDiffY < bestFit) + { + aIndex = j; + bestFit = resDiffX + resDiffY; + aBestScale = k; + continue; + } + } + } + if (bestFit != KBestFit) + { //it found the best resolution to scale into + break; + } + else if (fullAppSize == EFalse) + { //app does not fit any resolution, it will have to be scaled down to fit + aIndex=biggestAreaIndex; + aBestScale=1; + return EFalse; + } + else + { + aFullAppModeSize = TSize(aAppMode.iPixels.iBr.iX, + aAppMode.iPixels.iBr.iY); //try fitting with border only top and left + fullAppSize = EFalse; + } + } + return ETrue; + } + +TSize CDisplayPolicy::ResolutionSize(RArray& aResolutions, + const TSize aBestAppSize,TInt aIndex, TInt aScale) const + { + TSize returnSize; + + if (iUiScaling == EInteger) //only supporting integral scales + { //just calculate the scaled resolution + returnSize = TSize(aResolutions[aIndex].iPixelSize.iWidth/aScale, + aResolutions[aIndex].iPixelSize.iHeight/aScale); + } + else + { //find which axis scales best, create virtual resolution that fits this axis + TFraction bestAxisAsFraction; + + if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight > + (TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth) + { //y axis scales closest + bestAxisAsFraction.iNumer = aResolutions[aIndex].iPixelSize.iWidth; + bestAxisAsFraction.iDenom = aResolutions[aIndex].iPixelSize.iHeight; + returnSize = TSize(bestAxisAsFraction*aBestAppSize.iHeight, + aBestAppSize.iHeight); + } + else + { //x axis scales closest + bestAxisAsFraction.iNumer = aResolutions[aIndex].iPixelSize.iHeight; + bestAxisAsFraction.iDenom = aResolutions[aIndex].iPixelSize.iWidth; + returnSize = TSize(aBestAppSize.iWidth, + bestAxisAsFraction*aBestAppSize.iWidth); + } + } + return returnSize; + } + +TSize CDisplayPolicy::GetUiResolution() + { + return this->iUiSizePixels; + } + +TSize CDisplayPolicy::GetUiResolutionAsTwips() const + { + return this->iCompositionSizeTwips; + } + +TRect CDisplayPolicy::GetPolicyAppMode() + { + return iAppSizePixels; + } + +TSize CDisplayPolicy::ResolutionSizeFromTwips(RArray& aResolutions, TInt aAppMode, const TSize& aBestAppSize, + TInt aIndex,TBool aSwapAxis) const + { + TSize returnSize; + TFraction tempFraction; + TBool yScalesClosest; + + if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight > (TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth) + { //y axis scales closest + yScalesClosest = aSwapAxis?EFalse:ETrue; + } + else + { //x axis scales closest + yScalesClosest = aSwapAxis?ETrue:EFalse; + } + + if (yScalesClosest) + { //y axis scales closest + tempFraction.iNumer = aBestAppSize.iHeight; //bordered app height in pixels + tempFraction.iDenom = iAppModes[aAppMode].iPixels.iBr.iY - iAppModes[aAppMode].iPixels.iTl.iY; //app height in pixels + TInt uiYTwips=tempFraction*iAppModes[aAppMode].iTwips.iHeight; //bordered app height in twips + + tempFraction.iNumer = aResolutions[aIndex].iTwipsSize.iWidth; //display width in twips + tempFraction.iDenom = aResolutions[aIndex].iTwipsSize.iHeight; //display height in twips + TInt uiXTwips=tempFraction*uiYTwips; //virtual width in twips + + tempFraction.iNumer = iAppModes[aAppMode].iPixels.iBr.iX - iAppModes[aAppMode].iPixels.iTl.iX; //app width in pixels + tempFraction.iDenom = iAppModes[aAppMode].iTwips.iWidth; //display width in twips + TInt uiXPixels=tempFraction*uiXTwips; //virtual width in pixels + + returnSize.iWidth = uiXPixels; + returnSize.iHeight = aBestAppSize.iHeight; + } + else + { //x axis scales closest + tempFraction.iNumer = aBestAppSize.iWidth; //bordered app width in pixels + tempFraction.iDenom = iAppModes[aAppMode].iPixels.iBr.iX - iAppModes[aAppMode].iPixels.iTl.iX; //app width in pixels + TInt uiXTwips=tempFraction*iAppModes[aAppMode].iTwips.iWidth; //bordered app width in twips + + tempFraction.iNumer = aResolutions[aIndex].iTwipsSize.iHeight; //display height in twips + tempFraction.iDenom = aResolutions[aIndex].iTwipsSize.iWidth; //display width in twips + TInt uiYTwips=tempFraction*uiXTwips; //virtual height in twips + + tempFraction.iNumer = iAppModes[aAppMode].iPixels.iBr.iY - iAppModes[aAppMode].iPixels.iTl.iY; //app height in pixels + tempFraction.iDenom = iAppModes[aAppMode].iTwips.iHeight; //display height in twips + TInt uiYPixels=tempFraction*uiYTwips; //virtual width in pixels + + returnSize.iWidth = aBestAppSize.iWidth; + returnSize.iHeight = uiYPixels; + } + + return returnSize; + } + +TSize CDisplayPolicy::ResolutionSizeFromAssumedTwips(RArray& aResolutions,const TSize& aBestAppSize, + TInt aIndex,TBool aSwapAxis, TInt aScale) const + { + TSize returnSize; + + if (iUiScaling == EInteger) //only supporting integral scales + { //just calculate the scaled resolution + returnSize = TSize(aResolutions[aIndex].iTwipsSize.iWidth/aScale, + aResolutions[aIndex].iTwipsSize.iHeight/aScale); + } + else + { //find which axis scales best, create virtual resolution that fits this axis + TBool yScalesClosest; + TFraction bestAxisAsFraction; + + if ((TInt64)aResolutions[aIndex].iPixelSize.iWidth * aBestAppSize.iHeight > + (TInt64)aResolutions[aIndex].iPixelSize.iHeight * aBestAppSize.iWidth) + { //y axis scales closest + yScalesClosest = aSwapAxis?EFalse:ETrue; + } + else + { //x axis scales closest + yScalesClosest = aSwapAxis?ETrue:EFalse; + } + + if (yScalesClosest) + { //y axis scales closest + bestAxisAsFraction.iNumer = aResolutions[aIndex].iTwipsSize.iWidth; + bestAxisAsFraction.iDenom = aResolutions[aIndex].iTwipsSize.iHeight; + returnSize = TSize(bestAxisAsFraction*aBestAppSize.iHeight, + aBestAppSize.iHeight); + } + else + { //x axis scales closest + bestAxisAsFraction.iNumer = aResolutions[aIndex].iTwipsSize.iHeight; + bestAxisAsFraction.iDenom = aResolutions[aIndex].iTwipsSize.iWidth; + returnSize = TSize(aBestAppSize.iWidth, + bestAxisAsFraction*aBestAppSize.iWidth); + } + } + return returnSize; + } + +TInt CDisplayPolicy::MinSizedModeIndex() + { + return iSmallestAppMode; + } + +TInt CDisplayPolicy::SuitableAppMode(MWsDisplayPolicy::TDisplayStatus aSituation) + { + switch(aSituation) + { + case MWsDisplayPolicy::EAttach: + { + return iLastAppMode; + } + case MWsDisplayPolicy::EDetach: + { + return MinSizedModeIndex(); + } + default: + return KErrNotSupported; + } + + } + +void CDisplayPolicy::SetLastAppMode(TInt aMode) + { + iLastAppMode = aMode; + } + +