Next | Prev | Up | Top | Contents | Index

Input Contexts (ICs)

An input method may be serving multiple clients, or one client with multiple windows, or one client with multiple input styles on one window. The specification of style and client/IM communication is done via input contexts. An input context is simply a collection of parameters that together describe how to go about receiving and examining input under a given set of circumstances.

To set up and use an input context:

  1. Decide what styles your application can support.

  2. Query the IM to find out what styles it supports.

  3. Find a match.

  4. Determine information that the IC needs in order to work with your application.

  5. Create the IC.

  6. Employ the IC.

Find an IM Style

The IM may be able to support multiple styles--for example, both Off-the-Spot and Root Window. The application may be able to do, in order of preference, Over-the-Spot, Off-the-Spot, and Root Window. The application should determine that the best match in this case is Off-the-Spot.

First, discover what the IM can do, then set up a variable describing what the application can do, as shown in Example 6-8.

Example 6-8 : Finding What a Client Can Do

XIMStyles *IMcando;
XIMStyle  clientCanDo; /* note type difference */
XIMStyle  styleWeWillUse = NULL;
XGetImValues(im, XNQueryInputStyle, &IMcando, NULL);
clientCanDo =
/*none*/ XIMPreeditNone | XIMStatusNone |
/*over*/ XIMPreeditPosition | XIMStatusArea |
/*off*/  XIMPreeditArea | XIMStatusArea |
/*root*/ XIMPreeditNothing | XIMStatusNothing;
A client should always be able to handle the case of XIMPreeditNone | XIMStatusNone, which is likely in a Western locale. To the application, this is not very different from a RootWindow style, but it comes with less overhead.

Once you know what the application can handle, look through the IM styles for a match, as shown in Example 6-9.

Example 6-9 : Setting the Desired IM Style

for(i=0; i < IMcando->count_styles; i++) {
    XIMStyle tmpStyle;
    tmpStyle = IMcando->support_styles[i];
    if ( ((tmpStyle & clientCanDo) == tmpStyle) )
            styleWeWillUse = tmpStyle;
}
if (styleWeWillUse = NULL)
    exit_with_error();
XFree(IMcando);
/* styleWeWillUse is set, which is what we were after */

IC Values

There are several pieces of information an input method may require, depending on the input context and style chosen by the application. The input method can acquire any such information it needs from the input context, ignoring any information that does not affect the style or IM.

A full description of every item of information available to the IM is supplied in X Window System, Third Edition. The following is a brief list:

XNClientWindowSpecifies to the IM which client window it can display data in or create child windows in. Set once and cannot be changed.
XNFilterEventsAn additional event mask for event selection on the client window.
XNFocusWindowThe window to receive processed (composed) Key events.
XNGeometryCallbackA geometry handler that is called if the client allows an IM to change the geometry of the window.
XNInputStyleSpecifies the style for this IC.
XNResourceClass, XNResourceNameThe resource class and name to use when the IM looks up resources that vary by IC.
XNStatusAttributes, XNPreeditAttributesThe attributes to be used for any status and pre-edit areas (nested, variable-length lists).


Pre-Edit and Status Attributes

When an IM is going to provide state, it needs some simple X information with which to do its work. For example, if an IM is going to draw status information in a client window in an Off-the-Spot style, it needs to know where the area is, what color and font to render text in, and so on. The application gives this data to the IC for use by the IM.

As with the "IC Values" section, full details are available in X Window System, Third Edition.

XNAreaA rectangle to be used as a status or pre-edit area.
XNAreaNeededThe rectangle desired by the attribute writer. Either the application or the IM may provide this information, depending on circumstances.
XNBackgroundPixmapA pixmap to be used for the background of windows the IM creates.
XNColormapThe colormap to use.
XNCursorThe cursor to use.
XNFontSetThe fontset to use for rendering text.
XNForeground, XNBackgroundThe colors to use for rendering.
XNLineSpacingThe line spacing to be used in the pre-edit window if more than one line is used.
XNSpotLocationSpecifies where the next insertion point is, for use by XIMPreeditPosition styles.
XNStdColormapSpecifies that the IM should use XGetRGBColormaps() with the supplied property (passed as an Atom) in order to find out which colormap to use.


Creating an Input Context

Creating an input context is a simple matter of calling XCreateIC() with a variable-length list of parameters specifying IC values. Example 6-10 shows a simple example that works for the root window.

Example 6-10 : Creating an Input Context With XCreateIC()

XVaNestedList arglist;
XIC ic;
arglist = XVaCreateNestedList(0, XNFontSet, fontset,
                           XNForeground,
                           WhitePixel(dpy, screen),
                           XNBackground,
                           BlackPixel(dpy, screen),
                           NULL);
ic = XCreateIC(im, XNInputStyle, styleWeWillUse,
              XNClientWindow, window, XNFocusWindow, window,
              XNStatusAttributes, arglist,
              XNPreeditAttributes, arglist, NULL);
XFree(arglist);
if (ic == NULL)
    exit_with_error();

Using the IC

A multi-window application may choose to use several input contexts. But for simplicity, assume that the application just wants to get to the internationalized input using one method in one window.

Using the IC is a matter of making sure you check events the IC wants, and of setting IC focus. If you are setting up a window for the first time, you know the event mask you want, and you can use it directly. If you are attaching an IC to a previously configured window, you should query the window and add in the new event mask.

Example 6-11 : Using the IC

unsigned long imEventMask;
XGetWindowAttributes(dpy, win, &winAtts);
XGetICValues(ic, XNFilterEvents, &imEventMask, NULL);
imEventMask |= winAtts.your_event_mask;
XSelectInput(dpy, window, imEventMask);
XSetICFocus(ic);
At this point, the window is ready to be used.


Next | Prev | Up | Top | Contents | Index