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.