taskswitcher/taskswitcherui/taskswitcherapp/src/tsfastswaparea.cpp
branchRCL_3
changeset 83 5456b4e8b3a8
child 88 3321d3e205b6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/taskswitcher/taskswitcherui/taskswitcherapp/src/tsfastswaparea.cpp	Wed Sep 01 12:32:46 2010 +0100
@@ -0,0 +1,1971 @@
+/*
+* Copyright (c) 2008 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:  Taskswitcher Fast Swap area UI
+ *
+*/
+
+
+#include <gulicon.h>
+#include <eikenv.h>
+#include <AknUtils.h>
+#include <AknIconUtils.h>
+#include <AknIconArray.h>
+#include <aknstyluspopupmenu.h>
+#include <AknQueryDialog.h>
+#include <StringLoader.h>
+#include <taskswitcher.rsg>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <aknlists.h>
+#include <touchfeedback.h>
+#include <akntransitionutils.h>
+#include <akntranseffect.h>
+#include <aknlongtapanimation.h>
+
+#include "tsfastswaparea.h"
+#include "tsapplogging.h"
+#include "tsfswclient.h"
+#include "tsappui.h"
+#include "tsdatachangeobserver.h"
+#include "tseventcontroler.h"
+#include "tsappview.h"
+
+/** command ids for the fsw popup */
+enum TPopupCommands
+    {
+    EFswCmdClose = 10000,
+    EFswCmdCloseAll
+    };
+
+/** Number of closable applications, to show "close all" option. */
+const TInt KTsMaxClosableApps = 2;
+
+/** Default grid item to highlight.*/
+const TInt KItemToHighlight = 2;
+
+const TInt KAppKeyTypeShort = 1;
+const TInt KAppKeyTypeLong = 2;
+
+const TInt KLayoutItemCount = 4;
+
+const TInt KRedrawTime = 250000; // 0.25 sec
+const TInt KRedrawTimeForLayoutSwitch = 700000; // 0.7 sec
+const TInt KHighlighActivationTime = 100000; // 100 ms
+const TInt KUpdateGridTime = 0; // imediately
+const TInt KOrientationSwitchTime = 1000000; // 1 sec
+const TInt KLongTapAnimationInitTime = 150000; // 0.15 sec
+const TInt KLongTapAnimationTimeout = 1000000; // 1 sec
+
+const TInt KMaxGranularity = 4;
+
+const TUid KTsMenuUid = { 0x101f4cd2 };
+const TUid KTsHomescreenUid = { 0x102750f0 };
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NewL
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea* CTsFastSwapArea::NewL( const TRect& aRect,
+    CCoeControl& aParent, CTsDeviceState& aDeviceState, 
+    CTsEventControler& aEventHandler )
+    {
+    CTsFastSwapArea* self = CTsFastSwapArea::NewLC(aRect,
+            aParent, aDeviceState, aEventHandler);
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NewLC
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea* CTsFastSwapArea::NewLC( const TRect& aRect,
+    CCoeControl& aParent, CTsDeviceState& aDeviceState,
+    CTsEventControler& aEventHandler)
+    {
+    CTsFastSwapArea* self = new (ELeave) CTsFastSwapArea(
+            aParent, aDeviceState, aEventHandler);
+    CleanupStack::PushL( self );
+    self->ConstructL( aRect );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::CTsFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea::CTsFastSwapArea(CCoeControl& aParent,
+    CTsDeviceState& aDeviceState,
+    CTsEventControler& aEventHandler) :
+    iParent(aParent), iDeviceState(aDeviceState), iEvtHandler(aEventHandler),
+    iIgnoreLayoutSwitch(EFalse), iWidgetClosingCount(0), iLongTapAnimationRunning(EFalse)
+    {
+    // no implementation required
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::~CTsFastSwapArea
+// -----------------------------------------------------------------------------
+//
+CTsFastSwapArea::~CTsFastSwapArea()
+    {
+    iArray.ResetAndDestroy();
+    iIsClosing.Close();
+    delete iGrid;
+    delete iFSClient;
+    delete iPopup;
+    delete iHighlightTimer;
+    delete iRedrawTimer;
+    delete iUpdateGridTimer;
+    delete iOrientationSignalTimer;
+    delete iLongTapAnimation;
+    delete iLongTapAnimationTimer;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ConstructL( const TRect& aRect )
+    {
+    SetContainerWindowL( iParent );
+
+    SetRect( aRect );
+
+    // setup grid
+    ReCreateGridL();
+
+    // create stylus popup instance
+    PreCreatePopupL();
+
+    // connect to fsw server
+    iFSClient = CTsFswClient::NewL();
+    
+    iEvtHandler.ReInitPhysicsL(GridWorldSize(), ViewSize(), ETrue);
+    
+    // add self to device state observer
+    iDeviceState.AddObserverL( *this, EDeviceType );
+    
+    iHighlightTimer = new (ELeave) CTsFastSwapTimer( *this );
+    iHighlightTimer->ConstructL();
+    
+    iRedrawTimer = new (ELeave) CTsFastSwapTimer( *this );
+    iRedrawTimer->ConstructL();
+
+    iUpdateGridTimer = new (ELeave) CTsFastSwapTimer( *this );
+    iUpdateGridTimer->ConstructL();
+    
+    iOrientationSignalTimer = new (ELeave) CTsFastSwapTimer( *this ); 
+    iOrientationSignalTimer->ConstructL();
+    
+    iLongTapAnimationTimer = new (ELeave) CTsFastSwapTimer( *this ); 
+    iLongTapAnimationTimer->ConstructL();
+    
+    iActivateOnPointerRelease = TPoint();
+    iHandlePointerCandidate = EFalse;
+    
+    ActivateL();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ReCreateGridL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ReCreateGridL()
+    {
+    MCoeControlObserver* obs = NULL;
+    TBool wasHighlight = iDeviceState.DeviceType() == 
+                             CTsDeviceState::EHybrid ? ETrue : EFalse;
+    if ( iGrid )
+        {
+        obs = iGrid->Observer();
+        iDeviceState.RemoveObserver(*iGrid);
+        wasHighlight = iGrid->IsHighlightVisible();
+        delete iGrid;
+        iGrid = NULL;
+        }
+    
+    iGrid = new( ELeave ) CTsFastSwapGrid;
+    iGrid->ConstructL( this );
+	iGrid->DisableSingleClick(ETrue);//enables highlight on pointer
+    iDeviceState.AddObserverL(*iGrid, MTsDeviceStateObserver::ESkin);
+    
+    AknListBoxLayouts::SetupStandardGrid( *iGrid );
+    
+    // Setup layout
+    LayoutGridL();
+    
+    if( wasHighlight )
+        {
+        iGrid->ShowHighlight();
+        }
+    else
+        {
+        iGrid->HideHighlight();
+        }
+    
+    // Setup empty text
+    HBufC* text = StringLoader::LoadLC( R_TS_FSW_NO_APPS );
+    iGrid->SetEmptyGridTextL( *text );
+    CleanupStack::PopAndDestroy( text );
+    
+    // Setup grid observers
+    if ( obs )
+        {
+        iGrid->SetObserver( obs );
+        }
+    iGrid->SetListBoxObserver(this);
+    iGrid->SetFastSwapGridObserver(this);
+    iGrid->SetContainerWindowL(*this);
+	
+    // Make sure that there is an ActivateL call even when we are not
+    // called from ConstructL. (in order to have the grid's parent ptr set properly)
+    ActivateL();
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::LayoutGridL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::LayoutGridL()
+    {
+    RArray<TAknLayoutRect> rects;
+    CleanupClosePushL(rects);
+    rects.ReserveL(KLayoutItemCount);
+    GetFastSwapAreaRects(rects);
+    TAknLayoutRect gridAppPane = rects[0];
+    TAknLayoutRect gridItem = rects[1];
+    TAknLayoutRect gridImage = rects[2];
+    TAknLayoutRect gridNextItem = rects[3];
+    CleanupStack::PopAndDestroy(&rects);
+    
+    iGrid->SetRect(gridAppPane.Rect());
+    
+    TInt variety;
+    TBool disable = GetVariety(variety);
+    if ( disable )
+        {
+        TRAP_IGNORE(static_cast<CTsAppUi*>(iEikonEnv->AppUi())->RequestPopUpL());
+        }
+    variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; // double check to avoid layout panic
+    
+    TAknLayoutScalableParameterLimits gridParams = 
+        AknLayoutScalable_Apps::cell_tport_appsw_pane_ParamLimits( variety );
+    TPoint empty( ELayoutEmpty, ELayoutEmpty );
+    
+    // Setup bitmap layout
+    AknListBoxLayouts::SetupFormGfxCell( *iGrid, iGrid->ItemDrawer(), 0,
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ).LayoutLine(),
+            empty, empty );
+
+    // Setup text layout
+    AknListBoxLayouts::SetupFormTextCell(*iGrid, iGrid->ItemDrawer(), 1,
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_t1( variety ).LayoutLine(),
+            empty, empty);
+    
+    // Text colors
+    TRgb textColor;
+    AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG19 );
+    TRgb highlightTextColor;
+    AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), highlightTextColor,
+            KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG11 );
+    CFormattedCellListBoxData::TColors colors;
+    colors.iText = textColor;
+    colors.iBack = iGrid->ItemDrawer()->BackColor();
+    colors.iHighlightedText = highlightTextColor;
+    colors.iHighlightedBack = iGrid->ItemDrawer()->HighlightedBackColor();
+    iGrid->ItemDrawer()->FormattedCellData()->SetSubCellColorsL(1, colors);
+    iGrid->SetStrokeColors(textColor, highlightTextColor);
+    
+    if ( AknLayoutUtils::LayoutMirrored() )
+        {
+        iGridItemGap = gridItem.Rect().iTl.iX - gridNextItem.Rect().iBr.iX;
+        }
+    else
+        {
+        iGridItemGap = gridNextItem.Rect().iTl.iX - gridItem.Rect().iBr.iX;
+        }
+    iMaxItemsOnScreen = Rect().Width() / gridItem.Rect().Width();
+    if ( iMaxItemsOnScreen > 1 )
+        {
+        TInt widthWithGaps =
+            (iMaxItemsOnScreen - 1) * iGridItemGap + iMaxItemsOnScreen * gridItem.Rect().Width();
+        if ( widthWithGaps > Rect().Width() )
+            {
+            iMaxItemsOnScreen--;
+            }
+        }
+    iGridItemWidth = gridItem.Rect().Width();
+    
+    // Update item drawer
+    iGrid->UpdateItemDrawerLayoutDataL();
+    
+    // Update state
+    HandleDeviceStateChanged( EDeviceType );
+    
+    if ( disable )
+        {
+        TRAP_IGNORE(static_cast<CTsAppUi*>(iEikonEnv->AppUi())->DisablePopUpL());
+        }
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::LayoutGridView
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::LayoutGridViewL( TInt aItemCount )
+    {
+    RArray<TAknLayoutRect> rects;
+    CleanupClosePushL(rects);
+    rects.ReserveL(KLayoutItemCount);
+    GetFastSwapAreaRects(rects);
+    TAknLayoutRect gridItem = rects[1];
+    CleanupStack::PopAndDestroy(&rects);
+    if ( aItemCount )
+        {
+        iGrid->ItemDrawer()->ColumnData()->SetDrawBackground(EFalse);
+        static_cast<CTsAppView*>(&iParent)->EnableDragEvents(ETrue);
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            iGrid->SetLayoutL( EFalse, EFalse, ETrue, aItemCount, 1, gridItem.Rect().Size(), iGridItemGap );
+            }
+        else
+            {
+            iGrid->SetLayoutL( EFalse, ETrue, ETrue, aItemCount, 1, gridItem.Rect().Size(), iGridItemGap );
+            }
+        }
+    else
+        {
+        iGrid->ItemDrawer()->ColumnData()->SetDrawBackground(ETrue);
+        static_cast<CTsAppView*>(&iParent)->EnableDragEvents(EFalse);
+        }
+    
+    // Update scrollbar frame
+    if( iGrid->ScrollBarFrame() )
+        {
+        iGrid->SetScrollBarFrame(NULL,CEikListBox::EOwnedExternally);
+        }
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::GetFastSwapAreaRects
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::GetFastSwapAreaRects( RArray<TAknLayoutRect>& aRects )
+    {
+    TAknLayoutRect gridAppPane;
+    TAknLayoutRect gridItem;
+    TAknLayoutRect gridImage;
+    TAknLayoutRect gridNextItem;
+    
+    TInt variety;
+    TBool disable = GetVariety(variety);
+    if ( disable )
+        {
+        TRAP_IGNORE(static_cast<CTsAppUi*>(iEikonEnv->AppUi())->RequestPopUpL());
+        }
+    variety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0; // double check to avoid layout panic
+    
+    gridAppPane.LayoutRect( Rect(), 
+            AknLayoutScalable_Apps::tport_appsw_pane( variety ) );
+    aRects.Append(gridAppPane);
+    
+    gridItem.LayoutRect( gridAppPane.Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane( variety, 0, 0 ) );
+    aRects.Append(gridItem);
+    
+    gridImage.LayoutRect( gridItem.Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_g1( variety ) ); 
+    aRects.Append(gridImage);
+    gridNextItem.LayoutRect( gridAppPane.Rect(),
+            AknLayoutScalable_Apps::cell_tport_appsw_pane_cp03( variety ) );
+    aRects.Append(gridNextItem);
+    
+    if ( disable )
+        {
+        TRAP_IGNORE(static_cast<CTsAppUi*>(iEikonEnv->AppUi())->DisablePopUpL());
+        }
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::Setup
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Setup( MCoeControlObserver& aControlObserver )
+    {
+    iGrid->SetObserver( &aControlObserver );
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SizeChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SizeChanged()
+    {
+    TSLOG_CONTEXT( CTsFastSwapArea::SizeChanged, TSLOG_LOCAL );
+    TSLOG_IN();
+    
+    if ( iGrid && !iIgnoreLayoutSwitch )
+        {
+        // Cancel ongoing pointer event
+        iHandlePointerCandidate = EFalse;
+        // Grid needs to be recreated to proper reinitilize
+        // data with new layout values
+        TInt selIdx = SelectedIndex();
+        TRAPD(err,
+              LayoutGridL();
+              LayoutGridViewL( iArray.Count() );
+              iEvtHandler.ReInitPhysicsL( GridWorldSize(), ViewSize(), ETrue );
+              );
+        
+        if ( err != KErrNone )
+            {
+            TSLOG1( TSLOG_INFO, "LayoutGridL leaves with %d", err );
+            }
+        
+        // Update grid view
+        iGrid->SetCurrentDataIndex(selIdx);
+        UpdateGrid(ETrue, EFalse);
+        iGrid->DrawDeferred();
+        
+        // Order full redraw after switch
+        if(iRedrawTimer)
+            {
+            iRedrawTimer->Cancel();
+            iRedrawTimer->After(KRedrawTimeForLayoutSwitch);
+            }
+        }
+    
+    TSLOG_OUT();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Draw
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Draw( const TRect& /*aRect*/ ) const
+    {
+//    CWindowGc& gc = SystemGc();
+//    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+//    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
+//    AknsDrawUtils::Background( skin,
+//           cc,
+//           this,
+//           gc,
+//           Rect() );
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SwitchToApp
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SwitchToApp( TInt aIndex )
+    {
+    if ( aIndex >= 0 && aIndex < iArray.Count() )
+        {
+        TInt wgId = iArray[aIndex]->WgId();
+        TUid appUid = iArray[aIndex]->AppUid();
+        SwitchToApp( wgId, appUid );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SwitchToApp
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SwitchToApp( const TUid& aUid )
+    {
+    TApaTaskList taskList( iEikonEnv->WsSession() );
+    TApaTask task = taskList.FindApp( aUid );
+    TInt wgId = task.WgId();
+    SwitchToApp( wgId, aUid );
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SwitchToApp
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SwitchToApp( TInt aWgId, const TUid& aUid )
+    {
+    CTsAppUi* appui =
+        static_cast<CTsAppUi*>( iEikonEnv->AppUi() );
+    TBool effectsEnabled = appui->EffectsEnabled();
+
+    // Move other app to foreground
+    if ( !effectsEnabled )
+        {
+        iFSClient->SwitchToApp( aWgId );
+        }
+    
+    // We do not want to come back to ts if the activated app is closed.
+    // Therefore ts must be moved to background. Ignore orientation updates, it
+    // will be done after task switcher is sent to background
+    iIgnoreLayoutSwitch = ETrue;
+    appui->MoveAppToBackground( CTsAppUi::EActivationTransition, aUid, aWgId );
+    iIgnoreLayoutSwitch = EFalse;
+    
+    // Move other app to foreground
+    if ( effectsEnabled )
+        {
+        iFSClient->SwitchToApp( aWgId );
+        }
+    
+    // Orientation update
+    iPrevScreenOrientation = -1; // force orientation reinit
+    iOrientationSignalTimer->Cancel();
+    iOrientationSignalTimer->After(KOrientationSwitchTime);
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::TryCloseAppL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TryCloseAppL( TInt aIndex,
+        TBool aSuppressRendering )
+    {
+    TSLOG_CONTEXT( TryCloseAppL, TSLOG_LOCAL );
+    TSLOG2_IN( "%d %d", aIndex, aSuppressRendering );
+
+    if ( aIndex >= 0 && aIndex < iArray.Count() && CanClose( aIndex ) )
+        {
+        TInt wgId = iArray[aIndex]->WgId();
+        iFSClient->CloseApp( wgId );
+        iIsClosing.Append(wgId);
+        if ( iArray[aIndex]->Widget() )
+            {
+            iWidgetClosingCount++;
+            }
+        
+        // Orientation update
+        iPrevScreenOrientation = GetCurrentScreenOrientation();
+        iOrientationSignalTimer->Cancel();
+        iOrientationSignalTimer->After(KOrientationSwitchTime);
+        }
+
+    TSLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::TryCloseAllL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TryCloseAllL()
+    {
+    for ( TInt i = iArray.Count() - 1; i >= 0; --i )
+        {
+        if ( CanClose( i ) )
+            {
+            TryCloseAppL( i, ETrue );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CanClose
+// --------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::CanClose( TInt aIndex ) const
+    {
+    TBool canClose(EFalse);
+    if ( aIndex >= 0 && aIndex < iArray.Count() )
+        {
+        CTsFswEntry* e = iArray[aIndex];
+        canClose = !e->AlwaysShown() && !e->SystemApp();
+        // Special cases: Menu
+        canClose |= e->AppUid() == KTsMenuUid;
+        }
+    return canClose;
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CanCloseOthers
+// --------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::CanCloseAll( TInt aSelectedItem ) const
+    {
+    TInt count( 0 );
+
+    // Count number of closable applications and if number exceeds 2 finish
+    // counting, because it is already enough to show the option.
+    for ( TInt i = iArray.Count(); --i >= 0 && count < KTsMaxClosableApps; )
+        {
+        if ( CanClose( i ) )
+            {
+            count++;
+            }
+        }
+    return ( count >= KTsMaxClosableApps ) ||
+           ( count && !CanClose( aSelectedItem ) );
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleFswContentChanged
+// From MTsFswObserver
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleFswContentChanged()
+    {
+    TSLOG_CONTEXT( HandleFswContentChanged, TSLOG_LOCAL );
+    TSLOG_IN();
+
+    TRAPD( err, HandleFswContentChangedL() );
+    if ( err != KErrNone )
+        {
+        TSLOG1( TSLOG_INFO, "leave occured: %d", err );
+        }
+
+    TSLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleFswContentChangedL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleFswContentChangedL()
+    {
+    TSLOG_CONTEXT( HandleFswContentChangedL, TSLOG_LOCAL );
+    TSLOG_IN();
+
+    // get current content from fastswap server
+    iFSClient->GetContentL( iArray );
+
+#ifdef _DEBUG
+    for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
+        {
+        CTsFswEntry* e = iArray[i];
+        const TDesC& name( e->AppName() );
+        TSLOG4( TSLOG_INFO, "[%d]: %d %d %S", i, e->WgId(), e->AppUid(), &name );
+        }
+#endif
+    
+    // Update closing widget count if necessary
+    if ( iWidgetClosingCount )
+        {
+        TInt widgetCount(0);
+        for ( TInt i = 0, ie = iArray.Count(); i != ie; ++i )
+            {
+            if ( iArray[i]->Widget() )
+                {
+                widgetCount++;
+                }
+            }
+        iWidgetClosingCount = widgetCount;
+        }
+
+    // draw
+    RenderContentL();
+
+    // notify observer, if present
+    NotifyChange();
+
+    TSLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::RenderContentL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::RenderContentL( TBool aSuppressAnimation )
+    {
+    TSLOG_CONTEXT( RenderContentL, TSLOG_LOCAL );
+    TSLOG_IN();
+
+    _LIT(KSeparator, "\t");
+    
+    CArrayPtr<CGulIcon>* iconArray = new ( ELeave ) CAknIconArray( KMaxGranularity );
+    CleanupStack::PushL( iconArray );
+    CDesCArrayFlat* textArray = new ( ELeave ) CDesCArrayFlat( KMaxGranularity );
+    CleanupStack::PushL( textArray );
+    RArray<TInt> closeItemArray;
+    CleanupClosePushL(closeItemArray);
+    RArray<TInt> strokeItemArray;
+    CleanupClosePushL(strokeItemArray);
+    
+    // Update view based on number of items
+    LayoutGridViewL( iArray.Count() );
+    
+    for ( TInt i = 0; i < iArray.Count(); ++i )
+        {
+        const TDesC& appName( iArray[i]->AppName() );
+        const TInt formatLen = 3 + 2;
+        RBuf formAppName;
+        CleanupClosePushL(formAppName);
+        formAppName.CreateL(appName.Length() + formatLen);
+        formAppName.AppendNum(i);
+        formAppName.Append(KSeparator);
+        formAppName.Append(appName);
+        textArray->AppendL(formAppName);
+        CleanupStack::PopAndDestroy(&formAppName);
+        TSize sz = PreferredImageSize();
+
+        // take the screenshot or appicon+mask and make a copy and scale
+        CFbsBitmap* bitmap = 0;
+        TInt h = iArray[i]->ScreenshotHandle();
+        TSLOG2( TSLOG_INFO, "'%S' screenshot handle %d", &appName, h );
+        TInt maskh = 0;
+        CFbsBitmap* mask = 0;
+        if ( !h )
+            {
+            // No screenshot, take app icon
+            h = iArray[i]->AppIconBitmapHandle();
+            maskh = iArray[i]->AppIconMaskHandle();
+            TSLOG1( TSLOG_INFO, "using appicon, handle = %d", h );
+            }
+        else
+            {
+            // Screenshot exists, mark it for stroke
+            strokeItemArray.AppendL(i);
+            }
+        __ASSERT_DEBUG( h, User::Invariant() );
+        bitmap = CopyBitmapL( h, sz );
+        CleanupStack::PushL( bitmap );
+        if ( maskh )
+            {
+            mask = CopyBitmapL( maskh, sz );
+            }
+        CleanupStack::PushL( mask );
+
+        CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
+        CleanupStack::PushL(icon);
+        iconArray->AppendL(icon);
+        CleanupStack::Pop( 3, bitmap ); // mask, bitmap, icon
+        
+        // Check if item can be closed
+        if ( CanClose(i) && AknLayoutUtils::PenEnabled() )
+            {
+            closeItemArray.AppendL(i);
+            }
+        }
+    // Setup grid
+    iGrid->Model()->SetItemTextArray(textArray);
+    CArrayPtr<CGulIcon>* oldIconArray =
+        iGrid->ItemDrawer()->FormattedCellData()->IconArray();
+    if(oldIconArray)
+        {
+        delete oldIconArray;
+        oldIconArray = NULL;
+        }
+    iGrid->ItemDrawer()->FormattedCellData()->SetIconArrayL(iconArray);
+    iGrid->SetCloseItemsL(closeItemArray);
+    iGrid->SetStrokeItemsL(strokeItemArray);
+    
+    // Update scrollbar visibility
+    if( iGrid->ScrollBarFrame() )
+        {
+        iGrid->SetScrollBarFrame(NULL,CEikListBox::EOwnedExternally);
+        }
+    
+    // Cleanup
+    CleanupStack::PopAndDestroy(&strokeItemArray);
+    CleanupStack::PopAndDestroy(&closeItemArray);
+    CleanupStack::Pop(textArray);
+    CleanupStack::Pop(iconArray);
+    
+    // refresh the items in the grid
+    iGrid->HandleItemAdditionL();
+    iEvtHandler.ReInitPhysicsL( GridWorldSize(), ViewSize(), ETrue );
+    if ( SelectedIndex() >= GridItemCount() && GridItemCount() )
+        {
+        iGrid->SetCurrentDataIndex( GridItemCount() - 1 );
+        }
+    UpdateGrid( ETrue, !aSuppressAnimation );
+    
+    TSLOG_OUT();
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CopyBitmapL
+// Copy and scale.
+// --------------------------------------------------------------------------
+//
+CFbsBitmap* CTsFastSwapArea::CopyBitmapL( TInt aFbsHandle, TSize aSize )
+    {
+    CFbsBitmap* ret = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL( ret );
+
+    CFbsBitmap* bmp = new (ELeave) CFbsBitmap();
+    CleanupStack::PushL( bmp );
+    User::LeaveIfError( bmp->Duplicate( aFbsHandle ) );
+
+    // do not always use aSize, preserving the aspect ratio is quite
+    // important when showing app icons instead of screenshots
+    TSize sz = CalculateSizePreserveRatio( aSize, bmp->SizeInPixels() );
+    User::LeaveIfError( ret->Create( sz, bmp->DisplayMode() ) );
+
+    AknIconUtils::ScaleBitmapL( sz, ret, bmp );
+
+    CleanupStack::PopAndDestroy( bmp );
+    CleanupStack::Pop( ret );
+
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CountComponentControls
+// --------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::CountComponentControls() const
+    {
+    return 1;
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::ComponentControl
+// --------------------------------------------------------------------------
+//
+CCoeControl* CTsFastSwapArea::ComponentControl( TInt aIndex ) const
+    {
+    if ( aIndex == 0 )
+        {
+        return iGrid;
+        }
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleSwitchToBackgroundEvent
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleSwitchToBackgroundEvent()
+    {
+    // stop listening for changes in fsw content
+    iFSClient->CancelSubscribe();
+    // Hide highlight
+    if ( iGrid->GridBehaviour() == CTsFastSwapGrid::ETouchOnly )
+        {
+        iGrid->HideHighlight();
+        }
+    CancelLongTapAnimation();
+    iGrid->MakeVisible(EFalse);
+    iGrid->DrawNow();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleSwitchToForegroundEvent
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleSwitchToForegroundEvent()
+    {
+    TSLOG_CONTEXT( CTsFastSwapArea::HandleSwitchToForegroundEvent, TSLOG_LOCAL );
+    TSLOG_IN();
+    
+    iIsClosing.Reset();
+    iWidgetClosingCount = 0;
+    iHandlePointerCandidate = EFalse;
+    
+    CTsGridItemDrawer* itemDrawer =
+        static_cast<CTsGridItemDrawer*>( iGrid->ItemDrawer() );
+    itemDrawer->SetRedrawBackground(ETrue);
+    
+    // Update Layout
+    CTsAppUi* appUi = static_cast<CTsAppUi*>(iEikonEnv->AppUi());
+    if ( appUi && appUi->EffectsEnabled() )
+        {
+        TRAP_IGNORE( LayoutGridL() );
+        }
+    
+    // Reset grid
+    if ( iDeviceState.DeviceType() == CTsDeviceState::EFullTouch )
+        {
+        iGrid->HideHighlight();
+        }
+    else
+        {
+        iGrid->ShowHighlight();
+        }
+    
+    // get the current task list
+    HandleFswContentChanged();
+    // and then start listening for changes
+    iFSClient->Subscribe( *this );
+    
+    RestoreSelectedIndex();
+    UpdateGrid(EFalse, EFalse);
+    
+    iRedrawTimer->Cancel();
+    iRedrawTimer->After(KRedrawTime);
+    
+    // give feedback
+    LaunchPopupFeedback();
+    
+    iPrevAppCount = iArray.Count();
+    
+    if ( !appUi->DelayedForegroundLaunched() )
+        {
+        iGrid->MakeVisible(ETrue);
+        }
+
+    TSLOG_OUT();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::FocusChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::FocusChanged( TDrawNow /*aDrawNow*/ )
+    {
+    if ( IsFocused() )
+        {
+        // if in non-touch mode then select (highlight) some item
+        if ( !AknLayoutUtils::PenEnabled()
+            && SelectedIndex() == KErrNotFound
+            && GridItemCount() )
+            {
+            RestoreSelectedIndex();
+            }
+        }
+    else
+        {
+        // store the currently selected index if there is one
+        SaveSelectedIndex();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::OfferKeyEventL
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CTsFastSwapArea::OfferKeyEventL(
+        const TKeyEvent& aKeyEvent,
+        TEventCode aType )
+    {
+    CancelLongTapAnimation();
+    
+    iKeyEvent = ETrue;
+    
+    //do not forward the event until item is higlighted
+    TKeyResponse response = ShowHighlightOnKeyEvent(aKeyEvent, aType);
+    if( response == EKeyWasConsumed )
+        {
+        return EKeyWasConsumed;
+        }
+    
+    // handle the 'clear' key
+    if ( aType == EEventKey && aKeyEvent.iCode == EKeyBackspace )
+        {
+        TInt idx = SelectedIndex();
+        if ( idx >= 0 )
+            {
+            TryCloseAppL( idx );
+            }
+        return EKeyWasConsumed;
+        }
+    
+    // pass the event to grid
+    // do not pass down and up arrow key events
+    if ( aKeyEvent.iScanCode != EStdKeyUpArrow &&
+         aKeyEvent.iScanCode != EStdKeyDownArrow &&
+         aKeyEvent.iScanCode != EStdKeyApplication0 )
+        {
+        TBool animate(ETrue);
+        TBool redraw(EFalse);
+        TInt prevItem = SelectedIndex();
+        TKeyResponse response = iGrid->OfferKeyEventL( aKeyEvent, aType );
+        if ( prevItem != SelectedIndex() && // item changed
+             ( ( prevItem == 0 &&
+                 SelectedIndex() == GridItemCount() - 1 &&
+                 GridItemCount() > iMaxItemsOnScreen + 1 ) || // loop from first to last item
+               ( prevItem == GridItemCount() - 1 &&
+                 SelectedIndex() == 0 &&
+                 GridItemCount() > iMaxItemsOnScreen + 1) // loop from last to first item
+              ) // loop
+            )
+            {
+            // Loop occured
+            animate = EFalse;
+            }
+        if ( prevItem != SelectedIndex() )
+            {
+            redraw = ETrue;
+            iGrid->ShowHighlight();
+            }
+        UpdateGrid( redraw, animate );
+        return response;
+        }
+    
+    return EKeyWasNotConsumed;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::CatchKeyEvent
+// -----------------------------------------------------------------------------
+//
+TKeyResponse CTsFastSwapArea::ShowHighlightOnKeyEvent(
+		const TKeyEvent& aKeyEvent, TEventCode aType)
+	{
+	TKeyResponse retVal(EKeyWasNotConsumed);
+	
+	if (aKeyEvent.iScanCode == EStdKeyLeftArrow ||
+		aKeyEvent.iScanCode == EStdKeyRightArrow ||
+		aKeyEvent.iScanCode == EStdKeyDevice3 ||
+        aKeyEvent.iScanCode == EStdKeyBackspace ||
+        aKeyEvent.iScanCode == EStdKeyEnter )
+	    {
+		if (!iGrid->IsHighlightVisible())
+			{
+			if (aType == EEventKey)
+				{
+				iGrid->ShowHighlight();
+				iConsumeEvent = ETrue;
+				}
+			retVal = EKeyWasConsumed;
+			}
+		else if (iConsumeEvent)
+			{
+			if (aType == EEventKeyUp)
+				{
+				retVal = EKeyWasConsumed;
+				}
+			else
+				{
+				iConsumeEvent = EFalse;
+				}
+			}
+		}
+	return retVal;
+	}
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandlePointerEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    iKeyEvent = EFalse;
+    if(aPointerEvent.iType == TPointerEvent::EButton1Down)
+        {
+        iHandlePointerCandidate = ETrue;
+        iTapEvent = aPointerEvent;
+        iGrid->EnableAknEventHandling(EFalse);
+        iGrid->HandlePointerEventL(aPointerEvent);
+        iGrid->EnableAknEventHandling(ETrue);
+        // Check if long tap animation should be launched
+        if ( LongTapAnimForPos(aPointerEvent.iParentPosition) )
+            {
+            iLongTapAnimationTimer->Cancel();
+            iLongTapAnimationTimer->After(KLongTapAnimationInitTime);
+            }
+        }
+    else if ( aPointerEvent.iType == TPointerEvent::EButton1Up )
+        {
+        CancelLongTapAnimation( EFalse );
+        if( iActivateOnPointerRelease != TPoint() )
+            {
+            iHandlePointerCandidate = ETrue;
+            TapL(iActivateOnPointerRelease);
+            iActivateOnPointerRelease = TPoint();
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SelectedIndex
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::SelectedIndex() const
+    {
+    return iGrid->CurrentDataIndex();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SaveSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SaveSelectedIndex()
+    {
+    iSavedSelectedIndex = SelectedIndex();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::RestoreSelectedIndex
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::RestoreSelectedIndex()
+    {
+    iSavedSelectedIndex = KErrNotFound;
+    if ( GridItemCount() )
+        {
+        // highlight second recent item (that has index 1) if possible
+        TInt highlightItem = 0;
+        TInt count = GridItemCount();
+        while( highlightItem < count 
+            && highlightItem < KItemToHighlight )
+            {
+            ++highlightItem;
+            }
+        iSavedSelectedIndex = highlightItem - 1;//count from 0
+        iGrid->SetCurrentDataIndex( iSavedSelectedIndex );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ProcessCommandL
+// Handle fsw popup commands
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::ProcessCommandL( TInt aCommandId )
+    {
+    static_cast<CTsAppUi*>(iEikonEnv->AppUi())->DisablePopUpL();
+    switch ( aCommandId )
+        {
+        case EFswCmdClose:
+            TryCloseAppL( iAppIndexForPopup );
+            break;
+
+        case EFswCmdCloseAll:
+            TryCloseAllL();
+            break;
+
+        case KErrCancel:
+            // popup dismisses automatically when tapping outside or when switching to other app
+            break;
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleCloseEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleCloseEventL(TInt aItemIdx)
+    {
+    TryCloseAppL( aItemIdx );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleDeviceStateChanged
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleDeviceStateChanged( TChangeType aChangeType )
+    {
+    if ( aChangeType == EDeviceType )
+        {
+        CTsDeviceState::TDeviceType state = iDeviceState.DeviceType();
+        switch ( state )
+            {
+            case CTsDeviceState::EHybrid:
+                {
+                iGrid->SetGridBehaviour( CTsFastSwapGrid::EHybrid );
+                }
+                break;
+            case CTsDeviceState::EFullTouch:
+                {
+                iGrid->SetGridBehaviour( CTsFastSwapGrid::ETouchOnly );
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::TimerCompletedL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TimerCompletedL( CTsFastSwapTimer* aSource )
+    {
+    if(aSource == iHighlightTimer)
+        {
+        iTapEvent.iType = TPointerEvent::EButton1Up;
+        iGrid->HandlePointerEventL(iTapEvent);
+        }
+    else if(aSource == iRedrawTimer)
+        {
+        iGrid->MakeVisible(ETrue);
+        static_cast<CTsAppView*>(&iParent)->OrderFullWindowRedraw();
+        }
+    else if( aSource == iUpdateGridTimer )
+        {
+        UpdateGrid(ETrue, ETrue);
+        }
+    else if ( aSource == iOrientationSignalTimer )
+        {
+        TInt currentOrientation = GetCurrentScreenOrientation();
+        if ( currentOrientation != iPrevScreenOrientation )
+            {
+            // Order layout change
+            static_cast<CAknAppUi*>(iCoeEnv->AppUi())->HandleResourceChangeL(KEikDynamicLayoutVariantSwitch);
+            iRedrawTimer->Cancel();
+            iRedrawTimer->After(KRedrawTime);
+            }
+        }
+    else if ( aSource == iLongTapAnimationTimer )
+        {
+        if ( iLongTapAnimationRunning )
+            {
+            CancelLongTapAnimation();
+            }
+        else
+            {
+            static_cast<CTsAppUi*>(iEikonEnv->AppUi())->RequestPopUpL();
+            if ( iLongTapAnimation )
+                {
+                delete iLongTapAnimation;
+                iLongTapAnimation = NULL;
+                }
+            iLongTapAnimation = CAknLongTapAnimation::NewL(EFalse);
+            iLongTapAnimation->SetParent( this );
+            iLongTapAnimation->ShowAnimationL( iTapEvent.iParentPosition.iX,
+                                               iTapEvent.iParentPosition.iY );
+            iLongTapAnimationRunning = ETrue;
+            iLongTapAnimationTimer->Cancel();
+            iLongTapAnimationTimer->After(KLongTapAnimationTimeout);
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::PreCreatePopupL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::PreCreatePopupL()
+    {
+    if ( !iPopup )
+        {
+        iPopup = CAknStylusPopUpMenu::NewL( this, Rect().iTl );
+        HBufC* text = StringLoader::LoadLC( R_TS_FSW_CLOSE );
+        iPopup->AddMenuItemL( *text, EFswCmdClose );
+        CleanupStack::PopAndDestroy( text );
+        text = StringLoader::LoadLC( R_TS_FSW_CLOSE_ALL );
+        iPopup->AddMenuItemL( *text, EFswCmdCloseAll );
+        CleanupStack::PopAndDestroy( text );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ShowPopupL
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::ShowPopupL( TInt aIndex, const TPoint& aPoint )
+    {
+    TBool showPopUp(EFalse);
+    TBool showPopupItem;
+    // hide 'close' if app cannot be closed
+    showPopupItem = CanClose( aIndex );
+    iPopup->SetItemDimmed( EFswCmdClose, !showPopupItem );
+    showPopUp = showPopUp || showPopupItem;
+    // hide 'close all' if there are no applications to close.
+    showPopupItem = CanCloseAll( aIndex );
+    iPopup->SetItemDimmed( EFswCmdCloseAll, !showPopupItem );
+    showPopUp = showPopUp || showPopupItem;
+
+    if(showPopUp)
+        {
+        static_cast<CTsAppUi*>(iEikonEnv->AppUi())->RequestPopUpL();
+        // give feedback
+        LaunchPopupFeedback();
+        // save index for later use & show popup
+        iAppIndexForPopup = aIndex;
+        iPopup->SetPosition( aPoint, CAknStylusPopUpMenu::EPositionTypeLeftBottom );
+        iPopup->ShowMenu();
+        }
+    return showPopUp;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Count
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::Count() const
+    {
+    return iArray.Count();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::SetDataChangeObserver
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SetDataChangeObserver(
+        MTsDataChangeObserver* aDcObserver )
+    {
+    iDcObserver = aDcObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::NotifyChange
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::NotifyChange()
+    {
+    if ( iDcObserver )
+        {
+        iDcObserver->DataChanged( this, Count() );
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::PreferredImageSize
+// -----------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::PreferredImageSize()
+    {
+    TAknLayoutRect gridImage;
+    TRAP_IGNORE(
+        RArray<TAknLayoutRect> rects;
+        CleanupClosePushL(rects);
+        rects.ReserveL(KLayoutItemCount);
+        GetFastSwapAreaRects(rects);
+        gridImage = rects[2];
+        CleanupStack::PopAndDestroy(&rects);
+        );
+    return gridImage.Rect().Size();
+    }
+    
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::GridItemCount
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::GridItemCount()
+    {
+    return iGrid->Model()->ItemTextArray()->MdcaCount();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::HandleListBoxEventL
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType)
+    {
+    if ( aListBox == iGrid )
+        {
+        switch ( aEventType )
+            {
+            case EEventEnterKeyPressed:
+            case EEventItemClicked:
+            case EEventItemSingleClicked:
+                {
+                SwitchToApp(SelectedIndex());
+                }
+                break;
+            case EEventPenDownOnItem:
+                {
+                iGrid->ShowHighlight();
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CalculateSizePreserveRatio
+// --------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::CalculateSizePreserveRatio(
+        const TSize& aTargetAreaSize,
+        const TSize& aSourceSize )
+    {
+    const TReal 
+      resizedAspectRatio(aTargetAreaSize.iWidth/(TReal)aTargetAreaSize.iHeight);
+    const TReal 
+      orginalAspectRatio(aSourceSize.iWidth/(TReal)aSourceSize.iHeight);
+    //this condition avoid empty margins ( bigger output ). to realy fit area change it
+    const TReal scaleFactor = 
+        ( orginalAspectRatio > resizedAspectRatio ) ? 
+        (aTargetAreaSize.iHeight /(TReal)aSourceSize.iHeight) ://scale by height
+        (aTargetAreaSize.iWidth /(TReal)aSourceSize.iWidth) ;//scale by width
+    return TSize(aSourceSize.iWidth * scaleFactor, aSourceSize.iHeight * scaleFactor);
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::SelectNextItem
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::SelectNextItem()
+    {
+    iKeyEvent = ETrue;
+    TBool forceRedraw(ETrue);
+    TBool animate(ETrue);
+    TInt selectedItem = SelectedIndex();
+    selectedItem++;
+    if ( selectedItem == GridItemCount() )
+        {
+        // Last item is selected, move to first one
+        selectedItem = 0;
+        animate = EFalse;
+        }
+    iGrid->SetCurrentDataIndex(selectedItem);
+    UpdateGrid(forceRedraw, animate);
+    }
+
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::CenterItem
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::CenterItem(TInt aRedrawDelay)
+    {
+    if( iMaxItemsOnScreen < GridItemCount() )
+        {
+        TInt visibleItem = ViewToVisibleItem( ViewPos() );
+        if(iKeyEvent)
+            {
+            visibleItem = SelectedIndex();
+            }
+        if(visibleItem != SelectedIndex())
+            {
+            iGrid->SetCurrentDataIndex( visibleItem );
+            iParent.DrawDeferred();
+            iGrid->DrawDeferred();
+            }
+        }
+
+    // Check if view is outside of grid world
+    TPoint absViewPos = ViewPos();
+    absViewPos.iX -= Rect().Width() / 2;
+    if( !iEvtHandler.IsPhysicsRunning() &&
+        ( absViewPos.iX < 0 ||( absViewPos.iX + Rect().Width() > GridWorldSize().iWidth && GridItemCount() ) )
+      )
+        {
+        // View is outside of grid world - update view
+        iUpdateGridTimer->Cancel();
+        iUpdateGridTimer->After(aRedrawDelay);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::GridWorldSize
+// --------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::GridWorldSize()
+    {
+    return TSize( GridItemCount() * iGridItemWidth + (GridItemCount() - 1) * iGridItemGap, Rect().Height() );
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::UpdateGrid
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::UpdateGrid( TBool aForceRedraw, TBool aAnimate )
+    {
+    TPoint targetPoint = ItemViewPosition( SelectedIndex() );
+    if ( aForceRedraw || targetPoint.iX != ViewPos().iX )
+        {
+        if ( aAnimate )
+            {
+            iEvtHandler.Animate( targetPoint );
+            }
+        else
+            {
+            MoveOffset(targetPoint, ETrue);
+            iEvtHandler.StopAnimation();
+            }
+        if ( aForceRedraw )
+            {
+            iParent.DrawDeferred();
+            iGrid->DrawNow();
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::HandleAppKey
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::HandleAppKey(TInt aType)
+    {
+    if ( iArray.Count() )
+        {
+        if( aType == KAppKeyTypeShort )
+            {
+            //SwitchToApp( KTsHomescreenUid );
+            TRAP_IGNORE( iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit) );
+            }
+        else if( aType == KAppKeyTypeLong )
+            {
+            // Dismiss task switcher
+            TRAP_IGNORE( iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit) );
+            }
+        }
+    else
+        {
+        TRAP_IGNORE( iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit) );
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::MoveOffset
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::MoveOffset(const TPoint& aPoint, TBool aDrawNow)
+    {
+    if( iHandlePointerCandidate )
+        {
+		//pointer was pressed and it's being waiting for handling
+        return;
+        }
+
+    //postpone center item request in case of being moved
+    if(iUpdateGridTimer->IsActive())
+    	{
+    	iUpdateGridTimer->Cancel();
+		iUpdateGridTimer->After(KUpdateGridTime);
+    	}
+    
+    if ( aDrawNow )
+        {
+        TInt currentXPos = aPoint.iX;
+        currentXPos -= Rect().Width() / 2;
+        TRect gridViewRect = Rect();
+        gridViewRect.iTl.iX = -currentXPos;
+        // Take edge offset into account
+        gridViewRect.iTl.iX += Rect().iTl.iX;
+        if(GridItemCount() && GridItemCount() <= iMaxItemsOnScreen)
+            {
+            // Center view
+            gridViewRect.iTl.iX += ( Rect().Width() - GridItemCount() * iGridItemWidth ) / 2;
+            }
+        //iParent.DrawDeferred();
+        iGrid->DrawDeferred();
+        iGrid->SetRect( gridViewRect );
+        iLogicalViewPosOffset = 0;
+        }
+    else
+        {
+        // Update logical view position
+        iLogicalViewPosOffset = aPoint.iX - ViewPos().iX;
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::Tap
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::TapL(const TPoint& aPoint)
+    {
+    CancelLongTapAnimation();
+    
+    if(!iHandlePointerCandidate)
+        {
+        return;
+        }
+    
+    if(Rect().Contains(aPoint) && iArray.Count())
+        {
+        //provide tap pointer event to grid
+        iGrid->HandlePointerEventL(iTapEvent);
+        iHighlightTimer->Cancel();
+        iHighlightTimer->After(KHighlighActivationTime);
+        }
+    else
+        {
+        //move task switcher to background
+        iEikonEnv->EikAppUi()->HandleCommandL(EAknSoftkeyExit);
+        }
+	iHandlePointerCandidate = EFalse;
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::LongTap
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::LongTapL(const TPoint& aPoint)
+    {
+    CancelLongTapAnimation();
+    
+    if(!iHandlePointerCandidate)
+        {
+        return;
+        }
+    
+    TInt index(KErrNotFound);
+    if( iGrid->GridView()->XYPosToItemIndex(aPoint,index) && iArray.Count() )
+        {
+        iGrid->SetCurrentItemIndex(index);
+        SaveSelectedIndex();
+        if ( !ShowPopupL(iSavedSelectedIndex, aPoint) )
+            {
+            iActivateOnPointerRelease = aPoint;
+            }
+        iGrid->ShowHighlight();
+        DrawNow();
+        }
+	iHandlePointerCandidate = EFalse;
+    }
+
+// --------------------------------------------------------------------------
+// CTsFastSwapArea::DragL
+// --------------------------------------------------------------------------
+//
+void CTsFastSwapArea::DragL(
+    const MAknTouchGestureFwDragEvent& aEvent)
+    {
+    CancelLongTapAnimation();
+    // Reset activation point
+    iActivateOnPointerRelease = TPoint();
+	iHandlePointerCandidate = EFalse;
+	if( aEvent.State() == EAknTouchGestureFwStop)
+		{
+		CenterItem( KUpdateGridTime );
+		}
+
+    iGrid->HideHighlight();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TSize CTsFastSwapArea::ViewSize()
+    {
+    return TSize(Rect().Width(), Rect().Height());  
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::Stop
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::Stop()
+    {    
+    CenterItem( KUpdateGridTime );
+    DrawDeferred();
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewSize
+// -----------------------------------------------------------------------------
+//
+TPoint CTsFastSwapArea::ViewPos() const
+    {
+    TPoint retVal;
+    retVal.iY = iGrid->Rect().iTl.iY + Rect().Height() / 2;
+    retVal.iX = - (iGrid->Rect().iTl.iX - Rect().iTl.iX) + Rect().Width() / 2 ;
+    TInt gridItemCount = iGrid->Model()->ItemTextArray()->MdcaCount();
+    if(gridItemCount && gridItemCount <= iMaxItemsOnScreen)
+        {
+        // View centered
+        retVal.iX += ( Rect().Width() - gridItemCount * iGridItemWidth ) / 2;
+        }
+    retVal.iX += iLogicalViewPosOffset;
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ItemPosition
+// -----------------------------------------------------------------------------
+//
+TPoint CTsFastSwapArea::ItemViewPosition( TInt aItemIdx )
+    {
+    TPoint retVal = Rect().iTl;
+    if ( aItemIdx < 0 )
+        {
+        // No items
+        retVal.iX = 0;
+        }
+    else if ( aItemIdx == 0 )
+        {
+        // First item
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            if ( GridItemCount() > iMaxItemsOnScreen )
+                {
+                retVal.iX = GridWorldSize().iWidth - Rect().Width();
+                }
+            else
+                {
+                retVal.iX = 0;
+                }
+            }
+        else // normal layout
+            {
+            retVal.iX = 0;
+            }
+        }
+    else if ( aItemIdx == GridItemCount() - 1 )
+        {
+        // Last item selected
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            retVal.iX = 0;
+            }
+        else // normal layout
+            {
+            if ( GridItemCount() > iMaxItemsOnScreen )
+                {
+                retVal.iX = GridWorldSize().iWidth - Rect().Width();
+                }
+            else
+                {
+                retVal.iX = 0;
+                }
+            }
+        }
+    else
+        {
+        // Middle item
+        TInt screenMiddleItemOffset = ( Rect().Width() - iGridItemWidth ) / 2;
+        if( AknLayoutUtils::LayoutMirrored() )
+            {
+            retVal.iX = iGridItemWidth * ( GridItemCount() - 1 - aItemIdx ) - screenMiddleItemOffset;
+            retVal.iX += ( GridItemCount() - 1 - aItemIdx ) * iGridItemGap;
+            }
+        else // normal layout
+            {
+            retVal.iX = iGridItemWidth * aItemIdx - screenMiddleItemOffset;
+            retVal.iX += iGridItemGap * aItemIdx;
+            }
+        if ( retVal.iX < 0 )
+            {
+            retVal.iX = 0;
+            }
+        else if ( retVal.iX + Rect().Width() > GridWorldSize().iWidth )
+            {
+            retVal.iX = GridWorldSize().iWidth - Rect().Width();
+            }
+        }
+    
+    // Return middle of the view rectangle
+    retVal.iX += Rect().Width() / 2;
+    
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::ViewToVisibleItem
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::ViewToVisibleItem( const TPoint aViewPos )
+    {
+    TInt retVal(0);
+    TPoint absViewPos = aViewPos;
+    absViewPos.iX -= Rect().Width() / 2;
+    if ( absViewPos.iX < 0 )
+        {
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // View crossed left border of grid world rect, last item selected
+            retVal = GridItemCount() - 1;
+            }
+        else // normal layout
+            {
+            // View crossed left border of grid world rect, first item selected
+            retVal = 0;
+            }
+        }
+    else if ( absViewPos.iX + Rect().Width() > GridWorldSize().iWidth )
+        {
+        if ( AknLayoutUtils::LayoutMirrored() )
+            {
+            // View crossed right border of grid world rect, first item selected
+            retVal = 0;
+            }
+        else // normal layout
+            {
+            // View crossed right border of grid world rect, last item selected
+            retVal = GridItemCount() - 1;
+            }
+        }
+    else
+        {
+        TInt retItemPosX(0);
+        TInt offsetCheck = GridWorldSize().iWidth;
+        // View inside of grid world rect
+        for ( TInt i = 0 ; i < GridItemCount(); i++ )
+            {
+            TInt itemPosX = ItemViewPosition( i ).iX;
+            TInt offset = aViewPos.iX - itemPosX;
+            if ( Abs( offset ) <= offsetCheck )
+                {
+                offsetCheck = Abs( offset );
+                retVal = i;
+                retItemPosX = itemPosX;
+                }
+            else
+                {
+                break;
+                }
+            }
+        // Check if item is fully visible. If not
+        // return next one if possible
+        if ( retItemPosX - iGridItemWidth / 2 < absViewPos.iX &&
+             retVal + 1 < GridItemCount() )
+            {
+            retVal++;
+            }
+        }
+    
+    return retVal;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::LaunchPopupFeedback
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::LaunchPopupFeedback()
+    {
+    if ( AknLayoutUtils::PenEnabled() )
+        {
+        MTouchFeedback* feedback = MTouchFeedback::Instance();
+        if ( feedback )
+            {
+            TTouchLogicalFeedback fbLogicalType = ETouchFeedbackPopUp;
+            if ( CAknTransitionUtils::TransitionsEnabled(
+                 AknTransEffect::EComponentTransitionsOff ) )
+                {
+                fbLogicalType = ETouchFeedbackIncreasingPopUp;
+                }
+            feedback->InstantFeedback( this,
+                                       fbLogicalType,
+                                       ETouchFeedbackVibra,
+                                       TPointerEvent() );
+            }
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::GetCurrentScreenOrientation
+// -----------------------------------------------------------------------------
+//
+TInt CTsFastSwapArea::GetCurrentScreenOrientation()
+    {
+    TPixelsAndRotation availableRect;
+    iEikonEnv->ScreenDevice()->GetDefaultScreenSizeAndRotation(availableRect);
+    return availableRect.iPixelSize.iWidth > availableRect.iPixelSize.iHeight;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::GetVariety
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::GetVariety( TInt& aVariety )
+    {
+    aVariety = Layout_Meta_Data::IsLandscapeOrientation() ? 1 : 0;
+    TBool foreground = static_cast<CTsAppUi*>(iEikonEnv->AppUi())->IsForeground();
+    if ( foreground )
+        {
+        TInt screenOrientation = GetCurrentScreenOrientation();
+        if ( aVariety != screenOrientation )
+            {
+            aVariety = screenOrientation;
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::IsAppClosing
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::IsAppClosing( TInt aWgId )
+    {
+    TBool retVal(EFalse);
+    if ( iIsClosing.Count() )
+        {
+        TInt idx = iIsClosing.Find(aWgId);
+        retVal = idx != KErrNotFound;
+        if ( retVal )
+            {
+            iIsClosing.Remove(idx);
+            }
+        else if ( iWidgetClosingCount )
+            {
+            retVal = ETrue;
+            iWidgetClosingCount--;
+            }
+        }
+    return retVal;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::WgOnTaskList
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::WgOnTaskList( TInt aWgId )
+    {
+    TBool retVal(EFalse);
+    TInt appCount = iArray.Count();
+    
+    TApaTaskList taskList( iEikonEnv->WsSession() );
+    TApaTask task = taskList.FindApp( KTsHomescreenUid );
+    TInt homescrWgId = task.WgId();
+    
+    if ( iPrevAppCount != appCount )
+        {
+        for ( TInt i = 0; i < iArray.Count(); i++ )
+            {
+            TInt wgId = iArray[i]->WgId();
+            if ( wgId == aWgId ||
+                 homescrWgId == aWgId )
+                {
+                retVal = ETrue;
+                }
+            }
+        }
+    else if ( aWgId == homescrWgId )
+        {
+        retVal = ETrue;
+        }
+    iPrevAppCount = appCount;
+    return retVal;
+    }
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::CancelLongTapAnimation
+// -----------------------------------------------------------------------------
+//
+void CTsFastSwapArea::CancelLongTapAnimation(TBool aDisablePopup)
+    {
+    iLongTapAnimationRunning = EFalse;
+    iLongTapAnimationTimer->Cancel();
+    if ( iLongTapAnimation )
+        {
+        iLongTapAnimation->HideAnimation();
+        delete iLongTapAnimation;
+        iLongTapAnimation = NULL;
+        }
+    if( aDisablePopup )
+        {
+        TRAP_IGNORE( 
+        static_cast<CTsAppUi*>(iEikonEnv->AppUi())->DisablePopUpL() );
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTsFastSwapArea::LongTapAnimForPos
+// -----------------------------------------------------------------------------
+//
+TBool CTsFastSwapArea::LongTapAnimForPos( const TPoint& aHitPoint )
+    {
+    if ( Rect().Contains(aHitPoint) )
+        {
+        TInt itemIdx;
+        TBool isItemHit = iGrid->GridView()->XYPosToItemIndex( aHitPoint, itemIdx );
+        if ( isItemHit && ( CanClose( itemIdx ) || CanCloseAll( itemIdx ) ) )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// End of file