Input Method Engine SPI Tutorial


Contents

  1. Introduction
  2. Describing the Input Method
  3. Communicating with the Client Component
  4. Using Input Method Windows
  5. Implementing Composition
  6. Providing Engine-Specific Functionality
  7. Packaging the Input Method
  8. Sample Code


1. Introduction

The input method engine SPI enables the development of input methods in the Java programming language that can be used with any Java 2 runtime environment. As far as the input method framework is concerned, an input method consists of two classes implementing the InputMethodDescriptor and InputMethod interfaces, packaged with some additional information as an extension and installed into a Java runtime. The specifications for the package, and the InputMethodDescriptor and InputMethod interfaces provide the core information that's needed to implement an input method. This tutorial provides additional information that makes this task a little easier and helps avoid compatibility problems between different implementations of the Java 2 platform.

2. Describing the Input Method

Before the input method framework can start using an input method, it needs to know about its capabilities. The necessary information is provided by the input method's implementation of the InputMethodDescriptor class. This information is used in selecting input methods.

The list of available locales returned by getAvailableLocales should only return languages that the input method is really designed for. For example, a Chinese Pinyin input method that produces simplified Chinese characters should only return SIMPLIFIED_CHINESE, even if it has a mode that simply lets key events pass through and thus also makes it possible to write English or Malay. The java.util.Locale)">InputMethod.setLocale method on the other hand may return true for a larger set of languages. The reason is that getAvailableLocales is used to decide whether to load and switch to an input method, which is only worthwhile if the input method handles the language well, while setLocale is used to decide whether to switch away from an input method, which is only worthwhile if the input method doesn't handle the language at all.

3. Communicating with the Client Component

When an input method instance is created, it receives an InputMethodContext instance through setInputMethodContext. This instance provides it with all the functionality that it needs to communicate with the input method framework, the client component, or the composition window. It lets the input method send information about composed and committed text using the java.text.AttributedCharacterIterator, int, java.awt.font.TextHitInfo, java.awt.font.TextHitInfo)">dispatchInputMethodEvent method. And it lets the input method request information from the client component using the methods it inherits from the InputMethodRequests interface.

The input method framework provides the input method with an environment that makes it seem like it is always communicating with an active client component using the on-the-spot input style. If the actual client component is not an active client, or if a different input style is used, then the framework redirects events and requests as needed.

The input method should never try to access the client component directly, as doing so would conflict with the framework's switching and redirection functionality. Instead, the input method should always use the methods provided by its input method context.

4. Using Input Method Windows

Input methods may use a number of different windows to communicate with the user. Windows commonly used by input methods include:

Note: On some other platforms, input methods may also provide a composition window, which shows the composed text. In the Java input method framework, composed text is always displayed by the client component or the input method framework, never by the input method.

It is useful to consider three groups of windows:

Here's how these window groups can be handled by input methods written for the Java 2 platform:

Note that the focus behavior of a window created by createInputMethodWindow is implementation dependent. It may never get the focus, it may get the focus when initially made visible, or it may get the focus when the user clicks into it. An input method must be able to handle either case.

To position windows (such as the look-up window) automatically relative to the composed text, the input method can use the input method context's getTextLocation method. To position windows (such as a status window) automatically relative to the window containing the current client component, the input method can register for notifications about that window's location and state using the input method context's enableClientWindowNotification method; it then has to implement the notifyClientWindowChange method to receive notifications.

5. Implementing Composition

The main task of an input method is interpreting user actions in composing text input. The user actions may be typing on the keyboard, using the mouse, handwriting, or speaking.

The activate and deactivate methods indicate to the input method whether a client component has the focus and therefore is the target of text input. Typically input methods only process events to compose text while they're active.

When an input method is active, certain types of events are dispatched to the input method using the java.awt.AWTEvent)">dispatchEvent method before they are processed by the client component. The input method decides for each event whether it wants to handle it. If it does, it marks the event as consumed so that it is not processed by the client component.

Note: For key events, input methods should use only KEY_TYPED events to obtain information about characters being entered, and use KEY_PRESSED or KEY_RELEASED events only to obtain information about function keys that don't result in KEY_TYPED events. The mapping from key-presses to characters depends on platforms, hardware, locales, and possibly other factors, and is best left to the underlying operating system.

As text is being composed and committed, the input method needs to inform the client component about all changes so that the client component can redraw the text. The input method does this by using java.text.AttributedCharacterIterator, int, java.awt.font.TextHitInfo, java.awt.font.TextHitInfo)">InputMethodContext.dispatchInputMethodEvent to construct and dispatch input method events to the client component. Depending on the current event flow model, the input method framework may redirect the events to its composition window. Dispatching input method events is the only way for Java input methods to have composed text displayed.

Composed text is usually marked up with highlight styles that indicate the current state of the conversion. This is accomplished by adding attributes to the text using the TextAttribute.INPUT_METHOD_HIGHLIGHT key and instances of InputMethodHighlight as values. Normally input methods only define abstract highlights (using the state and selected properties of the input method highlight) and leave the mapping to concrete styles to the rendering system. However, if desired, input methods can add concrete style information to the highlight using the style property. It is a good idea to design the concrete styles as variations of the styles provided returned by Toolkit.mapInputMethodHighlight.

Both the client component and the input method framework may recognize situations where the current composition needs to be ended and all composed text either committed or cancelled. They inform the input method about this need using the endComposition method. Note that endComposition may be called while the input method is not active.

Client components can influence composition using several methods. The java.lang.Character.Subset[])">InputContext.setCharacterSubsets method lets them restrict the subset of the Unicode character set that the input method is allowed to input. Input methods should generally not create characters outside of the specified subsets, and may switch to a different input mode that particularly supports the specified character subsets. The InputContext.setCompositionEnabled and isCompositionEnabled methods let them control and examine whether the current input method is enabled for composition. The InputContext.reconvert method lets them initiate reconversion.

6. Providing Engine-Specific Functionality

Some input methods may want to provide functionality to client components that can not be made available through the input method framework API. This is possible through input method control objects. The input method developer must publish an interface for these objects, and return instances through InputMethod.getControlObject. Client components that want to take advantage of the additional functionality can then call InputContext.getInputMethodControlObject, check whether the returned object is an instance of a known control object class, and if it is, call its methods.

7. Packaging the Input Method

Input methods are packaged as installed extensions with specific content as described in the Input Methods" section of the SPI specification. One important aspect to consider is that all extensions installed in a Java application environment share the same name space. To avoid name collisions, input methods should follow the package naming conventions as described in the Java Language Specification. Similar conventions should be applied to naming non-class files that are packaged in the input method JAR file, such as dictionaries.

8. Sample Code

City Input Method is a simple input method that shows how to use the interfaces provided by the input method engine SPI.