Simulating key events is done by calling CCoeFep
’s
member function SimulateKeyEventsL()
; this sends to the
application a key event for each of the items in the array passed to it. There
are two overloads of SimulateKeyEventsL()
: in the first and most
commonly used overload, only the character codes of the key events are
specified; in the second overload, modifier keys can also be specified for each
key event to be simulated. The header file
epoc32\include\E32KEYS.H
defines the various modifiers possible.
The FEP author needs to derive from CCoeFep::MModifiedCharacter
in
order to use the second overload of SimulateKeyEventsL()
,
implementing all three of its pure virtual functions. The
ModifierMask()
function returns the modifiers whose value the FEP
wishes to specify; the values for the modifiers are returned by the
ModifierValues()
function. ModifierValues()
should
not return values for any modifiers that are not also returned by
ModifierMask()
.
For example, supposing a FEP wishes to send a key event to an
application with the func
modifier on and the
shift
modifier off. In this case the
ModifierMask()
function would return
EModifierFunc|EModifierShift
and the ModifierValues()
function would return EModifierFunc
. The resulting key event
received by the application would then have the EModifierFunc
modifier on and the EModifierShift
modifier off (even if the shift
key is being pressed down). All the other modifiers in the key event, since
they were not returned in the ModifierMask()
function, will
reflect the current state of the keyboard.
In order for a FEP to intercept key events before they reach the application beneath them, the FEP control must be added to the control stack at a high priority. This is done by using the following code in the control’s construction routine:
STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->AddToStackL(this, ECoeStackPriorityFep, ECoeStackFlagRefusesFocus|ECoeStackFlagSharable);
and the following code in its destructor:
STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi())->RemoveFromStack(this);
Passing the flag ECoeStackFlagSharable
to
AddToStackL()
ensures that if an embedded object is edited from an
application, for instance an embedded drawing is edited inside a word processor
document, the FEP’s control will also be put onto the child application’s
control stack when the child application is started. More importantly, the
ECoeStackFlagRefusesFocus
flag should be passed to
AddToStackL()
because FEPs in general should not “steal” focus
from the target underneath them. For the same reason,
SetNonFocusing()
(a member function of
CCoeControl
) should be called in the control’s
construction routine to prevent mouse or pen events from giving it focus. On
some occasions it may be legitimate for the FEP to take the focus, for instance
if the FEP has a floating window and it is temporarily in a mode where the user
can move this window around the screen by using the arrow keys. In this case,
the FEP’s control can take the focus by calling:
CCoeAppUi& appUi=*STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi());
appUi.UpdateStackedControlFlags(this, 0, ECoeStackFlagRefusesFocus);
appUi.HandleStackChanged();
The following code causes the FEP’s control to revert to normal operation by losing focus:
CCoeAppUi& appUi=*STATIC_CAST(CCoeAppUi*, iCoeEnv->AppUi());
appUi.UpdateStackedControlFlags(this, ECoeStackFlagRefusesFocus, ECoeStackFlagRefusesFocus);
appUi.HandleStackChanged();
Adding the FEP’s control to the control stack at priority
ECoeStackPriorityFep
means that it gets first refusal of all key
events. The UI framework offers key events to the FEP control by calling its
OfferKeyEventL()
virtual function (although key events for a FEP
over an OPL application follow a different route, described below). The
signature of this virtual function, which is first declared in
CCoeControl
, is:
TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType);
The first thing that should be done at the start of
OfferKeyEventL()
is to call either of the two macros below, both
of which are defined in epoc32\include\FEPBASE.H
:
#define FEP_START_KEY_EVENT_HANDLER_L(aFep, aKeyEvent, aEventCode)
#define FEP_START_KEY_EVENT_HANDLER_NO_DOWN_UP_FILTER_L(aFep, aKeyEvent, aEventCode)
The aFep
parameter must be a CCoeFep
object. Note that it should not be a pointer to a CCoeFep
.
The aKeyEvent
and the aEventCode
parameters should be
respectively the TKeyEvent
and the
TEventCode
parameters of the OfferKeyEventL()
function itself. The OfferKeyEventL()
function should only be
returned from by calling either of the following two macros (these are also
defined in epoc32\include\FEPBASE.H
):
#define FEP_END_KEY_EVENT_HANDLER_L(aFep, aKeyEvent, aKeyResponse)
#define FEP_END_KEY_EVENT_HANDLER_NO_DOWN_UP_FILTER_L(aFep, aKeyEvent, aEventCode, aKeyResponse)
Both of these two macros contain a return
statement, so
the return
C++ keyword should not occur in the
OfferKeyEventL()
function at all. Note that the macro used at the
start of the OfferKeyEventL()
function should match the macro used
to return from it; in other words, both should be of the
no-down-up-filter type or neither should be. The
no-down-up-filter variants should be used if the FEP wishes to
handle EEventKeyDown
or EEventKeyUp
events. This is
likely to be rare, however; most FEPs are probably only interested in
EEventKey
events, in which case
FEP_START_KEY_EVENT_HANDLER_L
and
FEP_END_KEY_EVENT_HANDLER_L
should be used. These variants filter
out EEventKeyDown
and EEventKeyUp
events so that the
FEP only receives EEventKey
events.
The first three parameters of the
FEP_END_KEY_EVENT_HANDLER_
XXX macros are the same
as for the FEP_START_KEY_EVENT_HANDLER_
XXX
macros. The fourth parameter should be a TKeyResponse
value (an enum defined in epoc32\include\COEDEF.H
). Specifying
EKeyWasNotConsumed
as this fourth parameter allows that key event
to 'fall through' to the application, whereas specifying
EKeyWasConsumed
prevents the application from receiving that
event. A good rule of thumb for a FEP that takes key events as its input is to
intercept as few key events as possible when not inside a FEP transaction, but
once inside a transaction to block all key events from getting through to the
application. A transaction may be defined as the composition and
abandoning/committing of a piece of text ('committing' means sending it on to
the application). For a Japanese FEP, that piece of text may be an entire
sentence, whereas for a Chinese FEP it may be just one or two characters.
For a FEP running over an OPL application, the
OfferKeyEventL()
virtual function declared in
CCoeFep
will get called. This is a completely independent
function from CCoeControl
’s virtual function of the same
name, and it has a different signature which is as follows:
void OfferKeyEventL(TEventResponse& aEventResponse, const TKeyEvent& aKeyEvent, TEventCode aEventCode);
This virtual function should be implemented in exactly the same way as
CCoeControl
’s OfferKeyEventL()
, the meaning
of the aKeyEvent
and aEventCode
parameters being the
same as for CCoeControl
’s OfferKeyEventL()
.
The aEventResponse
parameter should be set by the function
overriding CCoeFep::OfferKeyEventL()
to either
CCoeFep::EEventWasNotConsumed
or
CCoeFep::EEventWasConsumed
, and this must be done before any
function that can leave is called.