×
Namespaces

Variants
Actions

Capturing foreground window server events on Symbian

From Nokia Developer Wiki
Jump to: navigation, search

This article illustrates a Symbian C++ class that captures window server events sent to the foreground application.

Article Metadata
Compatibility
Platform(s): S60 3rd Edition and later
Platform Security
Capabilities: SwEvent
Article
Keywords: CApaWindowGroupName
Created: symbianyucca (27 Mar 2007)
Last edited: hamishwillee (22 Nov 2011)

Contents

Introduction

CFgrObserver illustrates how to capture foreground events in a background application. This implementation should work with all platform versions, but with S60 3rd Edition you need to have the SwEvent capability.

The usage is quite simple. Just implement the defined callback interface in your class and construct an instance of the CFgrObserver. Whenever a GUI application is taking focus you will get a notification through the callback functions. The aAppUid argument will have the UID of the application getting the focus.

Note that when constructing this class the aWsSession session variable should be connected. Otherwise the construction process will fail.

If you are only interested in your own application's focus changes, you could overwrite the Application user interface class HandleForegroundEventL() method.

Source code

Header required:

#include <w32std.h>
#include <APGWGNAM.H> //CApaWindowGroupName

Library Required:

LIBRARY   ws32.lib
LIBRARY apgrfx.lib //CApaWindowGroupName

Capability Required:

capability    SwEvent

ForeGroundObserver.cpp

CFgrObserver* CFgrObserver::NewL(RWsSession& aWsSession,MFgrCallBack& aCallBack)
{
CFgrObserver* self = CFgrObserver::NewLC(aWsSession,aCallBack);
CleanupStack::Pop(self);
return self;
}
 
 
CFgrObserver* CFgrObserver::NewLC(RWsSession& aWsSession,MFgrCallBack& aCallBack)
{
CFgrObserver* self = new (ELeave) CFgrObserver(aWsSession,aCallBack);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
 
 
CFgrObserver::CFgrObserver(RWsSession& aWsSession,MFgrCallBack& aCallBack)
:CActive(EPriorityHigh),iCallBack(aCallBack), iWsSession(aWsSession), iWg(aWsSession)
{
}
 
CFgrObserver::~CFgrObserver()
{
Cancel();
iWg.Close();
}
 
void CFgrObserver::ConstructL()
{
CActiveScheduler::Add(this);
 
User::LeaveIfError(iWg.Construct((TUint32)&iWg, EFalse));
iWg.SetOrdinalPosition(-1);
iWg.EnableReceiptOfFocus(EFalse);
 
CApaWindowGroupName* wn=CApaWindowGroupName::NewLC(iWsSession);
wn->SetHidden(ETrue);
wn->SetWindowGroupName(iWg);
CleanupStack::PopAndDestroy();
 
User::LeaveIfError(iWg.EnableFocusChangeEvents());
 
Listen();
}
 
void CFgrObserver::RunL()
{
if (iStatus == KErrNone)
{
TWsEvent e;
iWsSession.GetEvent(e);
}
 
TInt wgid = iWsSession.GetFocusWindowGroup();
 
CApaWindowGroupName* gn;
gn = CApaWindowGroupName::NewLC(iWsSession, wgid);
 
iCallBack.ForegroundEventL(gn->AppUid());
 
CleanupStack::PopAndDestroy(); // gn
 
if (iStatus != KErrCancel)
{
Listen();
}
}
 
void CFgrObserver::DoCancel()
{
iWsSession.EventReadyCancel();
}
 
void CFgrObserver::Listen()
{
iWsSession.EventReady(&iStatus);
SetActive();
}

ForeGroundObserver.h

class MFgrCallBack 
{
public:
virtual void ForegroundEventL(TUid aAppUid) = 0;
};
 
class CFgrObserver : public CActive
{
public:
static CFgrObserver* NewL(RWsSession& aWsSession,MFgrCallBack& aCallBack);
static CFgrObserver* NewLC(RWsSession& aWsSession,MFgrCallBack& aCallBack);
virtual ~CFgrObserver();
private:
CFgrObserver(RWsSession& aWsSession,MFgrCallBack& aCallBack);
void ConstructL();
void RunL();
void DoCancel();
void Listen();
private:
MFgrCallBack& iCallBack;
RWsSession& iWsSession;
RWindowGroup iWg;
};

Capturing Foreground events in a non-GUI application

If you wish to capture foreground events using non-GUI applications, the above solution will not work fully as most of the time you will receive an aAppUid of 0 for the application that caused the foreground event. An alternate solution would be monitoring EEventWindowGroupsChanged events by changing the ConstructL method, change the line

User::LeaveIfError(iWg.EnableFocusChangeEvents());

to

User::LeaveIfError(iWg.EnableGroupChangeEvents());

As you will receive an event callback every time a EEventWindowGroupsChanged will occur, you will need to check if the window group id of the application in the foreground is the same as the one of the application which caused the event:

void CFgrObserver::RunL()
{
if (iStatus == KErrNone)
{
TWsEvent e;
iWsSession.GetEvent(e);
}
 
TInt wgid = iWsSession.GetFocusWindowGroup();
 
CApaWindowGroupName* gn;
gn = CApaWindowGroupName::NewLC(iWsSession, wgid);
///retrieve the task in the foreground
TApaTask app = iTaskList->FindByPos(0);
///compare the window group ids, call the callback only if the ids are equal
if (app.WgId() == wgid)
iCallBack.ForegroundEventL(gn->AppUid());
 
 
CleanupStack::PopAndDestroy(); // gn
 
if (iStatus != KErrCancel)
{
Listen();
}
}

Note the usage of iTaskList which is a TApaTaskList* member, can be initialized in the ConstructL() method:

iTaskList = new (ELeave) TApaTaskList(iWsSession);
This page was last modified on 22 November 2011, at 04:05.
58 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×