libraries/btrace_parser/src/btrace_keypress.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Thu, 26 Aug 2010 00:49:35 +0100
changeset 37 534b01198c2d
parent 0 7f656887cf89
permissions -rw-r--r--
Added ENotifyKeypresses and ECaptureCtrlC flags to CCommandBase. Commands can now get keypresses and handle ctrl-C via callbacks instead of having to implement custom active objects. As part of this extended the CCommandBase extension interface to MCommandExtensionsV2 for the new virtual functions KeyPressed(TUint aKeyCode, TUint aModifiers) and CtrlCPressed(). sudo now cleans up correctly by using ECaptureCtrlC.

// btrace_keypress.cpp
// 
// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "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:
// Accenture - Initial contribution
//

#include <fshell/ltkutils.h>
#include "btrace_parser.h"

EXPORT_C CBtraceKeyPress* CBtraceKeyPress::NewL(CBtraceReader& aReader)
	{
	CBtraceKeyPress* self = new (ELeave) CBtraceKeyPress(aReader);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CBtraceKeyPress::CBtraceKeyPress(CBtraceReader& aReader): 
iReader(aReader)
	{
	}

EXPORT_C CBtraceKeyPress::~CBtraceKeyPress()
	{
	iReader.RemoveObserver(KAmTraceCategory, *this);
	iKeyNotifs.Close();
	iPointerNotifs.Close();
	iGenericNotifs.Close();
	iRawKeyNotifs.Close();
	}

void CBtraceKeyPress::ConstructL()
	{
	iReader.AddObserverL(KAmTraceCategory, *this);
	
	LtkUtils::W32CrackL(); // In case no-one's called it yet
	}

//
// CBtraceKeyPress::HandleBtraceFrameL
// process the btrace frame, stripping out the key event data
//
void CBtraceKeyPress::HandleBtraceFrameL(const TBtraceFrame& aFrame)
	{
	if(aFrame.iCategory == KAmTraceCategory && aFrame.iSubCategory == EAmTraceSubCategoryEvCapture)
		{
		const TUint32* data = reinterpret_cast<const TUint32*>(aFrame.iData.Ptr());
		const TAmTraceEventEvCapture event = static_cast<TAmTraceEventEvCapture>(*data++);
			
		switch(event)
			{
			case EAmTraceEventEvCaptureKeyPress:
				{
				data += 1; // step over superfluous bytes
				TKeyEvent* key = (TKeyEvent*) data;
				SeenKeyL(aFrame.iTickCount, *key);
				}
			break;
	
			case EAmTraceEventEvCapturePointer:
				{
				data += 1; // step over superfluous bytes
				TPointerEvent* pointer = (TPointerEvent*) data;
				SeenPointerL(aFrame.iTickCount, *pointer);			
				}
			break;
	
			case EAmTraceEventEvCaptureUnclassified:
				{
				TInt commandClass = *data++;
				TInt opcode = *data++;
				SeenUnclassifiedL(aFrame.iTickCount, commandClass, opcode, NULL);
				}
				break;
			
			case EAmTraceEventEvCaptureRawScan:
				{
				TBool isKeyUp = *data++;
				TInt scanCode = *data++;
				SeenRawKeyL(aFrame.iTickCount, isKeyUp, scanCode);
				}
			break;

			default:
				// Ignore anything we don't know about.
			break;
			}
		};
	}

//
// CBtraceKeyPress::SeenKeyL
// inform any observers that a key event has occured 
// & pass a reference back to the key event
//
void CBtraceKeyPress::SeenKeyL(const TBtraceTickCount& aTickCount, const TKeyEvent& aKey)
	{
	TInt ii = iKeyNotifs.Count();
	while (--ii >= 0)
		{
		MBtraceKeyPressObserver* observer = iKeyNotifs[ii].iObserver;
		if (iKeyNotifs[ii].iPersistence == ENotificationOneShot)
			{
			iKeyNotifs.Remove(ii);
			}
		observer->HandleKeyPressL(aTickCount, aKey);
		}	
	}

void CBtraceKeyPress::SeenRawKeyL(const TBtraceTickCount& aTickCount, TBool aKeyUp, TInt aScanCode)
	{
	TInt ii = iRawKeyNotifs.Count();
	while (--ii >= 0)
		{
		MBtraceKeyPressObserver* observer = iRawKeyNotifs[ii].iObserver;
		if (iRawKeyNotifs[ii].iPersistence == ENotificationOneShot)
			{
			iRawKeyNotifs.Remove(ii);
			}
		observer->HandleRawKeyL(aTickCount, aKeyUp, aScanCode);
		}
	}

//
// CBtraceKeyPress::SeenPointerL
// inform any observers that a key event has occured 
// & pass a reference back to the key event
//
void CBtraceKeyPress::SeenPointerL(const TBtraceTickCount& aTickCount, const TPointerEvent& aPointer)
	{
	TInt ii = iPointerNotifs.Count();
	while (--ii >= 0)
		{
		MBtraceKeyPressObserver* observer = iPointerNotifs[ii].iObserver;
		if (iPointerNotifs[ii].iPersistence == ENotificationOneShot)
			{
			iPointerNotifs.Remove(ii);
			}
		observer->HandlePointerPressL(aTickCount, aPointer);
		}	
	}

//
// CBtraceKeyPress::SeenUnclassifiedL
// inform any observers that unknown/unclassified data 
// has been received for a specific opcode
void CBtraceKeyPress::SeenUnclassifiedL(const TBtraceTickCount& aTickCount, const TInt aCommandClass, const TInt aOpcode, const TAny* aData)
	{
	TInt ii = iGenericNotifs.Count();
	while (--ii >= 0)
		{
		MBtraceKeyPressObserver* observer = iGenericNotifs[ii].iObserver;
		if (iGenericNotifs[ii].iPersistence == ENotificationOneShot)
			{
			iGenericNotifs.Remove(ii);
			}
		observer->HandleUnclassifiedDataL(aTickCount, aCommandClass, aOpcode, aData);
		}	
	}

//
// CBtraceKeyPress::NotifyKeyEvent
// called by the client to register an 
// interest in any key events captured 
//
EXPORT_C void CBtraceKeyPress::NotifyKeyEventL(MBtraceKeyPressObserver& aObserver)
	{
	NotifyKeyEventL(aObserver, ENotificationOneShot);
	}
	
EXPORT_C void CBtraceKeyPress::NotifyKeyEventL(MBtraceKeyPressObserver& aObserver, TBtraceNotificationPersistence aPersistence)
	{
	TKeyPressNotif notify(aObserver, aPersistence);
	User::LeaveIfError(iKeyNotifs.Append(notify));
	}
	
EXPORT_C void CBtraceKeyPress::CancelNotifyKeyEvent(MBtraceKeyPressObserver& aObserver)
	{
	for (TInt i=iKeyNotifs.Count()-1; i>=0; --i)
		{
		if (iKeyNotifs[i].iObserver == &aObserver)
			{
			iKeyNotifs.Remove(i);
			}
		}
	}

EXPORT_C void CBtraceKeyPress::NotifyRawKeyEventL(MBtraceKeyPressObserver& aObserver)
	{
	NotifyRawKeyEventL(aObserver, ENotificationOneShot);
	}
	
EXPORT_C void CBtraceKeyPress::NotifyRawKeyEventL(MBtraceKeyPressObserver& aObserver, TBtraceNotificationPersistence aPersistence)
	{
	TKeyPressNotif notify(aObserver, aPersistence);
	User::LeaveIfError(iRawKeyNotifs.Append(notify));
	}

EXPORT_C void CBtraceKeyPress::CancelNotifyRawKeyEvent(MBtraceKeyPressObserver& aObserver)
	{
	for (TInt i=iRawKeyNotifs.Count()-1; i>=0; --i)
		{
		if (iRawKeyNotifs[i].iObserver == &aObserver)
			{
			iRawKeyNotifs.Remove(i);
			}
		}
	}

//
// CBtraceKeyPress::NotifyPointerEvent
// called by the client to register an 
// interest in any pointer events captured 
//
EXPORT_C void CBtraceKeyPress::NotifyPointerEventL(MBtraceKeyPressObserver& aObserver)
	{
	NotifyPointerEventL(aObserver, ENotificationOneShot);
	}
	
EXPORT_C void CBtraceKeyPress::NotifyPointerEventL(MBtraceKeyPressObserver& aObserver, TBtraceNotificationPersistence aPersistence)
	{
	TKeyPressNotif notify(aObserver, aPersistence);
	User::LeaveIfError(iPointerNotifs.Append(notify));
	}

EXPORT_C void CBtraceKeyPress::CancelNotifyPointerEvent(MBtraceKeyPressObserver& aObserver)
	{
	for (TInt i=iPointerNotifs.Count()-1; i>=0; --i)
		{
		if (iPointerNotifs[i].iObserver == &aObserver)
			{
			iPointerNotifs.Remove(i);
			}
		}
	}

//
// CBtraceKeyPress::NotifyUnclassifiedDataL
// called by the client to register an 
// interest in any 'generic' events captured 
//
EXPORT_C void CBtraceKeyPress::NotifyUnclassifiedDataL(MBtraceKeyPressObserver& aObserver)
	{
	NotifyUnclassifiedDataL(aObserver, ENotificationOneShot);
	}

EXPORT_C void CBtraceKeyPress::NotifyUnclassifiedDataL(MBtraceKeyPressObserver& aObserver, TBtraceNotificationPersistence aPersistence)
	{
	TKeyPressNotif notify(aObserver, aPersistence);
	User::LeaveIfError(iGenericNotifs.Append(notify));	
	}

EXPORT_C void CBtraceKeyPress::CancelNotifyUnclassifiedData(MBtraceKeyPressObserver& aObserver)
	{
	for (TInt i=iGenericNotifs.Count()-1; i>=0; --i)
		{
		if (iGenericNotifs[i].iObserver == &aObserver)
			{
			iGenericNotifs.Remove(i);
			}
		}
	}

//
// TKeyPressNotif
// place holder for observers interested in key &/or pointer events
//
CBtraceKeyPress::TKeyPressNotif::TKeyPressNotif(MBtraceKeyPressObserver& aObserver, TBtraceNotificationPersistence aPersistence):
iObserver(&aObserver), iPersistence(aPersistence)
	{
	}