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 the
InputMethodDescriptor
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
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 platform.
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
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.
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
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.
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:
InputMethodContext.createInputMethodWindow
, typically
with attachToInputContext
set to true. They are opened
either in the input method's implementation of activate
,
or later when needed to respond to user input. They are closed in
the input method's implementations of
deactivate
or hideWindows
,
or earlier if they are no longer needed.
InputMethodContext.createInputMethodWindow
, with
attachToInputContext
set to false. They are typically
opened in the input method's implementation of activate
and closed in the input method's implementation of hideWindows
.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.
Input methods must call Window.dispose for 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.
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
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
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
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.
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.
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.
City Input Method is a simple input method that shows how to use the interfaces provided by the input method engine SPI.