A recent update.
The capturing and the sending back of key event is working now on a headless console exe application. Sending back the event is just described in the previous post(in my case, I capture the right soft key while in the menu list; but not all keys and applications can promise to work this way, the red "No" key with the phone app, for example). Although this event is not generated from my application, just captured.
You would better use DEV certification with required capabilities specified in MMP to make it work. According to my experience, the installation will go fine, but the actual invoke of capability required API will fail and give a return value of -46(KErrPermissionDenied), not 0(KErrNone).
The capture code is as follows, the code style is a little weird(I don't use NewL and NewLC here, and the ConstuctL is actually invoked directly in constructor), hope the logging message will help too:
header:
Code:
#ifndef CWSEVENTCAPTURER_H_
#define CWSEVENTCAPTURER_H_
#include <W32STD.H>
#include <e32keys.h>
#include <flogger.h>
class MWsEventCallBack
{
public:
virtual TBool KeyDownCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
virtual TBool KeyUpCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
virtual TBool KeyCapturedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
virtual TBool WindowGroupListChangedL(TWsEvent &aEvent, RWsSession &aWsSession) = 0;
};
enum KeyCapturerId {
KeyCapturerA,
KeyCapturerB,
};
class CWsEventCapturer : public CActive
{
public:
CWsEventCapturer(MWsEventCallBack& aObserver);
virtual ~CWsEventCapturer();
private:
void ConstructL();
public:
void SetCaptureKey(KeyCapturerId aId, TStdScanCode aScanCode, TKeyCode aKeyCode);
private:
void RunL();
void DoCancel();
void Listen();
public:
void StopKeyEventCapture(KeyCapturerId aId);
void StartKeyEventCapture(KeyCapturerId aId);
private:
MWsEventCallBack& iObserver;
#ifdef __FLOGGER__
RFileLogger iFileLogger;
#endif
TKeyCode iCaptureKeyCodeA;
TStdScanCode iCaptureKeyScanCodeA;
TInt iKeyEventHandleA;
TInt iKeyUpAndDownEventHandleA;
TKeyCode iCaptureKeyCodeB;
TStdScanCode iCaptureKeyScanCodeB;
TInt iKeyEventHandleB;
TInt iKeyUpAndDownEventHandleB;
RWsSession iWsSession;
RWindowGroup iWg;
};
#endif /*CWSEVENTCAPTURER_H_*/
source:
Code:
#include "CWsEventCapturer.h"
#include <APGWGNAM.H>
CWsEventCapturer::CWsEventCapturer(MWsEventCallBack& aObserver)
: CActive(EPriorityStandard),
iObserver(aObserver),
iCaptureKeyCodeA(EKeyNull),
iCaptureKeyScanCodeA(EStdKeyNull),
iCaptureKeyCodeB(EKeyNull),
iCaptureKeyScanCodeB(EStdKeyNull),
iKeyEventHandleA(-1),
iKeyUpAndDownEventHandleA(-1),
iKeyEventHandleB(-1),
iKeyUpAndDownEventHandleB(-1) {
ConstructL();
}
CWsEventCapturer::~CWsEventCapturer()
{
StopKeyEventCapture(KeyCapturerA);
StopKeyEventCapture(KeyCapturerB);
if (IsActive()) {
Cancel();
}
iWg.Close();
iWsSession.Close();
#ifdef __FLOGGER__
iFileLogger.Close();
#endif
}
void CWsEventCapturer::SetCaptureKey(KeyCapturerId aId, TStdScanCode aScanCode, TKeyCode aKeyCode) {
switch (aId) {
case KeyCapturerA:
iCaptureKeyScanCodeA = aScanCode;
iCaptureKeyCodeA = aKeyCode;
break;
case KeyCapturerB:
iCaptureKeyScanCodeB = aScanCode;
iCaptureKeyCodeB = aKeyCode;
break;
}
}
void CWsEventCapturer::StartKeyEventCapture(KeyCapturerId aId) {
#define __INT32_MAX__ 0x7fffffffL
#define __INT32_MIN__ (-__INT32_MAX__ - 1L)
switch (aId) {
case KeyCapturerA:
if (iKeyUpAndDownEventHandleA < 0 && iCaptureKeyScanCodeA != EStdKeyNull) {
iKeyUpAndDownEventHandleA = iWg.CaptureKeyUpAndDowns(iCaptureKeyScanCodeA, 0, 0/*, __INT32_MIN__*/);
}
if (iKeyEventHandleA < 0 && iCaptureKeyCodeA != EKeyNull) {
iKeyEventHandleA = iWg.CaptureKey(iCaptureKeyCodeA, 0, 0/*, __INT32_MIN__*/);
}
break;
case KeyCapturerB:
if (iKeyUpAndDownEventHandleB < 0 && iCaptureKeyScanCodeB != EStdKeyNull) {
iKeyUpAndDownEventHandleB = iWg.CaptureKeyUpAndDowns(iCaptureKeyScanCodeB, 0, 0/*, __INT32_MIN__*/);
}
if (iKeyEventHandleB < 0 && iCaptureKeyCodeB != EKeyNull) {
iKeyEventHandleB = iWg.CaptureKey(iCaptureKeyCodeB, 0, 0/*, __INT32_MIN__*/);
}
break;
}
#ifdef __FLOGGER__
iFileLogger.WriteFormat(_L("capture started, keyA up/down handle: %d, keyA event handle: %d"), iKeyUpAndDownEventHandleA, iKeyEventHandleA);
iFileLogger.WriteFormat(_L("capture started, keyB up/down handle: %d, keyB event handle: %d"), iKeyUpAndDownEventHandleB, iKeyEventHandleB);
#endif
// Listen();
}
void CWsEventCapturer::StopKeyEventCapture(KeyCapturerId aId) {
// if (IsActive()) {
// Cancel();
// }
switch (aId) {
case KeyCapturerA:
if(iKeyEventHandleA >= 0) {
iWg.CancelCaptureKey(iKeyEventHandleA);
iKeyEventHandleA = -1;
}
if (iKeyUpAndDownEventHandleA >= 0) {
iWg.CancelCaptureKeyUpAndDowns(iKeyUpAndDownEventHandleA);
iKeyUpAndDownEventHandleA = -1;
}
break;
case KeyCapturerB:
if(iKeyEventHandleB >= 0) {
iWg.CancelCaptureKey(iKeyEventHandleB);
iKeyEventHandleB = -1;
}
if (iKeyUpAndDownEventHandleB >= 0) {
iWg.CancelCaptureKeyUpAndDowns(iKeyUpAndDownEventHandleB);
iKeyUpAndDownEventHandleB = -1;
}
break;
}
#ifdef __FLOGGER__
iFileLogger.WriteFormat(_L("capture stopped, keyA up/down handle: %d, keyA event handle: %d"), iKeyUpAndDownEventHandleA, iKeyEventHandleA);
iFileLogger.WriteFormat(_L("capture started, keyB up/down handle: %d, keyB event handle: %d"), iKeyUpAndDownEventHandleB, iKeyEventHandleB);
#endif
}
void CWsEventCapturer::ConstructL()
{
#ifdef __FLOGGER__
iFileLogger.Connect();
iFileLogger.CreateLog(TPtrC((const TUint16 *) L"extkman"), TPtrC((const TUint16 *) L"swcap.txt"), EFileLoggingModeOverwrite);
iFileLogger.SetDateAndTime( EFalse, ETrue );
iFileLogger.WriteFormat(_L("window event capturer inited"));
#endif
CActiveScheduler::Add(this);
User::LeaveIfError(iWsSession.Connect());
iWg = RWindowGroup(iWsSession);
User::LeaveIfError(iWg.Construct((TUint32)&iWg, EFalse));
iWg.SetOrdinalPosition(-1);
iWg.EnableReceiptOfFocus(EFalse);
int err = 0;
err = iWg.EnableOnEvents(EEventControlAlways);
err = iWg.EnableGroupListChangeEvents();
CApaWindowGroupName* wn=CApaWindowGroupName::NewLC(iWsSession);
wn->SetHidden(ETrue);
wn->SetWindowGroupName(iWg);
CleanupStack::PopAndDestroy();//wn
Listen();
}
void CWsEventCapturer::RunL()
{
if (iStatus == KErrNone)
{
TWsEvent e;
iWsSession.GetEvent(e);
#ifdef __FLOGGER__
iFileLogger.WriteFormat(_L("event type: %d"), e.Type());
if (e.Key()) {
iFileLogger.WriteFormat(_L("key code: %d, key scan code: %d"), e.Key()->iCode, e.Key()->iScanCode);
}
#endif
switch (e.Type()) {
case EEventKeyUp:
if (iObserver.KeyUpCapturedL(e, iWsSession)) {
TInt wgId = iWsSession.GetFocusWindowGroup();
iWsSession.SendEventToWindowGroup(wgId, e);
}
break;
case EEventKeyDown:
if (iObserver.KeyDownCapturedL(e, iWsSession)) {
TInt wgId = iWsSession.GetFocusWindowGroup();
iWsSession.SendEventToWindowGroup(wgId, e);
}
break;
case EEventKey:
if (iObserver.KeyCapturedL(e, iWsSession)) {
TInt wgId = iWsSession.GetFocusWindowGroup();
iWsSession.SendEventToWindowGroup(wgId, e);
}
break;
case EEventWindowGroupListChanged:
iObserver.WindowGroupListChangedL(e, iWsSession);
break;
default:
break;
}
}
if (iStatus != KErrCancel)
{
Listen();
}
}
void CWsEventCapturer::DoCancel()
{
iWsSession.EventReadyCancel();
}
void CWsEventCapturer::Listen()
{
if (!IsActive()) {
iWsSession.EventReady(&iStatus);
SetActive();
}
}