Dynamic Behavior

This topic describes in detail the dynamic relationships between a keyboard driver, the Window Server, and related components.

What the keyboard driver does

The keyboard driver's job is to interpret keyboard presses and to generate key-up and key-down events. How the keyboard driver deals with the hardware depends to a great extent on that hardware, and also on whether the hardware generates interrupts as a result of key presses or whether the driver needs to poll the hardware at regular intervals.

The template Base port, which can be found at ...\cedar\template\..., gives two skeleton implementations, one for an interrupt driven implementation and one for a poll driven implementation. See Keyboard Driver Implementation Tutorial.

Whichever type is used, the end result is the addition of a stream of events onto the kernel's event queue. Events are represented by TRawEvent objects, and each one represents either a key-up or a key-down event, together with the scancode value for that key and the accompanying modifier key values, for example, Shift and Ctrl. The driver adds these events onto the kernel's event queue using Kern::AddEvent().

The general pattern, taken from the template keyboard driver, is as follows:

TRawEvent e;
...
e.Set(TRawEvent::EKeyUp,stdKey,0);
...
Kern::AddEvent(e);
TRawEvent e;
...
e.Set(TRawEvent::EKeyDown,stdKey,0);
...
Kern::AddEvent(e);

More generally, TRawEvent objects represent and encapsulate information about events such as screen pointer events, mouse events, etc. as well as keyboard key presses. Such events are mostly intended to result in a change to the device display(s) or the finer details of the User Interface, and for this reason, such events are captured by the Window Server.

The kernel event queue is a mechanism that allows this to happen. It is internal to Symbian platform, but to help you understand what happens, it works like this:

  • The kernel maintains a circular buffer of TRawEvent objects anchored in K::EventBufferStart, and this buffer is allocated at system initialization.

  • As part of its initialization, the Window Server calls the internal function UserSvr::CaptureEventHook(). This registers the Window Server's interest in capturing these events, and subsequent to this call, all such events are delivered to the Window Server. However, do note that the kernel does not permit any process other than the Window Server from registering to receive these events.

  • A call to Kern::AddEvent() causes a TRawEvent object to be added to this queue; the kernel subsequently attempts to deliver this to the Window Server.

  • The Window Server uses an active object to wait for and subsequently dispatch the handling of events (and most importantly, key press events). It makes a request for further events by a call to the internal function UserSvr::RequestEvent().

Figure 1. Dynamic Behavior

What the Window Server does

There are two services that the Window Server needs when dealing with key presses:

  • it needs a translation of a (hardware) scancode to a (Symbian platform or logical) keycode.

  • it needs to know whether a key and combination of modifier key states is a "hot-key", i.e. one that is intended to be sent to a specific window group, instead of the window group that currently has focus. Note that, in this context, a "hot-key" is more commonly referred to as a capture key.

To perform the translation, it creates an instance of a CKeyTranslator class.

To deal with capture keys, it creates an instance of a CCaptureKeys class.

Both classes are implemented in ektran.dll, the key translation DLL, which is built and delivered as part of the generic Symbian platform. The Window Server statically links to ektran.dll.

[Note that CKeyTranslator and CCaptureKeys are internal to Symbian platform and are not part of the public interface. This is an attempt to provide an outline understanding of the mechanisms involved.]

The Window Server also decides on the name of the key mapping tables DLL to be loaded. By default, the name of this DLL is ekdata.dll. However, if the Hardware Abstraction Layer (HAL) for the device records a language index, then this index value is used to form the name of the DLL to be loaded. For example, if the keyboard index value returned by a call to:

TInt keyboardIndex;
HAL::Get(HALData::EKeyboardIndex,keyboardIndex);

is 99, then the DLL loaded is ekdata99.dll.

The loading of this DLL is done by a member of CKeyTranslator, so although the Window Server decides which DLL is to be loaded, the actual loading is done by ektran.dll. For ease of explanation, we will continue to refer to this DLL as ekdata.dll.

On receipt of key-up and key-down events, the Window Server calls CKeyTranslator::TranslateKey(). This function takes the (hardware) scancode and translates it into the (logical) keycode. It also reports whether the key and combination of modifier key states is a capture key, and if so, returns the handle to the window group that is associated with it.

Before the Window Server can be told that a capture key has been pressed, it must previously have registered a pair of items:

  • the capture key itself, i.e. the (logical) keycode and combination of modifier key states.

  • a handle to a window group.

Registration is simply the act of adding this information into the CCaptureKey object by a call to CCaptureKeys::AddCaptureKeyL(). The Window Server does this as a result of a call to RWindowGroup::CaptureKey(), either by applications or the UI.