Symbian3/SDK/Source/GUID-CFC70204-1AD4-5DF0-ADDC-CDE4B39CFF96.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"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:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-CFC70204-1AD4-5DF0-ADDC-CDE4B39CFF96" xml:lang="en"><title>Simulating
and intercepting key events</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<section id="GUID-EC0588AB-A48E-42A8-A149-315B36DBE493"><title>Simulating
key events</title> <p>Simulating key events is done by calling <xref href="GUID-ADAA039A-7BF3-3B06-8486-2E3604C2633D.dita"><apiname>CCoeFep</apiname></xref> ’s
member function <codeph>SimulateKeyEventsL()</codeph>; this sends to the application
a key event for each of the items in the array passed to it. There are two
overloads of <codeph>SimulateKeyEventsL()</codeph>: 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 <filepath>epoc32\include\E32KEYS.H</filepath> defines
the various modifiers possible. The FEP author needs to derive from <codeph>CCoeFep::MModifiedCharacter</codeph> in
order to use the second overload of <codeph>SimulateKeyEventsL()</codeph>,
implementing all three of its pure virtual functions. The <codeph>ModifierMask()</codeph> function
returns the modifiers whose value the FEP wishes to specify; the values for
the modifiers are returned by the <codeph>ModifierValues()</codeph> function. <codeph>ModifierValues()</codeph> should
not return values for any modifiers that are not also returned by <codeph>ModifierMask()</codeph>. </p> <p>For
example, supposing a FEP wishes to send a key event to an application with
the <userinput>func</userinput> modifier on and the <userinput>shift</userinput> modifier
off. In this case the <codeph>ModifierMask()</codeph> function would return <codeph>EModifierFunc|EModifierShift</codeph> and
the <codeph>ModifierValues()</codeph> function would return <codeph>EModifierFunc</codeph>.
The resulting key event received by the application would then have the <codeph>EModifierFunc</codeph> modifier
on and the <codeph>EModifierShift</codeph> 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 <codeph>ModifierMask()</codeph> function, will
reflect the current state of the keyboard. </p> </section>
<section id="GUID-1B15C661-851B-5922-B8BC-7A772232DBD2"><title>Intercepting
key events</title> <p>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: </p> <codeblock id="GUID-1734E8DC-BB49-5EB9-B373-F8B4A8B92809" xml:space="preserve">STATIC_CAST(CCoeAppUi*, iCoeEnv-&gt;AppUi())-&gt;AddToStackL(this, ECoeStackPriorityFep, ECoeStackFlagRefusesFocus|ECoeStackFlagSharable);</codeblock> <p>and the following code in its destructor: </p> <codeblock id="GUID-D5BF8AAB-6BEA-5CF5-AE66-488CC2C44654" xml:space="preserve">STATIC_CAST(CCoeAppUi*, iCoeEnv-&gt;AppUi())-&gt;RemoveFromStack(this);</codeblock> <p>Passing the flag <codeph>ECoeStackFlagSharable</codeph> to <codeph>AddToStackL()</codeph> 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 <codeph>ECoeStackFlagRefusesFocus</codeph> flag
should be passed to <codeph>AddToStackL()</codeph> because FEPs in general
should not “steal” focus from the target underneath them. For the same reason, <codeph>SetNonFocusing()</codeph> (a
member function of <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref>) 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: </p> <codeblock id="GUID-183A9459-B8F1-5D7F-897E-3B5278B8BEE1" xml:space="preserve">CCoeAppUi&amp; appUi=*STATIC_CAST(CCoeAppUi*, iCoeEnv-&gt;AppUi());
appUi.UpdateStackedControlFlags(this, 0, ECoeStackFlagRefusesFocus);
appUi.HandleStackChanged();
</codeblock> <p>The following code causes the FEP’s control to revert to normal
operation by losing focus: </p> <codeblock id="GUID-D5C24301-9D84-5D62-9E75-4B17892316B2" xml:space="preserve">CCoeAppUi&amp; appUi=*STATIC_CAST(CCoeAppUi*, iCoeEnv-&gt;AppUi());
appUi.UpdateStackedControlFlags(this, ECoeStackFlagRefusesFocus, ECoeStackFlagRefusesFocus);
appUi.HandleStackChanged();
</codeblock> <p>Adding the FEP’s control to the control stack at priority <codeph>ECoeStackPriorityFep</codeph> means
that it gets first refusal of all key events. The UI framework offers key
events to the FEP control by calling its <codeph>OfferKeyEventL()</codeph> 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 <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref>, is: </p> <codeblock id="GUID-7823A4B2-AC86-502E-8609-9277F748C64F" xml:space="preserve">TKeyResponse OfferKeyEventL(const TKeyEvent&amp; aKeyEvent, TEventCode aType);</codeblock> <p>The first thing that should be done at the start of <codeph>OfferKeyEventL()</codeph> is
to call either of the two macros below, both of which are defined in <filepath>epoc32\include\FEPBASE.H</filepath>: </p> <codeblock id="GUID-84B500B8-7B35-5E6D-8C54-77AA59C4FCD7" xml:space="preserve">#define FEP_START_KEY_EVENT_HANDLER_L(aFep, aKeyEvent, aEventCode)
#define FEP_START_KEY_EVENT_HANDLER_NO_DOWN_UP_FILTER_L(aFep, aKeyEvent, aEventCode)
</codeblock> <p>The <codeph>aFep</codeph> parameter must be a <xref href="GUID-ADAA039A-7BF3-3B06-8486-2E3604C2633D.dita"><apiname>CCoeFep</apiname></xref> object.
Note that it should not be a pointer to a <xref href="GUID-ADAA039A-7BF3-3B06-8486-2E3604C2633D.dita"><apiname>CCoeFep</apiname></xref>. The <codeph>aKeyEvent</codeph> and
the <codeph>aEventCode</codeph> parameters should be respectively the <xref href="GUID-0F8FA6A3-F172-36E4-9CF5-60814ABCD562.dita"><apiname>TKeyEvent</apiname></xref> and
the <xref href="GUID-420348F5-4A82-3780-9D27-A3E1F4780F0B.dita"><apiname>TEventCode</apiname></xref> parameters of the <codeph>OfferKeyEventL()</codeph> function
itself. The <codeph>OfferKeyEventL()</codeph> function should only be returned
from by calling either of the following two macros (these are also defined
in <filepath>epoc32\include\FEPBASE.H</filepath>): </p> <codeblock id="GUID-AE03275F-FBD7-52AF-B7CC-C6F6707B9FDC" xml:space="preserve">#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)
</codeblock> <p>Both of these two macros contain a <codeph>return</codeph> statement,
so the <codeph>return</codeph> C++ keyword should not occur in the <codeph>OfferKeyEventL()</codeph> function
at all. Note that the macro used at the start of the <codeph>OfferKeyEventL()</codeph> function
should match the macro used to return from it; in other words, both should
be of the <i>no-down-up-filter</i> type or neither should be. The <i>no-down-up-filter</i> variants
should be used if the FEP wishes to handle <codeph>EEventKeyDown</codeph> or <codeph>EEventKeyUp</codeph> events.
This is likely to be rare, however; most FEPs are probably only interested
in <codeph>EEventKey</codeph> events, in which case <codeph>FEP_START_KEY_EVENT_HANDLER_L</codeph> and <codeph>FEP_END_KEY_EVENT_HANDLER_L</codeph> should be used. These variants filter out <codeph>EEventKeyDown</codeph> and <codeph>EEventKeyUp</codeph> events
so that the FEP only receives <codeph>EEventKey</codeph> events. </p> <p>The
first three parameters of the <codeph>FEP_END_KEY_EVENT_HANDLER_</codeph> <i>XXX</i> macros
are the same as for the <codeph>FEP_START_KEY_EVENT_HANDLER_</codeph> <i>XXX</i> macros.
The fourth parameter should be a <xref href="GUID-2AE56EA4-C71E-33FA-8FCE-D2D15453CD10.dita"><apiname>TKeyResponse</apiname></xref> value (an
enum defined in <filepath>epoc32\include\COEDEF.H</filepath>). Specifying <codeph>EKeyWasNotConsumed</codeph> as
this fourth parameter allows that key event to 'fall through' to the application,
whereas specifying <codeph>EKeyWasConsumed</codeph> 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. </p> <p>For
a FEP running over an OPL application, the <codeph>OfferKeyEventL()</codeph> virtual
function declared in <xref href="GUID-ADAA039A-7BF3-3B06-8486-2E3604C2633D.dita"><apiname>CCoeFep</apiname></xref> will get called. This is a
completely independent function from <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref> ’s virtual
function of the same name, and it has a different signature which is as follows: </p> <codeblock id="GUID-6760C373-FB46-53E5-96ED-A8273126B060" xml:space="preserve">void OfferKeyEventL(TEventResponse&amp; aEventResponse, const TKeyEvent&amp; aKeyEvent, TEventCode aEventCode);</codeblock> <p>This virtual function should be implemented in exactly the same way as <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref> ’s <codeph>OfferKeyEventL()</codeph>,
the meaning of the <codeph>aKeyEvent</codeph> and <codeph>aEventCode</codeph> parameters
being the same as for <xref href="GUID-B06F99BD-F032-3B87-AB26-5DD6EBE8C160.dita"><apiname>CCoeControl</apiname></xref> ’s <codeph>OfferKeyEventL()</codeph>.
The <codeph>aEventResponse</codeph> parameter should be set by the function
overriding <codeph>CCoeFep::OfferKeyEventL()</codeph> to either <codeph>CCoeFep::EEventWasNotConsumed</codeph> or <codeph>CCoeFep::EEventWasConsumed</codeph>, and this must be done before any function that can leave is called. </p> </section>
</conbody></concept>