--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/ServerCore/Src/alfhierarchymodel.cpp Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,1184 @@
+/*
+* 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
+ }
+
+// ---------------------------------------------------------------------------
+// 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
+ }
+
+// ---------------------------------------------------------------------------
+// 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;
+ }
+ 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 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
+ }
+
+// ---------------------------------------------------------------------------
+// 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();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// DoNodeActivatedL
+// ---------------------------------------------------------------------------
+//
+void CAlfHierarchyModel::DoNodeActivatedL()
+ {
+ TInt nodeType = iStream->ReadInt32L();
+ TUint32 nodeId = (TUint32)iStream->ReadUint32L();
+ CAlfNode* node = FindNode( nodeId );
+ if ( node )
+ {
+ node->ActivateNode();
+ }
+ else
+ {
+ USER_INVARIANT();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// 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
+
+ }
+
+// ---------------------------------------------------------------------------
+// DoNodeSiblingOrderChangedL
+// ---------------------------------------------------------------------------
+//
+void CAlfHierarchyModel::DoNodeSiblingOrderChangedL()
+ {
+ TInt newPos = iStream->ReadInt32L();
+ TUint32 nodeId = (TUint32)iStream->ReadUint32L();
+
+ CAlfNode* node = FindNode( nodeId );
+ if ( node )
+ {
+ node->SiblingOrderChanged( newPos );
+ }
+ 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();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// 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);
+ CAlfNodeVisual* node = (CAlfNodeVisual*)FindNode( nodeId );
+ if ( node && node->Window() )
+ {
+ // SetSurfaceExtent is not supported for image visual
+ node->Window()->SetSurfaceExtent( extent );
+ }
+ 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!
+ }
+ }
+// ---------------------------------------------------------------------------
+// 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;
+ }
+ }
+ }
+
+