contextframework/cfwplugins/displaysourceplugin/src/displayserviceuilayout.cpp
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contextframework/cfwplugins/displaysourceplugin/src/displayserviceuilayout.cpp	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,520 @@
+/*
+* Copyright (c) 2009-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:   CDisplayServiceUILayout class implementation.
+*
+*/
+
+
+// SYSTEM INCLUDES
+#include <cfcontextobject.h>
+#include <cfcontextinterface.h>
+#include <apgwgnam.h>
+#include <coedef.h>
+
+// USER INCLUDES
+#include "displayserviceuilayout.h"
+#include "displaysourcecontextdef.h"
+#include "displaysourcepluginpanic.h"
+#include "trace.h"
+
+// ======================== LOCAL FUNCTIONS ========================
+
+#ifdef _DEBUG
+
+/** Rotation constants */
+_LIT( KGraphicsOrientationNormal, "Normal" );
+_LIT( KGraphicsOrientationRotated90, "Rotated 90" );
+_LIT( KGraphicsOrientationRotated180, "Rotated 180" );
+_LIT( KGraphicsOrientationRotated270, "Rotated 270" );
+
+LOCAL_C const TDesC& RotationAsDesC( TInt aRotation )
+    {
+    switch( aRotation )
+        {
+        case CFbsBitGc::EGraphicsOrientationNormal:
+            {
+            return KGraphicsOrientationNormal;
+            }
+        case CFbsBitGc::EGraphicsOrientationRotated90:
+            {
+            return KGraphicsOrientationRotated90;
+            }
+        case CFbsBitGc::EGraphicsOrientationRotated180:
+            {
+            return KGraphicsOrientationRotated180;
+            }
+        case CFbsBitGc::EGraphicsOrientationRotated270:
+            {
+            return KGraphicsOrientationRotated270;
+            }
+        default:
+            {
+            return KNullDesC;
+            }
+        }
+    }
+
+#endif
+
+// ======================== MEMBER FUNCTIONS ========================
+
+// ======================== CDisplayServiceUILayout ========================
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CDisplayServiceUILayout::CDisplayServiceUILayout( MCFContextInterface& aCF ):
+    CDisplayServiceBase( CDisplayServiceBase::EDisplayUILayout, aCF ),
+    iCurrentLayout( EUILayoutValueUnknown )
+    {
+    FUNC_LOG;
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::ConstructL()
+    {
+    FUNC_LOG;
+    
+    // Call base class
+    CDisplayServiceBase::ConstructL();
+    
+    // Configure context source and type
+    iContext->SetSourceL( KDisplaySource );
+    iContext->SetTypeL( KDisplayUILayoutType );
+    
+    // Define context:
+    // Device: Display.UI.Layout
+    TInt err = iCF.DefineContext(
+        KDisplaySource, KDisplayUILayoutType, KDisplayUILayoutSec );
+    User::LeaveIfError( err );
+    
+    // Define context:
+    // Device: Display.UI.Rotation
+    err = iCF.DefineContext(
+        KDisplaySource, KDisplayUIRotationType, KDisplayUIRotationSec );
+    User::LeaveIfError( err );
+    
+    // Create window server event handler
+    iWsEventHandler = CWsEventHandler::NewL( *this );
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian two phased constructor.
+// ---------------------------------------------------------------------------
+//
+CDisplayServiceUILayout* CDisplayServiceUILayout::NewL(
+    MCFContextInterface& aCF )
+    {
+    FUNC_LOG;
+
+    CDisplayServiceUILayout* self = CDisplayServiceUILayout::NewLC( aCF );
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian two phased constructor.
+// Leaves pointer in the cleanup stack.
+// ---------------------------------------------------------------------------
+//
+CDisplayServiceUILayout* CDisplayServiceUILayout::NewLC(
+    MCFContextInterface& aCF )
+    {
+    FUNC_LOG;
+
+    CDisplayServiceUILayout* self =
+        new ( ELeave ) CDisplayServiceUILayout( aCF );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// C++ destructor.
+// ---------------------------------------------------------------------------
+//
+CDisplayServiceUILayout::~CDisplayServiceUILayout()
+    {
+    FUNC_LOG;
+
+    delete iWsEventHandler;
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::StartL
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::StartL()
+    {
+    FUNC_LOG;
+
+    // Get initial values
+    TDisplayUILayoutValues layout;
+    CFbsBitGc::TGraphicsOrientation rotation;
+    iWsEventHandler->ResolveUILayout( layout, rotation );
+
+    // Publish initial UI layout context value
+    PublishContextL( layout, ETrue );
+    
+    // Publish initial UI rotation context value
+    PublishContextL( rotation, ETrue );
+    
+    //  Start listening window server events
+    iWsEventHandler->IssueRequest();
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::Stop
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::Stop()
+    {
+    FUNC_LOG;
+    
+    iWsEventHandler->Cancel();
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::HandleWsEventL
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::HandleWsEventL( const TWsEvent &aEvent )
+    {
+    FUNC_LOG;
+    
+    INFO_1( "New window server event received: Event: [%d]", aEvent.Type() );
+
+    // New window server event received, solve the event type
+    switch( aEvent.Type() )
+        {
+        case EEventWindowGroupsChanged:
+        case EEventScreenDeviceChanged:
+            {
+            TDisplayUILayoutValues layout = EUILayoutValueUnknown;
+            CFbsBitGc::TGraphicsOrientation rotation =
+                CFbsBitGc::EGraphicsOrientationNormal;
+            iWsEventHandler->ResolveUILayout( layout, rotation );
+            PublishContextL( layout );
+            PublishContextL( rotation );
+            break;
+            }
+        default:
+            {
+            // Nothing to do here
+            break;
+            }
+        }
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::HandleWsEventErrorL
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::HandleWsEventErrorL( TInt aError )
+    {
+    FUNC_LOG;
+    
+    // Remove warnings in urel builds
+    (void)aError;
+    
+    ERROR( aError,
+        "Window server event error occured. UI layout set to 'unknown" );
+
+    // Error occured and it is impossible to know the current UI layout.
+    // Publish context:
+    // Device: Display.UI.Layout: Unknown
+    iContext->SetValueL( TPtrC(
+        KDisplayUILayoutValues[EUILayoutValueUnknown] ) );
+    iCF.PublishContext( *iContext, iThread );
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::PublishContextL
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::PublishContextL( TDisplayUILayoutValues aLayout,
+    TBool aForce )
+    {
+    FUNC_LOG;
+
+    if( aLayout != iCurrentLayout || aForce )
+        {
+        iContext->SetTypeL( KDisplayUILayoutType );
+        iContext->SetValueL( TPtrC( KDisplayUILayoutValues[aLayout] ) );
+        iCF.PublishContext( *iContext, iThread );
+        iCurrentLayout = aLayout;
+        }
+    }
+
+//------------------------------------------------------------------------------
+// CDisplayServiceUILayout::PublishContextL
+//------------------------------------------------------------------------------
+//
+void CDisplayServiceUILayout::PublishContextL(
+    CFbsBitGc::TGraphicsOrientation aRotation,
+    TBool aForce )
+    {
+    FUNC_LOG;
+
+    if( aRotation != iCurrentRotation || aForce )
+        {
+        iContext->SetTypeL( KDisplayUIRotationType );
+        iContext->SetValueL( TPtrC( KDisplayUIRotationValues[aRotation] ) );
+        iCF.PublishContext( *iContext, iThread );
+        iCurrentRotation = aRotation;
+        }
+    }
+
+// ======================== CWsEventHandler ========================
+
+// ---------------------------------------------------------------------------
+// C++ constructor.
+// ---------------------------------------------------------------------------
+//
+CWsEventHandler::CWsEventHandler( MWsEventObserver& aObserver ):
+    CActive( CActive::EPriorityStandard ),
+    iObserver( aObserver )
+    {
+    FUNC_LOG;
+    
+    CActiveScheduler::Add( this );
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian 2nd phase constructor.
+// ---------------------------------------------------------------------------
+//
+void CWsEventHandler::ConstructL()
+    {
+    FUNC_LOG;
+    
+    // Connect to window server server
+    User::LeaveIfError( iWsSession.Connect() );
+    
+    // Construct window group
+    iWindowGroup = new( ELeave ) RWindowGroup( iWsSession );
+    User::LeaveIfError( iWindowGroup->Construct( (TUint32)this, EFalse ) );
+    User::LeaveIfError( iWindowGroup->EnableScreenChangeEvents() );
+    User::LeaveIfError( iWindowGroup->EnableGroupChangeEvents() );
+    iWindowGroup->SetOrdinalPosition( 0, ECoeWinPriorityNeverAtFront );
+    iWindowGroup->EnableReceiptOfFocus( EFalse );
+    
+    // Hide the invisible window from the task manager
+    iWindowGroupName = CApaWindowGroupName::NewL( iWsSession );
+    iWindowGroupName->SetHidden( ETrue );
+    iWindowGroupName->SetWindowGroupName( *iWindowGroup );
+
+    // Construct screen device
+    iWsScreenDevice = new( ELeave ) CWsScreenDevice( iWsSession );
+    User::LeaveIfError( iWsScreenDevice->Construct() );
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian two phased constructor.
+// ---------------------------------------------------------------------------
+//
+CWsEventHandler* CWsEventHandler::NewL( MWsEventObserver& aObserver )
+    {
+    FUNC_LOG;
+
+    CWsEventHandler* self = CWsEventHandler::NewLC( aObserver );
+    CleanupStack::Pop( self );
+    
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Symbian two phased constructor.
+// Leaves pointer in the cleanup stack.
+// ---------------------------------------------------------------------------
+//
+CWsEventHandler* CWsEventHandler::NewLC( MWsEventObserver& aObserver )
+    {
+    FUNC_LOG;
+
+    CWsEventHandler* self = new ( ELeave ) CWsEventHandler( aObserver );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// C++ destructor.
+// ---------------------------------------------------------------------------
+//
+CWsEventHandler::~CWsEventHandler()
+    {
+    FUNC_LOG;
+    
+    Cancel();
+    
+    // Cleanup screen device
+    delete iWsScreenDevice;
+    
+    // Cleanup window group name
+    delete iWindowGroupName;
+       
+    // Cleanup window group
+    if( iWindowGroup )
+        {
+        iWindowGroup->DisableGroupChangeEvents();
+        iWindowGroup->DisableScreenChangeEvents();
+        iWindowGroup->Close();
+        delete iWindowGroup;
+        }
+    
+    // Cleanup window server session
+    iWsSession.Close();
+    }
+
+//------------------------------------------------------------------------------
+// CWsEventHandler::IssueRequest
+//------------------------------------------------------------------------------
+//
+void CWsEventHandler::IssueRequest()
+    {
+    FUNC_LOG;
+
+    __ASSERT_DEBUG( !IsActive(), Panic( ERequestAlreadyIssued ) );
+    
+    // Request events from window server
+    iWsSession.EventReady( &iStatus );
+    SetActive();
+    }
+
+//------------------------------------------------------------------------------
+// CWsEventHandler::ResolveUILayout
+//------------------------------------------------------------------------------
+//
+void CWsEventHandler::ResolveUILayout( TDisplayUILayoutValues& aLayout,
+    CFbsBitGc::TGraphicsOrientation& aRotation ) const
+    {
+    FUNC_LOG;
+    
+    // Resolve the current UI layout from screen dimensions
+    TInt mode = iWsScreenDevice->CurrentScreenMode();
+    INFO_1( "Current screen mode: [%d]", mode );
+    
+    TPixelsAndRotation pixelsAndRotation;
+    iWsScreenDevice->GetScreenModeSizeAndRotation( mode, pixelsAndRotation );
+    INFO_3( "Current screen mode size and rotation: Size: [W=%d, H=%d], Rotation: [%S]",
+        pixelsAndRotation.iPixelSize.iWidth,
+        pixelsAndRotation.iPixelSize.iHeight,
+        &RotationAsDesC( pixelsAndRotation.iRotation ) );
+    
+    // Resolve current UI rotation
+    aRotation = pixelsAndRotation.iRotation;
+    
+    // Resovle current UI layout mode
+    TSize screenSize( pixelsAndRotation.iPixelSize );
+    if( screenSize.iWidth < screenSize.iHeight )
+        {
+        // Assuming portrait layout
+        INFO( "Current UI layout resolved to be in 'Portrait' mode" );
+        aLayout = EUILayoutValuePortrait;
+        }
+    else if( screenSize.iWidth > screenSize.iHeight )
+        {
+        // Assuming landscape layout
+        INFO( "Current UI layout resolved to be in 'Landscape' mode" );
+        aLayout = EUILayoutValueLandscape;
+        }
+    else
+        {
+        // Need to check the rotation even though this might not be correct
+        // if wsini.ini has not been configured properly.
+        CFbsBitGc::TGraphicsOrientation orientation(
+            pixelsAndRotation.iRotation );
+        if( orientation == CFbsBitGc::EGraphicsOrientationNormal ||
+            orientation == CFbsBitGc::EGraphicsOrientationRotated180 )
+            {
+            // Assuming portrait layout
+            INFO( "Current UI layout resolved to be in 'Portrait' mode" );
+            aLayout = EUILayoutValuePortrait;
+            }
+        else
+            {
+            // Assuming landscape layout
+            INFO( "Current UI layout resolved to be in 'Landscape' mode" );
+            aLayout = EUILayoutValueLandscape;
+            }
+        }
+    }
+
+//------------------------------------------------------------------------------
+// CWsEventHandler::RunL
+//------------------------------------------------------------------------------
+//
+void CWsEventHandler::RunL()
+    {
+    FUNC_LOG;
+    
+    TInt err = iStatus.Int();
+    if( err == KErrNone )
+        {
+        // No errors occured, fetch event
+        TWsEvent wsEvent;
+        iWsSession.GetEvent( wsEvent );
+        
+        // Continue listening
+        IssueRequest();
+        
+        // Forward event to observer
+        iObserver.HandleWsEventL( wsEvent );
+        }
+    else
+        {
+        // Continue listening
+        IssueRequest();
+        
+        // Forward error to observer
+        iObserver.HandleWsEventErrorL( err );
+        }    
+    }
+
+//------------------------------------------------------------------------------
+// CWsEventHandler::DoCancel
+//------------------------------------------------------------------------------
+//
+void CWsEventHandler::DoCancel()
+    {
+    FUNC_LOG;
+    
+    // Cancel event ready from window server
+    iWsSession.EventReadyCancel();
+    }
+
+//------------------------------------------------------------------------------
+// CWsEventHandler::RunError
+//------------------------------------------------------------------------------
+//
+TInt CWsEventHandler::RunError( TInt /*aError*/ )
+    {
+    FUNC_LOG;
+
+    // Issue a new request, other error handling is not performed since the
+    // problem has occured in the observer code
+    IssueRequest();
+    
+    return KErrNone;
+    }
+
+// End of file