windowing/windowserver/nga/CLIENT/RDirect.CPP
changeset 0 5d03bc08d59c
child 10 0e9202c0340c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Client side classes for handling direct screen access
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32std.h>
       
    19 #include <e32base.h>
       
    20 #include "../SERVER/w32cmd.h"
       
    21 #include "CLIENT.H"
       
    22 #include "w32comm.h"
       
    23 #include <e32msgqueue.h>
       
    24 
       
    25 
       
    26 NONSHARABLE_CLASS(CDsaMsgQueue) : public CActive
       
    27 {
       
    28 	public:
       
    29 		CDsaMsgQueue();
       
    30 		~CDsaMsgQueue();
       
    31 		void Request(TRequestStatus* aClientRequest);
       
    32 		TBool Started() { return iStarted;}
       
    33 		TBool Completed();
       
    34 		void OpenRecQueue(TInt aHandle);
       
    35 		void OpenSendQueue(TInt aHandle);
       
    36 		TInt Send(TInt aData);
       
    37 		RMsgQueueBase& SendQueue() {return iSendQueue; }
       
    38 		RMsgQueueBase& Queue() { return iRecQueue; }
       
    39 		TRequestStatus* Status() { return &iStatus; }
       
    40 		TBool RequestStarted() { return iStarted;}
       
    41 	private:
       
    42 		void DoCancel();
       
    43 		void RunL();
       
    44 		void Listen();
       
    45 		
       
    46 	private:
       
    47 		RMsgQueueBase iRecQueue;
       
    48 		RMsgQueueBase iSendQueue;
       
    49 		TRequestStatus* iClientRequest;
       
    50 		TBool iStarted;
       
    51 		RThread* iServer;
       
    52 };
       
    53 
       
    54 //
       
    55 CDsaMsgQueue::CDsaMsgQueue() : CActive(RDirectScreenAccess::EPriorityVeryHigh)
       
    56 	{
       
    57 	CActiveScheduler::Add(this);
       
    58 	}
       
    59 
       
    60 CDsaMsgQueue::~CDsaMsgQueue()
       
    61 	{
       
    62 	Cancel();
       
    63 	iRecQueue.Close();
       
    64 	iSendQueue.Close();
       
    65 	}
       
    66 
       
    67 TInt CDsaMsgQueue::Send(TInt aData)
       
    68 	{
       
    69 	return iSendQueue.Send(&aData,sizeof(TInt));
       
    70 	}
       
    71 
       
    72 void CDsaMsgQueue::OpenRecQueue(TInt aHandle)
       
    73 	{
       
    74 	iRecQueue.SetHandle(aHandle);
       
    75 // With RmessagePtr2 compelete using an RHandle the returned handle is already duplicated
       
    76 	}
       
    77 
       
    78 void CDsaMsgQueue::OpenSendQueue(TInt aHandle)
       
    79 	{
       
    80 	iSendQueue.SetHandle(aHandle);
       
    81 // With RmessagePtr2 compelete using an RHandle the returned handle is already duplicated
       
    82 	}
       
    83 
       
    84 void CDsaMsgQueue::DoCancel()
       
    85 	{
       
    86 	iRecQueue.CancelDataAvailable();
       
    87 	TInt ret = KErrNone;
       
    88 	do
       
    89 		{
       
    90 		TInt data = 0;
       
    91 		ret = iRecQueue.Receive(&data,sizeof(TInt));
       
    92 		}while(ret == KErrNone);
       
    93 	if(iClientRequest)
       
    94 		{
       
    95 		RThread().RequestComplete(iClientRequest,KErrCancel);
       
    96 		}
       
    97 	}
       
    98 	
       
    99 void CDsaMsgQueue::RunL()
       
   100 	{
       
   101 	// get the data from the msg queue
       
   102 	TInt reason = 0;
       
   103 	iRecQueue.Receive(&reason,sizeof(TInt));
       
   104 	
       
   105 	if(iClientRequest)
       
   106 		{
       
   107 		// if there is an outstanding client request, complete and pass on the abort reason
       
   108 		User::RequestComplete(iClientRequest,reason);
       
   109 		iClientRequest = NULL;
       
   110 		}
       
   111 	}
       
   112 
       
   113 void CDsaMsgQueue::Listen()
       
   114 	{
       
   115 	if(!IsActive())
       
   116 		{
       
   117 		SetActive();	
       
   118 		iRecQueue.NotifyDataAvailable(iStatus);
       
   119 		}
       
   120 	}
       
   121 
       
   122 void CDsaMsgQueue::Request(TRequestStatus* aClientRequest)
       
   123 	{
       
   124 	__ASSERT_ALWAYS(!IsActive(),User::Invariant());
       
   125 	iClientRequest = aClientRequest;
       
   126 	iStarted = ETrue;
       
   127 	Listen();
       
   128 	}
       
   129 
       
   130 TBool CDsaMsgQueue::Completed()
       
   131 	{
       
   132 	if(iStarted)
       
   133 		{
       
   134 		Send(KErrNone);
       
   135 		iStarted = EFalse;
       
   136 		return ETrue;
       
   137 		}
       
   138 	return EFalse;
       
   139 	}
       
   140 
       
   141 
       
   142 LOCAL_C inline TDeviceOrientation Graphics2DeviceOrientation(CFbsBitGc::TGraphicsOrientation aGraphicsOrientation)
       
   143     {
       
   144     return ((TDeviceOrientation)(1 << aGraphicsOrientation));
       
   145     }
       
   146 
       
   147 //
       
   148 // RDirectScreenAccess
       
   149 //
       
   150 
       
   151 EXPORT_C RDirectScreenAccess::RDirectScreenAccess()
       
   152 /** Default constructor.
       
   153 
       
   154 Developers should use the other constructor overload instead. */
       
   155 	{
       
   156 	}
       
   157 
       
   158 EXPORT_C RDirectScreenAccess::RDirectScreenAccess(RWsSession& aWs) : MWsClientClass(aWs.iBuffer), iWs(&aWs), iMsgQueue(NULL)
       
   159 /** C++ constructor with a connected window server session.
       
   160 
       
   161 Construct() must be called to complete construction.
       
   162 
       
   163 @param aWs Connected session with the window server. */
       
   164 	{
       
   165 	}
       
   166 
       
   167 EXPORT_C TInt RDirectScreenAccess::Construct()
       
   168 /** Second phase constructor.
       
   169 
       
   170 Creates the server side resource and initialises the client's handle to it.
       
   171 
       
   172 This function always causes a flush of the window server buffer.
       
   173 
       
   174 @return KErrNone if successful, otherwise one of the system wide error codes. 
       
   175 @panic TW32Panic 17 in debug builds if called on an already constructed object.*/
       
   176 	{
       
   177 	__ASSERT_DEBUG(iWsHandle == KNullHandle, Panic(EW32PanicGraphicDoubleConstruction));
       
   178 	return Construct(EFalse);
       
   179 	}
       
   180 
       
   181 EXPORT_C TInt RDirectScreenAccess::Construct(TBool aRegionTrackingOnly)
       
   182 /** Second phase constructor.
       
   183 
       
   184 Creates the server side resource and initialises the client's handle to it.
       
   185 
       
   186 This function always causes a flush of the window server buffer.
       
   187 
       
   188 @param aRegionTrackingOnly ETrue if the DSA is intended to be used for region tracking purposes only,
       
   189 EFalse if the DSA will be used to perform actual drawing.
       
   190 @return KErrNone if successful, otherwise one of the system wide error codes. 
       
   191 @panic TW32Panic 17 in debug builds if called on an already constructed object.*/
       
   192 	{
       
   193 	__ASSERT_DEBUG(iWsHandle == KNullHandle, Panic(EW32PanicGraphicDoubleConstruction));
       
   194 	TInt ret = KErrNone;
       
   195 	TWsClientOpcodes requestedOpCode = aRegionTrackingOnly? EWsClOpCreateDirectScreenAccessRegionTrackingOnly : EWsClOpCreateDirectScreenAccess;
       
   196 	
       
   197 	if ((ret = iBuffer->WriteReplyWs(requestedOpCode)) >= 0)
       
   198 		{
       
   199 		iWsHandle = ret;
       
   200 		TRAP(ret,iMsgQueue = new (ELeave)CDsaMsgQueue);
       
   201 		if(ret == KErrNone)
       
   202 			{
       
   203 			// the servers send queue is the client receive queue
       
   204 			TInt h = WriteReply(EWsDirectOpGetSendQueue);
       
   205 			iMsgQueue->OpenRecQueue(h);	
       
   206 		
       
   207 			// servers receive queue is the clients send queue
       
   208 			h = WriteReply(EWsDirectOpGetRecQueue);
       
   209 			iMsgQueue->OpenSendQueue(h);	
       
   210 			}
       
   211 		else
       
   212 			{
       
   213 			Close();
       
   214 			}
       
   215 		}
       
   216 	return(ret);
       
   217 	}
       
   218 
       
   219 EXPORT_C TInt RDirectScreenAccess::Request(RRegion*& aRegion,TRequestStatus& aStatus,const RWindowBase& aWindow)
       
   220 /** Issues a request to the window server for permission to perform direct screen 
       
   221 access on a window.
       
   222 
       
   223 Direct access to the screen may be refused due to lack of memory or if the 
       
   224 target window is completely obscured.
       
   225 
       
   226 If direct access is allowed, the function passes back a clipping region which 
       
   227 is the part of the screen the caller can draw to. 
       
   228 
       
   229 When direct screen access must stop, for instance because a dialog is to be 
       
   230 displayed in front of the region where direct screen access is taking place, 
       
   231 the window server completes the request. The recommended way to check for 
       
   232 this is for aStatus to be the request status of an active object that will 
       
   233 be run when the request completes, i.e. if Request() returns KErrNone, call 
       
   234 SetActive(), and in the object's RunL(), you should immediately abort direct 
       
   235 screen access.
       
   236 
       
   237 While the DSA is in operation, it is strongly advised that the client should 
       
   238 not make any call to WSERV that will affect the visible area of the window in 
       
   239 which the DSA is taking place. 
       
   240 
       
   241 When WSERV tells the client that it needs to abort its DSA, it waits to receive
       
   242 the acknowledgment from the client that it has done so. However, it doesn't wait 
       
   243 for ever, since the client may have entered some long running calculation or even
       
   244 an infinite loop. So WSERV also waits on a timer: if the timer expires before the
       
   245 client acknowledges, then WSERV continues; if, later on, WSERV gets notification
       
   246 from the client that it has aborted the DSA, then WSERV will invalidate the region
       
   247 in which the DSA was taking place, just in case there had been a conflict between
       
   248 the DSA and another client.
       
   249 
       
   250 
       
   251 This function always causes a flush of the window server buffer.
       
   252 
       
   253 @param aRegion On return, the clipping region that the caller can draw to. 
       
   254 NULL if the function was not successful.
       
   255 If the target window is invisible or completely covered by other windows
       
   256 then the region will be empty.
       
   257 @param aStatus A request status that is set to a completion code by the window 
       
   258 server when direct screen access must stop.
       
   259 @param aWindow The window that you want to perform the direct screen access 
       
   260 on.
       
   261 @return KErrNone if the request was successful, KErrNone with empty region if 
       
   262 none of the window is currently visible, otherwise one of the system wide error codes,
       
   263 e.g. KErrNoMemory if out of memory. */
       
   264 	{
       
   265 	__ASSERT_ALWAYS(iMsgQueue,Panic(EW32PanicDirectMisuse));
       
   266 
       
   267 	aRegion = NULL;
       
   268 
       
   269 	// Allocate the memory for the RRegion here so it is simple to back out
       
   270 	// in case of failure
       
   271 	TAny* regionMem = User::Alloc (sizeof (RRegion));
       
   272 	if (!regionMem)
       
   273 		{
       
   274 		return KErrNoMemory;
       
   275 		}
       
   276 
       
   277 	TInt ret = WriteReplyInt(aWindow.WsHandle(),EWsDirectOpRequest);
       
   278 	if (ret<KErrNone)
       
   279 		{
       
   280 		User::Free (regionMem);
       
   281 		return ret;
       
   282 		}
       
   283 	TRect* rectList = NULL;
       
   284 	TRect* newRectList;
       
   285 	TInt numRect;
       
   286 
       
   287 	do
       
   288 		{
       
   289 		numRect = ret;
       
   290 		newRectList = STATIC_CAST(TRect*,User::ReAlloc(rectList,numRect*sizeof(TRect)));
       
   291 		if (!newRectList)
       
   292 			{
       
   293 			Write(EWsDirectOpInitFailed);
       
   294 			User::Free (regionMem);
       
   295 			delete rectList;
       
   296 			return KErrNoMemory;
       
   297 			}
       
   298 		rectList = newRectList;
       
   299 		TPtr8 ptr(REINTERPRET_CAST(TUint8*,rectList),ret*sizeof(TRect));
       
   300 		ret = WriteReplyIntP(ret,&ptr,EWsDirectOpGetRegion);
       
   301 		} while(ret >=0 && ret != KMaxTInt);
       
   302 	if (ret<0)
       
   303 		{
       
   304 		User::Free (regionMem);
       
   305 		delete rectList;
       
   306 		return ret;
       
   307 		}
       
   308 
       
   309 	aRegion = new (regionMem) RRegion (numRect, rectList);
       
   310 	aStatus = KRequestPending;
       
   311 	iMsgQueue->Request(&aStatus);
       
   312 	iWs->DirectAcessActivation(ETrue);
       
   313 	return KErrNone;
       
   314 	}
       
   315 
       
   316 EXPORT_C void RDirectScreenAccess::Completed()
       
   317 /** Indicates to the window server that you have responded to the completion of 
       
   318 the request status passed to Request(), by stopping direct screen access. */
       
   319 	{
       
   320 	__ASSERT_ALWAYS(iMsgQueue->Started(),Panic(EW32PanicDirectMisuse));
       
   321 	if(iMsgQueue->Completed())
       
   322 		{
       
   323 		iWs->DirectAcessActivation(EFalse);
       
   324 		}
       
   325 	}
       
   326 
       
   327 EXPORT_C void RDirectScreenAccess::Cancel()
       
   328 /** Indicates to the window server that you have finished performing direct screen 
       
   329 access. */
       
   330 	{
       
   331 	if(iMsgQueue->Started())
       
   332 		{
       
   333 		Completed();
       
   334 		}
       
   335 	TInt ret = WriteReply(EWsDirectOpCancel);
       
   336 	if(ret != 0) // the server is sending us some data.
       
   337 		{
       
   338 		iMsgQueue->Queue().CancelDataAvailable();
       
   339 		TInt data = 0;
       
   340 		iMsgQueue->Queue().ReceiveBlocking(&data,sizeof(TInt));
       
   341 		}
       
   342 	iMsgQueue->Cancel();
       
   343 	}
       
   344 
       
   345 EXPORT_C void RDirectScreenAccess::Close()
       
   346 /** Calls Completed() then deletes the server side resource and sets the client's 
       
   347 handle to it to NULL. */
       
   348 	{
       
   349 	if (iBuffer && iWsHandle)
       
   350 		{
       
   351 		if(iMsgQueue && iMsgQueue->Started())
       
   352 			{
       
   353 			Completed();
       
   354 			}
       
   355 		Write(EWsDirectOpFree);
       
   356 		delete iMsgQueue;
       
   357 		iMsgQueue = NULL;
       
   358 		}
       
   359 	iWsHandle = NULL;
       
   360 	}
       
   361 
       
   362 //
       
   363 // CDirectScreenAccess
       
   364 //
       
   365 
       
   366 EXPORT_C CDirectScreenAccess* CDirectScreenAccess::NewL(RWsSession& aWs,CWsScreenDevice& aScreenDevice,RWindowBase& aWin,MDirectScreenAccess& aAbort)
       
   367 /** Allocates and constructs the object and adds it to the current active scheduler.
       
   368 
       
   369 This function always causes a flush of the window server buffer.
       
   370 
       
   371 @param aWs A session with the window server.
       
   372 @param aScreenDevice Specifies the characteristics of the screen device to 
       
   373 draw to.
       
   374 @param aWin The window to draw to directly.
       
   375 @param aAbort Defines an AbortNow() and a Restart() function which are both 
       
   376 called on aborting, as part of the RunL(). Restart() is called from an idle 
       
   377 time active object (CIdle).
       
   378 @return The newly constructed object. */
       
   379 	{
       
   380 	return CDirectScreenAccess::NewL(aWs,aScreenDevice,aWin,aAbort,EFalse);
       
   381 	}
       
   382 
       
   383 EXPORT_C CDirectScreenAccess* CDirectScreenAccess::NewL(RWsSession& aWs,CWsScreenDevice& aScreenDevice,RWindowBase& aWin,MDirectScreenAccess& aAbort,TBool aRegionTrackingOnly)
       
   384 /** Allocates and constructs the object and adds it to the current active scheduler.
       
   385 
       
   386 This function always causes a flush of the window server buffer.
       
   387 
       
   388 @param aWs A session with the window server.
       
   389 @param aScreenDevice Specifies the characteristics of the screen device to 
       
   390 draw to.
       
   391 @param aWin The window to draw to directly.
       
   392 @param aAbort Defines an AbortNow() and a Restart() function which are both 
       
   393 called on aborting, as part of the RunL(). Restart() is called from an idle 
       
   394 time active object (CIdle).
       
   395 @param aRegionTrackingOnly The screen device and GC are allocated if this is EFalse,
       
   396 but not if it is ETrue. Only the DSA region data and updates to that are
       
   397 available in the latter case. Creating the screen device will trigger the dsa
       
   398 buffer allocationand it is an operation that could fail, should this happen
       
   399 the function will leave.
       
   400 @return The newly constructed object. */
       
   401 	{
       
   402 	CDirectScreenAccess* self = new(ELeave) CDirectScreenAccess(aWs,&aScreenDevice,aWin,aAbort);
       
   403 	CleanupStack::PushL(self);
       
   404 	self->ConstructL(aWs,aRegionTrackingOnly);
       
   405 	CleanupStack::Pop(self);
       
   406 	return self;
       
   407 	}
       
   408 
       
   409 CDirectScreenAccess::~CDirectScreenAccess()
       
   410 	{
       
   411 	__ASSERT_ALWAYS(!iAborting,Panic(EW32PanicDirectMisuse));
       
   412 	Cancel();
       
   413 	delete iGc;
       
   414 	delete iScreenDevice;
       
   415 	if (iDrawingRegion)
       
   416 		iDrawingRegion->Destroy();
       
   417 	iDirectAccess.Close();
       
   418 	delete iRestart;
       
   419 	}
       
   420 
       
   421 void CDirectScreenAccess::ConstructL(RWsSession& aWs,TBool aRegionTrackingOnly)
       
   422 	{
       
   423 	iScreenNumber = iWsScreenDevice->GetScreenNumber();
       
   424 	
       
   425 	if(aRegionTrackingOnly)
       
   426 		{
       
   427 		iFlags |= EDirectRegionTrackingOnly;
       
   428 		}
       
   429 	User::LeaveIfError(iDirectAccess.Construct(aRegionTrackingOnly));
       
   430 	
       
   431 	iRestart = CIdle::NewL(RDirectScreenAccess::EPriorityVeryHigh-5);
       
   432 	CActiveScheduler::Add(this);
       
   433 	if (aWs.GetColorModeList(NULL)>1)
       
   434 		iFlags |= EDirectCheckModeChange;
       
   435 	if (iWsScreenDevice->NumScreenModes() == 1)
       
   436 		{
       
   437 		if ((iWsScreenDevice->GetRotationsList(0,NULL) == 1) && !aRegionTrackingOnly)
       
   438 			{
       
   439 			return;
       
   440 			}
       
   441 		}
       
   442 	iFlags |= EDirectCheckSizeModeChange;
       
   443 	}
       
   444 
       
   445 void CDirectScreenAccess::CreateScreenObjectsL(TDisplayMode aCurrentMode)
       
   446 	{
       
   447 	__ASSERT_DEBUG(!(iFlags&EDirectRegionTrackingOnly),Panic(EW32PanicDirectMisuse));
       
   448 	delete iScreenDevice;
       
   449 	iScreenDevice = NULL;
       
   450 	
       
   451 	iScreenDevice = CFbsScreenDevice::NewL(iScreenNumber,aCurrentMode);
       
   452 	
       
   453 	if (iGc)
       
   454 		{
       
   455 		iGc->Activate(iScreenDevice);
       
   456 		}
       
   457 	else
       
   458 		{
       
   459 		User::LeaveIfError(iScreenDevice->CreateContext(iGc));
       
   460 		if (!(iFlags&EDirectCheckSizeModeChange))
       
   461 			UpdateSizeAndRotation(iGc);
       
   462 		}
       
   463 	}
       
   464 
       
   465 EXPORT_C void CDirectScreenAccess::StartL()
       
   466 /** Informs the window server that you are going to start direct screen access 
       
   467 and sets up a graphics context with which you can draw to the screen.
       
   468 
       
   469 It should also be called to restart direct screen access after Cancel() has 
       
   470 been called to stop it. 
       
   471 
       
   472 While the DSA is in operation, it is strongly advised that the client should 
       
   473 not make any call to WSERV that will affect the visible area of the window in 
       
   474 which the DSA is taking place. 
       
   475 
       
   476 When WSERV tells the client that it needs to abort its DSA, it waits to receive
       
   477 the acknowledgment from the client that it has done so. However, it doesn't wait
       
   478 for ever, since the client may have entered some long running calculation or even
       
   479 an infinite loop. So WSERV also waits on a timer: if the timer expires before the
       
   480 client acknowledges, then WSERV continues; if, later on, WSERV gets notification
       
   481 from the client that it has aborted the DSA, then WSERV will invalidate the region
       
   482 in which the DSA was taking place, just in case there had been a conflict between
       
   483 the DSA and another client.
       
   484 
       
   485 
       
   486 This function always causes a flush of the window server buffer. */
       
   487 	{
       
   488 	if (iDrawingRegion)
       
   489 		iDrawingRegion->Destroy();
       
   490 	User::LeaveIfError(iDirectAccess.Request(iDrawingRegion,iStatus,iWindow));
       
   491 	SetActive();
       
   492 	if(!(iFlags&EDirectRegionTrackingOnly))
       
   493 		{
       
   494 		if((iFlags&EDirectCheckModeChange) || iScreenDevice == NULL)
       
   495 			{
       
   496 			TDisplayMode currentDisplayMode = iWsScreenDevice->DisplayMode();
       
   497 			if (iScreenDevice == NULL || currentDisplayMode != iScreenDevice->DisplayMode())
       
   498 				{
       
   499 				TRAPD(err,CreateScreenObjectsL(currentDisplayMode));
       
   500 				if (err != KErrNone)
       
   501 					{
       
   502 					Cancel();
       
   503 					User::Leave(err);
       
   504 					}
       
   505 				}
       
   506 			}
       
   507 		if (iFlags&EDirectCheckSizeModeChange)
       
   508 			{
       
   509 			UpdateSizeAndRotation(iGc);
       
   510 			}
       
   511 		iGc->SetOrigin(iWindow.AbsPosition());
       
   512 		}
       
   513 	iDrawingRegion->ClipRect(iScreenSize);
       
   514 	if(!(iFlags&EDirectRegionTrackingOnly))
       
   515 			{
       
   516 			iGc->SetClippingRegion(iDrawingRegion);
       
   517 			}
       
   518 	}
       
   519 
       
   520 TInt CDirectScreenAccess::Restart(TAny* aDirect)		//static
       
   521 	{
       
   522 	STATIC_CAST(CDirectScreenAccess*,aDirect)->Restart();
       
   523 	return(KErrNone);
       
   524 	}
       
   525 
       
   526 void CDirectScreenAccess::Restart()
       
   527 	{
       
   528 	iAbort.Restart(iReason);
       
   529 	}
       
   530 
       
   531 void CDirectScreenAccess::UpdateSizeAndRotation(CFbsBitGc*/* aGc*/)
       
   532 	{
       
   533 	TPixelsAndRotation sizeAndRotation;
       
   534 	iWsScreenDevice->GetDefaultScreenSizeAndRotation(sizeAndRotation);
       
   535 	iScreenSize = sizeAndRotation.iPixelSize;
       
   536 	__ASSERT_ALWAYS(iScreenDevice,Panic(EW32PanicDirectMisuse));
       
   537 	iScreenDevice->SetDeviceOrientation(Graphics2DeviceOrientation(sizeAndRotation.iRotation));
       
   538 	MDisplayMapping* interface = static_cast<MDisplayMapping*>
       
   539 				(iWsScreenDevice->GetInterface(MDisplayMapping::ETypeId));
       
   540 	
       
   541 	if(interface)
       
   542 		{
       
   543 		TRect appAreaInDsa;
       
   544 		interface->MapCoordinates(EApplicationSpace, iScreenSize, EDirectScreenAccessSpace, appAreaInDsa);
       
   545 		if(!iDrawingRegion->BoundingRect().IsEmpty())
       
   546 			{
       
   547 			//no point to set draw origin if draw region is empty
       
   548 			//this also indicates the place to draw might be outside DSA buffer
       
   549 			iScreenDevice->SetDrawDeviceOffset(appAreaInDsa.iTl);
       
   550 			}
       
   551 		}
       
   552 	}
       
   553 
       
   554 void CDirectScreenAccess::RunL()
       
   555 	{
       
   556 	iAborting = ETrue;
       
   557 	iReason = REINTERPRET_CAST(RDirectScreenAccess::TTerminationReasons&,iStatus);
       
   558 	iAbort.AbortNow(iReason);
       
   559 	iAborting = EFalse;
       
   560 	iDirectAccess.Completed();
       
   561 	iRestart->Start(TCallBack(CDirectScreenAccess::Restart,this));
       
   562 	}
       
   563 
       
   564 void CDirectScreenAccess::DoCancel()
       
   565 	{
       
   566 	iDirectAccess.Cancel();
       
   567 	}