Documentation  |   Table of Contents   |  < Previous   |  Next >   |  Index

2    Working with the Dynamic Input Area

Input Services

Exploring Palm OS®

This chapter describes how applications may interact with the dynamic input area. It covers:

Checking the Dynamic Input Area Features
Programmatically Opening and Closing the Input Area
Interacting with Pinlets

Although dynamic input areas are not new to Palm Powered devices, Palm OS® Cobalt version 6.0 provides the first built-in support for dynamic input areas.

This chapter does not cover how an application's windows should resize when the user opens and closes the input area; it covers how an application might want to control the input area itself. See Exploring Palm OS: User Interface for information about resizing your application.

Checking the Dynamic Input Area Features ^TOP^

Before you can use any of the API described in this chapter, you must make sure that the dynamic input area API is available. Test the pinFtrAPIVersion feature as shown in Listing 2.1.

Listing 2.1  Checking the dynamic input area feature


err = FtrGet(pinCreator, pinFtrAPIVersion, &version); 
if (!err && version) { 
   //dynamic input area exists 
} 

If this feature is defined, a manager called the Pen Input Manager controls the input area and notifies the application of any changes in the input area state.

Do not assume that if this feature is not present, the device has a static input area. Some devices have no input area at all. For example, the Handspring Treo has a built-in keyboard and thus forgoes having any input area altogether. All textual user input is typed. On devices that don't have the dynamic input area, the API described in this chapter has no effect.

If you need more information, the sysFtrNumInputAreaFlags feature indicates the device-specific capabilities of the input area (see Listing 2.2). "Input Area Flags Constants" defines the flags that may be set in this feature constant.

Listing 2.2  Checking the input area capabilities


err = FtrGet(sysFtrCreator, sysFtrNumInputAreaFlags,  
   &inputAreaFlags); 
if (!err) { 
   if (inputAreaFlags & grfFtrInputAreaFlagDynamic) 
      // device has dynamic input area 
   if (inputAreaFlags & grfFtrInputAreaFlagLiveInk) 
      // device supports live ink 
   if (inputAreaFlags & grfFtrInputAreaFlagCollapsible) 
      // dynamic input area is collapsible.  
} 

Programmatically Opening and Closing the Input Area ^TOP^

In rare cases, it may be beneficial for a form to open the input area when the form itself is opened. For example, a password dialog might open the input area while the form is opened to save the user a tap. If your application has a form that requires text input (rather than simply having the ability to receive text input), you might also want to open the input area when the form is opened. Only do this if you're certain the user is always going to use the form for text input and never to read what was previously entered.

Opening and closing the input area is controlled by setting the input area state. The function PINSetInputAreaState() sets the input area state. Call this function in response to the winFocusGainedEvent. Be sure to preserve the previous input area state and restore it when your form is closed. See Listing 2.3.

Listing 2.3  Example of a form controlling input area state


uint16_t userInputAreaState = 0; 
case winFocusGainedEvent: 
   if (eventP->data.winFocusGained.window ==  
         FrmGetWindowHandle(frmP)) { 
      //First, preserve the current input area state,  
      //which is likely to be the one the user prefers. 
      userInputAreaState = PINGetInputAreaState(); 
      PINSetInputAreaState(pinInputAreaOpen); 
   } 
   break; 
 
case frmCloseEvent: 
   PINSetInputAreaState(userInputAreaState); 
   break; 


IMPORTANT: Be careful not to set the input area state too much. If the input area is opened and closed automatically in too many instances, the result may be a jumpy user interface that produces a jarring user experience. It is best to let your users decide what they want to do.

You should open the input area in response to winFocusGainedEvent to allow for the possibility that a dialog displayed by another process, such as a system dialog or a slip window, might close it. When the dialog is dismissed and control returns to your application, you then might need to reopen (or reclose) the input area. You won't receive a frmLoadEvent or frmOpenEvent because your form is already loaded and opened. Instead, you'll get the winFocusGainedEvent. Well-behaved dialogs that enforce a certain input state should restore the input area state when they are closed (as shown in Listing 2.3), so you should never encounter a situation where you need to re-open the input area after a dialog is displayed; however, to be on the safe side, open the input area in winFocusGainedEvent.

Interacting with Pinlets ^TOP^

A pinlet is a module with a user interface that displays in the input area. A pinlet's purpose is to receive pen events in the input area and translate them into character data.

There are two basic types of pinlets. A handwriting recognition pinlet converts user pen strokes to characters using either the Graffiti® 2 engine or some other handwriting recognition software (see Figure 2.1).

Figure 2.1  Handwriting recognition pinlet

A keyboard pinlet provides a set of buttons that the user taps to enter a corresponding character (see Figure 2.2).

Figure 2.2  Keyboard pinlet

On devices with a dynamic input area, there is at least one pinlet available, and there may be several others. The button on the status bar that controls whether the input area is opened or closed also controls which pinlet is active. If the user holds the pen down on that button, it displays a menu from which the user can choose a new pinlet (see Figure 2.3).

Figure 2.3  Changing the active pinlet

Users can also switch between the default handwriting recognition pinlet and the default keyboard pinlet by pressing the buttons shown on the right side of the PalmSource-provided handwriting recognition and keyboard pinlets.

Applications typically do not need to interact with the pinlet. Your application receives the character data that the pinlet produces in the form of keyDownEvents. If your application does need information from or about a pinlet, it uses calls to Pen Input Manager to obtain that information. The next several sections describe how an application might interact with the pinlet through the Pen Input Manager:

Changing the Active Pinlet
Querying Alternative Input Systems
Setting the Pinlet Input Mode

Changing the Active Pinlet ^TOP^

An application might want to control which pinlet is active. To do so, it can call PINSwitchToPinlet(). Before it can do so, it must know which pinlets are available. Applications can use the following functions:

  • PINGetCurrentPinletName() returns the name of the currently active pinlet.
  • PINGetPinletInfo() returns the name or the kind of a specific pinlet. This function references a pinlet by its index in the Pen Input Manager's pinlet list. An application can call PINCountPinlets() to obtain the upper limit for the pinlet list.

Suppose an application wants to ensure that the pinlet used with it is a keyboard pinlet. It might contain code similar to that shown in Listing 2.4.

Listing 2.4  Switching to a keyboard pinlet


uint16_t index = 0; 
uint32_t info; 
char *activePinlet; 
Boolean found = false; 
 
// First find a keyboard pinlet.  
while (!found && (index < PINCountPinlets())) { 
   PINGetPinletInfo(index, pinPinletInfoStyle, &info); 
   if (info == pinPinletStyleKeyboard) { 
      found = true;  
   } else { 
      index++; 
   } 
} 
// We now need to see if we need to change pinlets.  
if (found) { 
   PINGetPinletInfo(index, pinPinletInfoComponentName,  
		&info); 
   activePinlet = PINGetCurrentPinletName(); 
   if (strcmp((char *)info, activePinlet)) { 
      // If the names are different, we need to switch. 
      PINSwitchToPinlet((const char *)info,  
         pinInputModeNormal); 
   } 
} 

Querying Alternative Input Systems ^TOP^

Many Palm Powered devices come with hardware solutions for text entry. These solutions are called alternative input systems because they are not controlled using the Pen Input Manager.

The primary example of an alternative input system is a detachable keyboard that is sold separately from the device, like the keyboards available for many Palm handhelds. The alternative input system is not required to be a keyboard. In the future, it may be some other sort of device such as a speech recognizer. The requirements for an input system to be considered an "alternative input system" are:

  • It must be a way for the user to enter textual data. A jog dial is not an alternative input system.
  • It must be on a device with an input area. The keyboard on a Handspring Treo is not an alternative input system because there is no other input system available on that device.

Applications might want to decide to open or close the input area based on whether an alternative is available. For example, a password dialog might want to open the dynamic input area to ensure that the user has a means of entering the password, but before it does so, it could check for an alternative input system using PINAltInputSystemEnabled(). If that function returns true, it could leave the input area state closed because the user already has a means of entering data.

If you use PINAltInputSystemEnabled() to decide when to open or close the input area, you should also register to receive the notifications sysNotifyAltInputSystemEnabled and sysNotifyAltInputSystemDisabled to account for the fact that users might attach or detach this alternative input system while your dialog is being displayed. See Listing 2.5.

Listing 2.5  Registering for alternative input system notifications


uint32_t PilotMain(uint16_t cmd, MemPtr, cmdPBP,  
  uint16_t launchFlags) 
{ 
  ... 
  case sysAppLaunchCmdNormalLaunch: 
    SysNotifyRegister(appDBID, 
        sysNotifyAltInputSystemEnabled, NULL, 
        sysNotifyNormalPriority, NULL, 0); 
    SysNotifyRegister(appDBID,  
        sysNotifyAltInputSystemDisabled, NULL,  
        sysNotifyNormalPriority, NULL, 0); 
    ... 
    break; 
  case sysAppLaunchCmdNotify: 
    if (cmdPBP->notify->notifyType ==  
        sysNotifyAltInputSystemEnabled) 
      PINSetInputAreaState(pinInputAreaClosed); 
    else if (cmdPBP->notify->notifyType ==  
        sysNotifyAltInputSystemDisabled) 
      PINSetInputAreaState(pinInputAreaOpen); 
    ... 
    break; 
} 

Setting the Pinlet Input Mode ^TOP^

The input mode specifies how the pinlet converts the next set of strokes into characters. For example, in the normal input mode on an ISO Latin device, strokes are converted to lowercase letters. If the mode is set to shift, the next stroke is converted into an uppercase letter as if the user has pressed the Shift key on a keyboard. For Japanese systems, the input mode indicates whether the input is in Hiragana or Katakana characters.

Note that the input mode is different from the FEP mode. The Graffiti 2 handwriting recognition engine does not use Hiragana or Katakana input modes; however, on some Japanese devices writing Graffiti 2 strokes generates Hiragana or Katakana character, but that is dependent on the FEP mode, not the pinlet input mode. The same devices might have a Japanese keyboard pinlet that does use the Hiragana and Katakana input modes.

The function PINSetInputMode() sets the pinlet input mode, and PINGetInputMode() retrieves the current input mode.

The user interface elements use PINSetInputMode() to set the shift state automatically. On most ISO Latin 1 devices, the state is set automatically to Shift mode after a period or other sentence terminator followed by a space.

Note that the auto-shifting rules are language-specific, since capitalization differs depending on the region. These rules depend on the version of the ROM, the market into which the device is being sold, and so on.

Earlier releases of Palm OS used something called the shift state for the same purpose for which the input mode is now used. You placed a shift indicator (GSI) on all forms that contained an editable text field to show the shift state. If there is a dynamic input area, the pinlet displays its own indication of what the input mode is. However, your forms should still define a GSI to allow for devices with static input areas or no input areas. The GSI is disabled for you if a dynamic input area is present.

Summary ^TOP^