/*
* 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:
*
*/
#include <graphics/wsgraphicscontext.h>
#include <graphics/wsgraphicdrawerinterface.h>
#include <bitstd.h>
#include <fbs.h>
#include <gdi.h>
#include <e32math.h>
#include <e32hashtab.h>
#include <uiacceltk/HuiUtil.h>
#include "alfhierarchymodel.h"
#include "alfstreamerconsts.h"
#include "alfstreamerserver.h"
#include "alfwindowmanager.h"
#include "alfstreamerbridge.h"
#include "alfwindow.h"
#include "alflogger.h"
#ifdef ALF_DEBUG_TRACK_DRAWING
#include "alfcommanddebug.h"
#endif
#include "alfnodes.h"
#include "huiwscanvascommands.h"
#include "mwsgraphicscontexttobitgdimappings.h"
const TInt KChunkCommitBatchSize = 10000;
const TInt KChunkMaxSize = 500000;
const TInt KFrameOffsetTemplate = 12345678;
// ---------------------------------------------------------------------------
// NewL
// ---------------------------------------------------------------------------
//
CAlfHierarchyModel* CAlfHierarchyModel::NewL(CAlfStreamerServer& aServer)
{
CAlfHierarchyModel* self = new(ELeave)CAlfHierarchyModel(aServer);
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop(self);
return self;
}
// ---------------------------------------------------------------------------
// ConstructL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ConstructL()
{
iWindowPos = TPoint(0, 0 );
iSema.CreateLocal();
if (iServer.Bridge())
{
iServer.Bridge()->SetBatchObserver(this);
}
#ifdef ALF_DEBUG_TRACK_DRAWING
iCommandDebugger = CAlfCommandDebug::NewL();
#endif
#ifdef USE_MODULE_TEST_HOOKS_FOR_ALF
// Initiliaze global data in TLS and Open global module testing chunk and mutex
User::LeaveIfError(Dll::SetTls(new(ELeave) CAlfModuleTestDataControl()));
User::LeaveIfError(AMT_CONTROL()->OpenGlobalObjects());
#endif
}
// ---------------------------------------------------------------------------
// AppendScreenL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::AppendScreen( TInt aScreenNumber )
{
__ALFLOGSTRING1("CAlfHierarchyModel::AppendScreenL( %d )", aScreenNumber );
if ( aScreenNumber > 0 ) // first display comes with the package. only the following are created when requested
{
iServer.Bridge()->AddData( EAlfDSCreateNewDisplay, aScreenNumber, 0, NULL );
}
}
// ---------------------------------------------------------------------------
// RemoveScreenL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::RemoveScreen( TInt aScreenNumber )
{
if ( aScreenNumber < 1 )
{
// The main display cannot be removed.
return;
}
__ALFLOGSTRING1("CAlfHierarchyModel::RemoveDisplayL( %d )", aScreenNumber );
// NOTE & TODO: This works fine, if we are removing the last added display. If we happen to remove display in the middle,
// then referring to displays by their indeces would be a major problem
// TODO: Who destroyes the nodes on this display? wserv?
iServer.Bridge()->AddData( EAlfDSDestroyDisplay, aScreenNumber, 0, NULL );
}
// ---------------------------------------------------------------------------
// destructor
// ---------------------------------------------------------------------------
//
CAlfHierarchyModel::~CAlfHierarchyModel()
{
// we do not complete pending messages
iPendingAlfWindowDataMessages.Close();
iNodeHashArray.Close();
if (iServer.Bridge())
{
iServer.Bridge()->SetBatchObserver(0);
}
delete iPeriodic;
iSema.Close();
if(iStream)
{
iStream->Close();
delete iStream;
iStream = NULL;
}
iChunk.Close();
#ifdef ALF_DEBUG_TRACK_DRAWING
delete iCommandDebugger;
#endif
#ifdef USE_MODULE_TEST_HOOKS_FOR_ALF
delete AMT_CONTROL();
Dll::FreeTls();
#endif
}
// ---------------------------------------------------------------------------
// ReleaseSemaphor
// ---------------------------------------------------------------------------
//
void ReleaseSemaphor(TAny* aAlfHierarchyModel)
{
CAlfHierarchyModel* me = (CAlfHierarchyModel*)aAlfHierarchyModel;
me->DoReleaseSemaphor();
}
// ---------------------------------------------------------------------------
// DoReleaseSemaphor
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoReleaseSemaphor()
{
iSema.Signal();
}
// ---------------------------------------------------------------------------
// RequestPacketEndCallback
//
// This is used to notify when certain offset in the chunk is freed. To avoid
// excessive notifications (and callbacks), skip some of the notifications.
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::RequestPacketEndCallback( TInt aOffset )
{
if ( aOffset > iPreviousCallbackOffset + KChunkCommitBatchSize || aOffset < iPreviousCallbackOffset )
{
iPreviousCallbackOffset = aOffset;
iServer.Bridge()->RequestCommandReadNotification( aOffset );
}
}
// ---------------------------------------------------------------------------
// RequestFrameEndCallback
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::RequestFrameEndCallback( )
{
__ALFLOGSTRING( "CAlfHierarchyModel::RequestFrameEndCallback" );
iServer.Bridge()->StartNewBlock();
}
// ---------------------------------------------------------------------------
// HandleMessageL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::HandleMessageL( const RMessage2& aMessage )
{
iSema.Wait();
CleanupStack::PushL(TCleanupItem(ReleaseSemaphor, this));
TBool doComplete= EFalse;
// __ALFLOGSTRING1( "CAlfHierarchyModel::HandleMessageL %d", aMessage.Function() );
switch (aMessage.Function())
{
case EAlfBridgerRequestDataBlock:
{
ShareChunkL( aMessage );
return;
}
case EDsNotifyNativeWindowData:
{
User::Leave(KErrNotSupported);
return;
}
case EAlfBridgerAsyncronousData:
{
if ( iChunk.Handle() )
{
ExecuteCommandsL();
if ( iBatchAlreadyCommited )
{
// This may happen, if alfstreamerbridge happens to process the commands (containing the EAlfCommitBatch)
// before this asyncronous request is received.
__ALFLOGSTRING("Batch already completed. Complete immediately");
aMessage.Complete( EAlfBridgerAsyncronousData );
iBatchAlreadyCommited = EFalse;
}
else
{
SetSynchMessage(&aMessage);
}
}
break;
}
case EAlfBridgerBlindSend:
{
ExecuteCommandsL();
CleanupStack::PopAndDestroy(); // releases iSema
aMessage.Complete( EAlfBridgerBlindSend );
return;
}
case EAlfBridgerSendChunk:
{
OpenChunkL( aMessage );
aMessage.Complete( EAlfBridgerSendChunk );
return;
}
case EAlfSynchronize:
{
iServer.Bridge()->AddData( EAlfDSSynchronize, aMessage.Int0() );
aMessage.Complete( KErrNone );
}
break;
default:
{
doComplete= ETrue;
__ALFLOGSTRING("CAlfHierarchyModel::HandleMessageL, default case reached.");
break;
}
}
if (doComplete && !aMessage.IsNull())
{
aMessage.Complete(KErrNotSupported);
}
CleanupStack::PopAndDestroy(); // releases iSema
}
// ---------------------------------------------------------------------------
// ShareChunkL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ShareChunkL( const RMessage2& aMessage )
{
if ( !iChunk.Handle() )
{
// For security reasons, alfserver owns the chunk. Because it is nameless, it cannot be accessed
// unless a handle to the chunk is given by alfserver
//
// TODO:CHECK what if somebody else wants to send EAlfBridgerRequestDataBlock. Currently we are giving the chunk
// to anybody who connects to the server.
iChunk.CreateDisconnectedGlobal( KNullDesC, 0, KChunkMaxSize, KChunkMaxSize ); //CreateDisconnectedGlobal
iChunkHeader = reinterpret_cast<TChunkHeader*>(iChunk.Base());
memset( iChunkHeader, 0, sizeof( TChunkHeader ) );
}
TInt screenNumber = aMessage.Int1();
TPckg<TInt> pkgLength( KChunkMaxSize );
AppendScreen( screenNumber );
aMessage.WriteL(0, pkgLength );
aMessage.Complete( iChunk );
if ( iStream )
{
iStream->Close();
}
else
{
iStream = new(ELeave)RMemReadStream;
}
iStream->Open( iChunk.Base() + sizeof( TChunkHeader), KChunkMaxSize );
CleanupStack::PopAndDestroy(); // releases iSema
}
// ---------------------------------------------------------------------------
// ShareChunkL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::OpenChunkL( const RMessage2& aMessage )
{
TInt size = aMessage.Int0();
TInt32 handle = aMessage.Int1();
TBool openForReading = aMessage.Int2();
iCacheChunks.Insert( handle, RChunk() );
iCacheChunks.Find( handle )->SetHandle( aMessage.Int1() );
iCacheChunks.Find( handle )->Open( aMessage, 1, EFalse, EOwnerProcess );
if ( openForReading )
{
if (iStream)
{
iStream->Close();
}
else
{
iStream = new(ELeave)RMemReadStream;
}
TUint8* base = iCacheChunks.Find( handle )->Base();
iStream->Open( base + sizeof( TChunkHeader), size );
__ALFLOGSTRING1("Chunk in use %d", iChunkInUse );
iChunkInUse = handle;
iChunkHeader = reinterpret_cast<TChunkHeader*>(base);
}
CleanupStack::PopAndDestroy(); // releases iSema
}
// ---------------------------------------------------------------------------
// CloseChunkL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::CloseChunk( TInt32 aChunkHandle )
{
__ALFLOGSTRING1("CAlfHierarchyModel::CloseChunkL: closing %d", aChunkHandle );
RChunk* chunk = iCacheChunks.Find( aChunkHandle );
iCacheChunks.Remove( aChunkHandle );
if ( chunk )
{
chunk->Close();
}
else
{
__ALFLOGSTRING1( "CAlfHierarchyModel::CloseChunkL - Warning: chunk %d not found!", aChunkHandle );
}
}
// ---------------------------------------------------------------------------
// ReadEndMarkerL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ReadEndMarkerL()
{
TUint8 marker = iStream->ReadInt8L();
ASSERT( marker == EAlfCommandEndMarker ) ; // endmarker
}
// ---------------------------------------------------------------------------
// ReadRectL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ReadRectL( TRect& aRect, RMemReadStream* aStream )
{
aStream->ReadL( (TUint8*)&(aRect.iTl.iX), sizeof( TRect) );
}
// ---------------------------------------------------------------------------
// ReadRegionL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ReadRegionL( RMemReadStream* aStream, RRegion& aRegion, TPoint aWindowPos )
{
aRegion.Clear();
TRect rect;
TInt count = aStream->ReadInt32L();
for (TInt i = 0 ; i < count ; i++ )
{
ReadRectL( rect, aStream );
rect.Move(-aWindowPos);
aRegion.AddRect( rect );
}
}
// ---------------------------------------------------------------------------
// ExecuteCommandsL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ExecuteCommandsL( )
{
if ( !iStream )
{
return;
}
TInt offset = iStream->Source()->TellL( MStreamBuf::ERead ).Offset();
#ifdef _ALF_LOGGING
TInt commandCount(0);
TSgcCanvasCommands previousCommand;
#endif
TSgcCanvasCommands command = EAlfCommandNotInitialized;
TTime beginTime;
beginTime.HomeTime();
__ALFLOGSTRING1( "CAlfHierarchyModel::ExecuteCommandsL - Committed write offset: %d", iChunkHeader->iCommittedWriteOffset );
while( iChunkHeader->iCommittedWriteOffset != offset )
{
#ifdef _ALF_LOGGING
previousCommand = command;
#endif
TRAPD( err,
command = (TSgcCanvasCommands)iStream->ReadUint8L();
iScreenNumber = iStream->ReadUint8L();
);
if ( err != KErrNone )
{
#ifdef _ALF_LOGGING
__ALFLOGSTRING3("CAlfHierarchyModel::ExecuteCommandsL - Cmd: %d, Previous Cmd: %d, Count: %d..", command, previousCommand, commandCount );
#endif
__ALFLOGSTRING2("..CAlfHierarchyModel::ExecuteCommandsL - Offset: %d, LEAVE WITH ERROR: %d", offset, err );
}
#ifdef ALF_DEBUG_TRACK_DRAWING
commandCount++;
iUsedCommands[command]++;
iCommandDebugger->SetDescription( command );
__ALFLOGSTRING3("CAlfHierarchyModel::ExecuteCommandsL (%d) %S offset: %d,", command, &iCommandDebugger->Text(), offset );
#endif
switch ( command )
{
case EAlfSetWindowId:
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNodeVisual* node = (CAlfNodeVisual*)FindNode( nodeId );
if ( node )
{
#ifdef ALF_DEBUG_TRACK_DRAWING
if (node->iId == iSearchNode || node->Tracking() )
{
RDebug::Print( _L( "CAlfHierarchyModel::ExecuteCommandsL - Tracking"));
}
#endif
#ifdef ALF_DEBUG_PRINT_NODE_INFO
_LIT( KText, "Drawing");
// node->PrintInfo(0, node, TPtrC(KText) , iSearchNode);
#endif
node->DrawWindowFrameL( *iStream );
}
else
{
ProcessUnknownNodeDrawingL( *iStream );
}
break;
}
case EAlfNodeCreated:
{
DoNodeCreatedL();
break;
}
case EAlfNodeReleased:
{
DoNodeReleasedL();
break;
}
case EAlfNodeActivated:
{
DoNodeActivatedL();
break;
}
case EAlfNodeExtentChanged:
{
DoNodeExtentChangedL();
break;
}
case EAlfNodeSiblingOrderChanged:
{
DoNodeSiblingOrderChangedL();
break;
}
case EAlfNodeFlagChanged:
{
DoNodeFlagChangedL();
break;
}
case EAlfNodeFadeCountChanged:
{
DoNodeFadeCountChangedL();
break;
}
case EAlfNodeFadeAllChildren:
{
DoNodeFadeAllChildrenL();
break;
}
case EAlfNodeTransparentRegionChanged:
{
DoNodeTransparentRegionChangedL();
break;
}
case EAlfNodeLayerAdded:
{
DoNodeLayerAddedL();
break;
}
case EAlfNodeLayerExtentChanged:
{
DoNodeLayerExtentChangedL();
break;
}
case EAlfNodeLayerUsesAlphaFlagChanged:
{
DoNodeLayerUsesAlphaFlagChangedL();
break;
}
case EAlfNodeMovedToWindowGroup:
{
DoNodeMovedToWindowGroupL();
break;
}
case EAlfNodeWindowGroupChained:
{
DoNodeWindowGroupChainedL();
break;
}
case EAlfNodeWindowGroupChainBrokenAfter:
{
DoNodeWindowGroupChainBrokenAfterL();
break;
}
case EAlfWrap:
{
ReadEndMarkerL(); // futile, but just in case somet
iStream->Source()->SeekL( MStreamBuf::ERead, TStreamPos(0));
iChunkHeader->iReadOffset = 0;
break;
}
case EAlfNodeAttributeChanged: // currently only textcursor may receive these events
{
DoNodeAttributeChangedL();
break;
}
case EAlfNodeSetWindowArea:
{
DoNodeSetWindowAreaL();
}
break;
case EAlfCommitBatch:
{
RequestFrameEndCallback();
break;
}
#ifdef ALF_DEBUG_TRACK_DRAWING
case EAlfDebugTrackNode:
{
DoNodeDebugTrackL();
break;
}
#endif
case EAlfDestroyChunk:
{
TInt chunkId = iStream->ReadInt32L();
iServer.Bridge()->AddData( EAlfReleaseTemporaryChunk, chunkId );
break;
}
case EAlfJumpToAnotherChunk:
{
RequestPacketEndCallback( offset );
TInt32 readChunkId = iStream->ReadInt32L();
TInt size = iStream->ReadInt32L();
ReadEndMarkerL();
// __ALFLOGSTRING1("Next chunk: %d, size: %d, previous chunk: %d"), readChunkId, size, iChunkInUse );
if ( readChunkId == 0 )
{
iChunkHeader = reinterpret_cast<TChunkHeader*>(iChunk.Base());
iStream->Close();
iStream->Open( iChunk.Base() + sizeof( TChunkHeader), KChunkMaxSize );
iStream->Source()->SeekL( MStreamBuf::ERead, TStreamPos(0));
}
else
{
iStream->Close();
iStream->Open( iCacheChunks.Find( readChunkId )->Base() + sizeof( TChunkHeader), size );
iChunkHeader = reinterpret_cast<TChunkHeader*>(iCacheChunks.Find( readChunkId )->Base());
}
iChunkInUse = readChunkId;
break;
}
default:
{
__ALFLOGSTRING("CAlfHierarchyModel::ExecuteCommandsL, off track");
#ifdef _ALF_LOGGING
__ALFLOGSTRING3("CAlfHierarchyModel::ExecuteCommandsL, off track - Cmd: %d, Previous Cmd: %d, Count: %d..", command, previousCommand, commandCount );
#endif
__ALFLOGSTRING1("..CAlfHierarchyModel::ExecuteCommandsL, unrecoverable error : HALTING at offset: %d", offset );
USER_INVARIANT();
break;
}
}
ReadEndMarkerL();
offset = iStream->Source()->TellL( MStreamBuf::ERead ).Offset();
RequestPacketEndCallback( offset );
//__ALFLOGSTRING1("end offset %d offset %d, command %d"), aEndOffset, offset, command );
};
iFrame++;
}
// ---------------------------------------------------------------------------
// BridgerCallback
// This is called by CAlfStreamBridge when EAlfCommitBatch is processed.
//
// Note: This call comes from another thread, Alf server thread. Beware that
// Alf streamer/decoder server thread might access the class data
// concurrently!
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::BridgerCallback( TInt aOp, TInt aInt )
{
// hackish, just do the panic release for window server
// Trying to mimize changes on existing logic
if (aOp == KRELEASEWINDOWSERVER)
{
__ALFLOGSTRING1("CAlfHierarchyModel::BridgerCallback, iMessage is null: %d", iMessage.IsNull());
if (!iMessage.IsNull())
{
__ALFLOGSTRING("CAlfHierarchyModel::BridgerCallback, emergency releasing of window server");
iMessage.Complete(EAlfBridgerAsyncronousData);
iDidForcedComplete = ETrue;
}
else if (aInt == KRELEASEDBEFOREQUEUE)
{
iBatchAlreadyCommited = ETrue;
}
return;
}
switch( aOp )
{
case EAlfDSGetAlfNativeWindowData:
{
iSema.Wait();
// Complete the pending message
RMessage2* rsMessage = (RMessage2*)aInt;
for (TInt i = 0; i < iPendingAlfWindowDataMessages.Count(); i++)
{
if (&(iPendingAlfWindowDataMessages[i]) == rsMessage)
{
// Complete the message to RS
rsMessage->Complete(KErrNone);
iPendingAlfWindowDataMessages.Remove(i);
break;
}
}
iSema.Signal();
break;
}
case EAlfRequestCommandReadNotification:
{
if (iChunkHeader)
{
iChunkHeader->iReadOffset = aInt; // last read offset
}
// TODO: If you can absolute guaranteen to count the available space correctly, then this can also complete iSpaceNotificationMessage
break;
}
case EAlfRequestCommitBatch:
{
__ALFLOGSTRING1("CAlfHierarchyModel::BridgerCallback, iMessage.IsNull %d", iMessage.IsNull());
if ( iMessage.IsNull())
{
if (!iDidForcedComplete)
{
__ALFLOGSTRING("request for this message has not arrived. complete on arrival");
iBatchAlreadyCommited = ETrue;
}
}
else
{
iBatchAlreadyCommited = EFalse;
iMessage.Complete(EAlfBridgerAsyncronousData);
}
iDidForcedComplete = EFalse;
break;
}
case EAlfReleaseTemporaryChunk:
{
CloseChunk( aInt );
break;
}
default:
{
USER_INVARIANT();
}
}
}
// ---------------------------------------------------------------------------
// DoNodeCreatedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeCreatedL()
{
#ifdef ALF_DEBUG_TRACK_DRAWING
TBool trackThisNode(EFalse);
#endif
CAlfNode* node = NULL;
// Nodes add themself to iNodeStructArray, which "owns" the nodes. Nodes are created and destroyed only if requested by the Wserv
MWsWindowTreeNode::TType nodeType = (MWsWindowTreeNode::TType)iStream->ReadInt32L();
switch (nodeType)
{
case MWsWindowTreeNode::EWinTreeNodeClient:
{
node = CAlfNodeWindow::NewL( this, iStream, iScreenNumber );
break;
}
case MWsWindowTreeNode::EWinTreeNodeRoot:
{
node = CAlfNodeRoot::NewL( this ,iStream, iScreenNumber );
iRootNode = (CAlfNodeRoot*)node;
break;
}
case MWsWindowTreeNode::EWinTreeNodeGroup:
{
node = CAlfNodeGroup::NewL( this, iStream, iScreenNumber );
break;
}
case MWsWindowTreeNode::EWinTreeNodeAnim:
{
node = CAlfNodeAnim::NewL(this, iStream, iScreenNumber );
break;
}
case MWsWindowTreeNode::EWinTreeNodeSprite:
{
node = CAlfNodeSprite::NewL( this, iStream, iScreenNumber );
break;
}
case MWsWindowTreeNode::EWinTreeNodeStandardTextCursor:
{
node = CAlfNodeTextCursor::NewL( this, iStream, iScreenNumber );
break;
}
default:
{
__ALFLOGSTRING1("CAlfHierarchyModel::DoNodeCreatedL, unknown node type: %i", nodeType);
break;
}
}
// Note to Debuggers
// You can track certain type of nodes and their draw buffers by changing the trackThisNode value to 1.
// Then enable breakpoints in
// some places marked in code using the ALF_DEBUG_TRACK_DRAWING and HUI_DEBUG_TRACK_DRAWING . The macro
// must be enabled in
// alfappservercore.mmp
// coretoolkit.mmp and
// alfrenderstageplugin.mmp
#ifdef ALF_DEBUG_TRACK_DRAWING
if ( trackThisNode )
{
node->SetTracking( trackThisNode );
}
#endif
#ifdef ALF_DEBUG_PRINT_NODE_INFO
if ( node )
{
RDebug::Print(_L("DoNodeCreatedL"));
iRootNode->iLogging = 1;
CAlfNode::PrintNodeTree(iRootNode, node->iId);
iRootNode->iLogging = 0;
//CAlfNode::PrintInfo( 0, (CAlfNodeVisual*)node, TPtrC(KText) , iSearchNode);
}
#endif
AMT_INC_COUNTER_IF(node && (nodeType==MWsWindowTreeNode::EWinTreeNodeClient), iWindowNodeCount );
AMT_INC_COUNTER_IF(node && (nodeType==MWsWindowTreeNode::EWinTreeNodeGroup), iWindowGroupNodeCount );
AMT_INC_COUNTER_IF(node, iTotalNodeCount );
AMT_MAP_INC_VALUE_IF( node && nodeType == MWsWindowTreeNode::EWinTreeNodeClient,
iIntMap, node->iId, EAlfModuleTestTypeHierarchyModelCreateWindow );
AMT_MAP_INC_VALUE_IF( node && nodeType == MWsWindowTreeNode::EWinTreeNodeGroup,
iIntMap, node->iId, EAlfModuleTestTypeHierarchyModelCreateWindowGroup );
}
// ---------------------------------------------------------------------------
// DoNodeReleasedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeReleasedL()
{
MWsWindowTreeNode::TType nodeType = (MWsWindowTreeNode::TType)iStream->ReadInt32L();
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNode* node = FindNode( nodeId );
#ifdef ALF_DEBUG_PRINT_NODE_INFO
if ( node )
{
//_LIT(KText,"DoNodeReleasedL");
CAlfNode::PrintNodeTree(iRootNode, node->iId);
// CAlfNode::PrintInfo( 0, (CAlfNodeVisual*)node, TPtrC(KText) , iSearchNode);
}
#endif
if ( node )
{
delete node;
}
else
{
USER_INVARIANT();
}
AMT_DEC_COUNTER_IF(node && (nodeType==MWsWindowTreeNode::EWinTreeNodeClient), iWindowNodeCount );
AMT_DEC_COUNTER_IF(node && (nodeType==MWsWindowTreeNode::EWinTreeNodeGroup), iWindowGroupNodeCount );
AMT_DEC_COUNTER_IF(node, iTotalNodeCount );
AMT_MAP_INC_VALUE_IF( node && nodeType == MWsWindowTreeNode::EWinTreeNodeClient,
iIntMap, nodeId, EAlfModuleTestTypeHierarchyModelReleaseWindow );
AMT_MAP_INC_VALUE_IF( node && nodeType == MWsWindowTreeNode::EWinTreeNodeGroup,
iIntMap, nodeId, EAlfModuleTestTypeHierarchyModelReleaseWindowGroup );
}
// ---------------------------------------------------------------------------
// DoNodeActivatedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeActivatedL()
{
TInt nodeType = iStream->ReadInt32L();
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNode* node = FindNode( nodeId );
if ( node )
{
node->ActivateNode();
}
else
{
USER_INVARIANT();
}
AMT_INC_COUNTER_IF( node && (nodeType==MWsWindowTreeNode::EWinTreeNodeClient), iWindowNodeActivatedCount );
AMT_MAP_SET_VALUE_IF( node && nodeType == MWsWindowTreeNode::EWinTreeNodeClient,
iBoolMap, nodeId, ETrue,
EAlfModuleTestTypeHierarchyModelActiveWindow );
}
// ---------------------------------------------------------------------------
// DoNodeExtentChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeExtentChangedL()
{
TRect rect;
ReadRectL( rect, iStream);
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNodeVisual* node = (CAlfNodeVisual*)FindNode( nodeId );
if ( node )
{
node->SetExtent( rect );
}
else
{
USER_INVARIANT();
}
#ifdef ALF_DEBUG_PRINT_NODE_INFO
if ( node )
{
RDebug::Print(_L("Extent changed"));
CAlfNode::PrintNodeTree(iRootNode, node->iId);
//CAlfNode::PrintInfo( 0, (CAlfNodeVisual*)node, TPtrC(KText), iSearchNode);
}
#endif
AMT_INC_COUNTER_IF(node, iNodeExtentChangedCount );
AMT_SET_VALUE_IF(node, iLatestNodeExtentRect, rect );
AMT_MAP_SET_VALUE_IF( node && node->iWindow,
iSizeMap, node->iWindow->WsInfo().iClientSideId.iWindowIdentifer,
rect.Size(), EAlfModuleTestTypeHierarchyModelChangeWindowSize );
AMT_MAP_SET_VALUE_IF( node && node->iWindow,
iPositionMap, node->iWindow->WsInfo().iClientSideId.iWindowIdentifer,
rect.iTl, EAlfModuleTestTypeHierarchyModelChangeWindowPosition );
}
// ---------------------------------------------------------------------------
// DoNodeSiblingOrderChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeSiblingOrderChangedL()
{
TInt newPos = iStream->ReadInt32L();
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNode* node = FindNode( nodeId );
if ( node )
{
AMT_SET_VALUE(iAST_Temp1, node->OrdinalPosition());
node->SiblingOrderChanged( newPos );
AMT_SET_VALUE(iOrdinalChange, node->OrdinalPosition() - AMT_DATA()->iAST_Temp1);
}
else
{
#ifdef _DEBUG
RDebug::Print( _L("Missing a node %d"), nodeId );
#endif
// USER_INVARIANT();
}
#ifdef ALF_DEBUG_PRINT_NODE_INFO
if ( node )
{
RDebug::Print(_L("Sibling order changed"));
CAlfNode::PrintNodeTree(iRootNode, node->iId);
// CAlfNode::PrintInfo( 0, (CAlfNodeVisual*)node, TPtrC(KText), iSearchNode );
}
#endif
}
// ---------------------------------------------------------------------------
// DoNodeFlagChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeFlagChangedL()
{
MWsWindowTreeObserver::TFlags flag = (MWsWindowTreeObserver::TFlags)iStream->ReadUint32L();
TBool newValue = (TBool)iStream->ReadInt32L();
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNode* node = FindNode( nodeId );
if ( node )
{
node->FlagChanged( flag, newValue );
}
else
{
USER_INVARIANT();
}
AMT_INC_COUNTER_IF(node, iTotalNodeFlagChangedCount );
AMT_MAP_SET_VALUE_IF( node && node->iWindow && MWsWindowTreeObserver::EVisible == flag,
iBoolMap,
node->iWindow->WsInfo().iClientSideId.iWindowIdentifer,
newValue,
EAlfModuleTestTypeHierarchyModelChangeWindowVisibility );
}
// ---------------------------------------------------------------------------
// DoNodeFadeAllChildrenL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeFadeAllChildrenL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TBool faded = (TBool)iStream->ReadInt32L();
CAlfNode* node = FindNode( nodeId );
if ( node )
{
node->FadeAllChildren( faded );
}
else
{
USER_INVARIANT();
}
}
// ---------------------------------------------------------------------------
// DoNodeFadeCountChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeFadeCountChangedL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TInt fadeCount = (TInt)iStream->ReadUint32L();
CAlfNode* node = FindNode( nodeId );
if ( node )
{
node->FadeCountChanged( fadeCount );
}
else
{
USER_INVARIANT();
}
}
// ---------------------------------------------------------------------------
// DoNodeTransparentRegionChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeTransparentRegionChangedL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
iStream->ReadInt8L();
RRegion newTransparentRegion;
RRegion newOpaqueRegion;
ReadRegionL( iStream, newTransparentRegion );
iStream->ReadInt8L();
ReadRegionL( iStream, newOpaqueRegion );
// TODO: Implement actions
}
// ---------------------------------------------------------------------------
// DoNodeLayerAddedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeLayerAddedL()
{
DoNodeLayerExtentChangedL();
}
// ---------------------------------------------------------------------------
// DoNodeLayerExtentChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeLayerExtentChangedL()
{
// Set composition surface extent
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TRect extent = TRect(0,0,0,0);
ReadRectL(extent, iStream);
TBool isDSA = (TUint32)iStream->ReadUint32L();
CAlfNodeVisual* node = (CAlfNodeVisual*)FindNode( nodeId );
if ( node && node->Window() )
{
// SetSurfaceExtent is not supported for image visual
node->Window()->SetSurfaceExtent( extent );
if (isDSA)
{
node->Window()->SetLayerUsesAplhaFlag(KWindowIsDSAHost);
}
if (extent.IsEmpty())
{
iServer.ReleasePermissionTokenL(node->iId);
}
else
{
iServer.CreatePermissionTokenL(node->iId,
node->Window()->WsInfo().iClientSideId.iWindowIdentifer,
node->Window()->WsInfo().iClientSideId.iWindowGroupId );
}
}
else if( node ) // this would mean that node has being orphaneded but not yet deleted
{
__ALFLOGSTRING1("CAlfHierarchyModel::DoNodeLayerExtentChangedL node found but window %d was destroyed", nodeId);
}
}
// ---------------------------------------------------------------------------
// DoNodeLayerUsesAlphaFlagChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeLayerUsesAlphaFlagChangedL()
{
// Set composition surface extent
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TBool enabled = (TBool)iStream->ReadInt32L();
CAlfNodeVisual* node = (CAlfNodeVisual*)FindNode( nodeId );
if ( node && node->Window() )
{
// SetLayerUsesAplhaFlag is not supported for image visual
node->Window()->SetLayerUsesAplhaFlag( enabled );
}
else if( node ) // this would mean that node has being orphaneded but not yet deleted
{
__ALFLOGSTRING1("CAlfHierarchyModel::DoNodeLayerUsesAlphaFlagChangedL node found but window %d was destroyed", nodeId);
}
}
// ---------------------------------------------------------------------------
// DoNodeMovedToWindowGroupL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeMovedToWindowGroupL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TUint32 newWindowgroupNode = (TUint32)iStream->ReadUint32L();
CAlfNodeWindow* node = (CAlfNodeWindow*)FindNode( nodeId );
if ( node )
{
node->MoveToWindowGroup( newWindowgroupNode );
}
}
// ---------------------------------------------------------------------------
// DoNodeWindowGroupChainedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeWindowGroupChainedL()
{
TUint32 parentNode = (TUint32)iStream->ReadUint32L();
TUint32 childNode = (TUint32)iStream->ReadUint32L();
CAlfNodeGroup* node = (CAlfNodeGroup*)FindNode( parentNode );
if ( node )
{
node->WindowGroupChained( childNode );
}
}
// ---------------------------------------------------------------------------
// DoNodeWindowGroupChainBrokenAfterL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeWindowGroupChainBrokenAfterL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNodeGroup* node = (CAlfNodeGroup*)FindNode( nodeId );
if ( node )
{
node->GroupChainBrokenAfter();
}
}
// ---------------------------------------------------------------------------
// DoNodeAttributeChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeAttributeChangedL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNodeTextCursor* node = (CAlfNodeTextCursor*)FindNode( nodeId);
if ( node && node->Type() == MWsWindowTreeNode::EWinTreeNodeStandardTextCursor )
{
node->AttributeChangedL( iStream );
#ifdef ALF_DEBUG_PRINT_NODE_INFO
if ( node )
{
//_LIT(KText,"Attribute changed");
//CAlfNode::PrintInfo( 0, (CAlfNodeVisual*)node, TPtrC(KText) , iSearchNode);
//CAlfNode::PrintNodeTree(iRootNode, KText, node->iId);
}
#endif
}
else
{
USER_INVARIANT(); // attribute change for unexpected node type. new code needed!
}
AMT_INC_COUNTER_IF(node, iTotalNodeAttributeChangedCount );
}
// ---------------------------------------------------------------------------
// DoNodeAttributeChangedL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::DoNodeSetWindowAreaL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
CAlfNode* node = FindNode(nodeId);
if ( node && node->Type() == MWsWindowTreeNode::EWinTreeNodeClient )
{
CAlfNodeWindow* w = static_cast<CAlfNodeWindow*>(node);
w->SetWindowAreaL( iStream );
}
else
{
USER_INVARIANT(); // set window area change for unexpected node type. new code needed!
}
}
// ---------------------------------------------------------------------------
// DoNodeWindowGroupChainBrokenAfterL
// ---------------------------------------------------------------------------
//
#ifdef ALF_DEBUG_TRACK_DRAWING
void CAlfHierarchyModel::DoNodeDebugTrackL()
{
TUint32 nodeId = (TUint32)iStream->ReadUint32L();
TBool trackingValue = iStream->ReadUint32L();
CAlfNodeGroup* node = (CAlfNodeGroup*)FindNode( nodeId );
if ( node )
{
node->SetTracking( trackingValue );
}
}
#endif
// ---------------------------------------------------------------------------
// FindNode
// ---------------------------------------------------------------------------
//
CAlfNode* CAlfHierarchyModel::FindNode( TUint32 aWindowId )
{
if ( iPreviouslySearchedNode && iPreviouslySearchedNode->iId == aWindowId )
{
return iPreviouslySearchedNode;
}
CNodeHashStruct* nodeHashStruct = iNodeHashArray.Find( aWindowId );
if (nodeHashStruct)
{
iPreviouslySearchedNode = nodeHashStruct->iNode;
return iPreviouslySearchedNode;
}
return NULL;
}
// ---------------------------------------------------------------------------
// InsertNode
// ---------------------------------------------------------------------------
//
TInt CAlfHierarchyModel::InsertNode( TUint32 aWindowId, CAlfNode* aNode )
{
return iNodeHashArray.Insert( aWindowId, CNodeHashStruct( aNode ));
}
// ---------------------------------------------------------------------------
// RemoveNode
// ---------------------------------------------------------------------------
//
TBool CAlfHierarchyModel::RemoveNode( TUint32 aWindowId )
{
iPreviouslySearchedNode = NULL;
return iNodeHashArray.Remove( aWindowId );
}
// ---------------------------------------------------------------------------
// RemoveAllNodes
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::RemoveAllNodes( )
{
// TODO: Is this useless? wserv will remove its nodes anyway, if screen is destroyed
}
// ---------------------------------------------------------------------------
// ProcessUnknownNodeDrawingL
// ---------------------------------------------------------------------------
//
void CAlfHierarchyModel::ProcessUnknownNodeDrawingL( RMemReadStream& aStream )
{
TInt32 chunkInUse = aStream.ReadInt32L();
TInt nextFramePos = aStream.ReadInt32L();
// jump to the next frame
if ( nextFramePos == KFrameOffsetTemplate )
{
__ALFLOGSTRING("CAlfHierarchyModel::PostBufferL, Address of the frame has not been initialized!");
}
TUint8 padding = aStream.ReadInt8L();
aStream.ReadInt8L();
while( padding--)
{
aStream.ReadInt8L();
}
TInt currentPos = aStream.Source()->TellL( MStreamBuf::ERead ).Offset();
aStream.Source()->SeekL( MStreamBuf::ERead, TStreamPos(nextFramePos));
TSgcCanvasCommands packetState = (TSgcCanvasCommands)aStream.ReadInt8L();
switch( packetState )
{
case EAlfPacketReady: // fall through
case EAlfPacketNotReady:
default:
{
__ALFLOGSTRING1("CAlfHierarchyModel::PostBufferL endMarker: %d ", packetState);
break;
}
}
}