Input Method Engine SPI Tutorial (original) (raw)
Contents
- Introduction
- Describing the Input Method
- Communicating with the Client Component
- Using Input Method Windows
- Implementing Composition
- Providing Engine-Specific Functionality
- Packaging the Input Method
- 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 JRE. As far as the input method framework is concerned, an input method consists of two classes implementing theInputMethodDescriptor
and InputMethod
interfaces, packaged with some additional information as an extension and installed into a Java runtime. The specifications for the [java.awt.im.spi](../../../api/java/awt/im/spi/package-summary.html#package%5Fspecification)
package, and the [InputMethodDescriptor](../../../api/java/awt/im/spi/InputMethodDescriptor.html)
and [InputMethod](../../../api/java/awt/im/spi/InputMethod.html)
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 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](../../../api/java/awt/im/spi/InputMethodDescriptor.html)
class. This information is used in selecting input methods.
The list of available locales returned by [getAvailableLocales](../../../api/java/awt/im/spi/InputMethodDescriptor.html#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](../../../api/java/util/Locale.html#SIMPLIFIED%5FCHINESE)
, 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[InputMethod.setLocale](../../../api/java/awt/im/spi/InputMethod.html#setLocale-java.util.Locale-)
method on the other hand may return true for a larger set of languages. The reason is thatgetAvailableLocales
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, whilesetLocale
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](../../../api/java/awt/im/spi/InputMethodContext.html)
instance through [setInputMethodContext](../../../api/java/awt/im/spi/InputMethod.html#setInputMethodContext-java.awt.im.spi.InputMethodContext-)
. 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 [dispatchInputMethodEvent](../../../api/java/awt/im/spi/InputMethodContext.html#dispatchInputMethodEvent-int-java.text.AttributedCharacterIterator-int-java.awt.font.TextHitInfo-java.awt.font.TextHitInfo-)
method. And it lets the input method request information from the client component using the methods it inherits from the [InputMethodRequests](../../../api/java/awt/im/InputMethodRequests.html)
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:
- a look-up window, which shows several possible interpretations of the user's input and lets the user choose the correct one.
- a status window, which provides the user with information about the current state of the input method, such as the selected language or target character set.
- a control panel (often combined with the status window), which lets the user change the input method's state, such as selecting a different language or target character set.
- a preferences window, which lets the user tailor the input method to his or her needs.
- a dictionary editor window, which lets the user add or correct conversions.
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:
- transient windows: these windows pop up for short times during a composition operation. Their functionality is tied to a specific composition. Opening, closing, positioning, and sizing are usually automatic since any user interaction with the windows themselves would distract from the composition. In particular, transient windows are always closed when the composition operation ends or is interrupted. Examples: look-up window.
- persistent windows: these windows tend to stay around for extended periods of time, possibly for as long as the user is using the input method. Their functionality may be tied to the currently active instance of the input method, or to the input method class. Usually the user can actively open, close, position, and possibly resize these windows, although they are always automatically closed when switching to a different input method, and in some cases they're automatically positioned relative to the window containing the current client component. Examples: status window, control panel.
- document windows: these are just regular windows. Their functionality is not tied to composition. The user fully controls opening, closing, positioning, and possibly sizing of these windows. Examples: dictionary editor window.
Here's how these window groups can be handled by input methods:
- transient windows are created using
[InputMethodContext.createInputMethodWindow](../../../api/java/awt/im/spi/InputMethodContext.html#createInputMethodWindow-java.lang.String-boolean-)
, typically withattachToInputContext
set to true. They are opened either in the input method's implementation of[activate](../../../api/java/awt/im/spi/InputMethod.html#activate--)
, or later when needed to respond to user input. They are closed in the input method's implementations of[deactivate](../../../api/java/awt/im/spi/InputMethod.html#deactivate-boolean-)
or[hideWindows](../../../api/java/awt/im/spi/InputMethod.html#hideWindows--)
, or earlier if they are no longer needed. - persistent windows are created using
[InputMethodContext.createInputMethodWindow](../../../api/java/awt/im/spi/InputMethodContext.html#createInputMethodWindow-java.lang.String-boolean-)
, withattachToInputContext
set to false. They are typically opened in the input method's implementation of[activate](../../../api/java/awt/im/spi/InputMethod.html#activate--)
and closed in the input method's implementation of[hideWindows](../../../api/java/awt/im/spi/InputMethod.html#hideWindows--)
. - document windows are created as regular AWT windows, and opening and closing them is usually under user control.
Note that the focus behavior of a window created bycreateInputMethodWindow
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](../../../api/java/awt/im/InputMethodRequests.html#getTextLocation-java.awt.font.TextHitInfo-)
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](../../../api/java/awt/im/spi/InputMethodContext.html#enableClientWindowNotification-java.awt.im.spi.InputMethod-boolean-)
method; it then has to implement the [notifyClientWindowChange](../../../api/java/awt/im/spi/InputMethod.html#notifyClientWindowChange-java.awt.Rectangle-)
method to receive notifications.
Input methods must call Window.disposefor all windows they create when they are no longer needed. This ensures that the JVM exits when the application terminates all non-daemon threads it started. Please refer to AWT Threading Issues for more information.
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](../../../api/java/awt/im/spi/InputMethod.html#activate--)
and [deactivate](../../../api/java/awt/im/spi/InputMethod.html#deactivate-boolean-)
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 [dispatchEvent](../../../api/java/awt/im/spi/InputMethod.html#dispatchEvent-java.awt.AWTEvent-)
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[InputMethodContext.dispatchInputMethodEvent](../../../api/java/awt/im/spi/InputMethodContext.html#dispatchInputMethodEvent-int-java.text.AttributedCharacterIterator-int-java.awt.font.TextHitInfo-java.awt.font.TextHitInfo-)
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](../../../api/java/awt/font/TextAttribute.html#INPUT%5FMETHOD%5FHIGHLIGHT)
key and instances of [InputMethodHighlight](../../../api/java/awt/im/InputMethodHighlight.html)
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](../../../api/java/awt/Toolkit.html#mapInputMethodHighlight-java.awt.im.InputMethodHighlight-)
.
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](../../../api/java/awt/im/spi/InputMethod.html#endComposition--)
method. Note that endComposition
may be called while the input method is not active.
Client components can influence composition using several methods. The [InputContext.setCharacterSubsets](../../../api/java/awt/im/InputContext.html#setCharacterSubsets-java.lang.Character.Subset:A-)
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](../../../api/java/awt/im/InputContext.html#setCompositionEnabled-boolean-)
and [isCompositionEnabled](../../../api/java/awt/im/InputContext.html#isCompositionEnabled--)
methods let them control and examine whether the current input method is enabled for composition. The [InputContext.reconvert](../../../api/java/awt/im/InputContext.html#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](../../../api/java/awt/im/spi/InputMethod.html#getControlObject--)
. Client components that want to take advantage of the additional functionality can then call [InputContext.getInputMethodControlObject](../../../api/java/awt/im/InputContext.html#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 "Packaging 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.
- City Input Method documentation - tells you how to install and use this input method.
- City Input Method - a jar file containing the input method. Some browsers will automatically offer to download this file; others will show its contents in a window (not a pretty sight), and you then have to use the Save command to write it into a file. See the documentation for installation instructions.
- CityInputMethodDescriptor.java- the InputMethodDescriptor implementation for this input method.
- CityInputMethod.java - the InputMethod implementation for this input method.