Export to GitHub

networkpx - Creating_Keyboard_Bundles.wiki


(You should be familiar with Objective-C and the official iPhone SDK framework first.)

Fundamentals

In the iPhoneOS, the so-called keyboards or input modes are actually composed of 2 parts: the layout and the input manager

Layout

The layout is a view that interacts with user input and process commands with the keyboard implementation (UIKeyboardImpl). Layouts must be implemented as subclasses of UIKeyboardLayout, which in turn is a subclass of UIView.

The standard keyboard layouts you're using are all subclasses of the more specialized UIKeyboardLayoutRoman. It has several UIKeyboardSublayout members which does the actual rendering.

There are also layouts not derived from UIKeyboardLayoutRoman. The emoji keyboard is a prominent example.

Input Manager

An input manager is an abstract class that transforms key press commands to actual inputs. The auto-correction prompt is an input manager in action.

CJK keyboards usually rely on input managers because of the vast amount of characters.

Input managers are usually subclasses of UIKeyboardInputManager. If you're working with a standard keyboard layout, you should subclass the more specialized UIKeyboardInputManagerAlphabet. This class will automatically handle word frequency analysis for you.

If you are not subclassing from UIKeyboardInputManagerAlphabet, but wants to use a standard keyboard layout (including layout.plist method), you must implement the -(void)setShallowPrediction:(BOOL)sp message to avoid crashing.

Handwriting regconition is also the job of an input manager.

Keyboard Bundles

iKeyEx keyboard extensions are packaged in keyboard bundles. Keyboard bundles are simply directories (folders) with a definite structure, i.e. a bundle. All keyboard bundles must have an Info.plist file to describe themselves, for example.

Keyboard bundles must reside in /Library/iKeyEx/Keyboards/, and have an extension of .keyboard.

Example: The keyboard bundle for ℏClipboard is placed in /Library/iKeyEx/Keyboards/hClipboard.keyboard/

Note that the iPhoneOS file system is case sensitive. Make sure you follow the same capitalization for all files listed here.

Together with the "iKeyEx:" prefix, the file name will become the input mode name of the keyboard extension. It does not have to match the display name, since the latter will be specified in the Info.plist file.

The input mode name is used to uniquely identify a keyboard. For example, the English (US) keyboard's input mode name is en_US, Traditional Chinese Handwriting is zh_Hant-HWR, and ℏClipboard is iKeyEx:hClipboard.

The input mode name should only contain alphanumeric symbols, _ (underscore) and - (hyphen). iKeyEx uses input mode names starting with __ (2 underscores) for internal keyboards, so you should avoid using prefixing underscores in the mode name.

Info.plist

Info.plist is the description of the keyboard extension. It is a property list. Currently, iKeyEx recognizes the following keys:

struct <Info.plist> :: > key type meaning default depends CFBundleDisplayName string localizable string Display name of the keyboard. current input mode name -- UIKeyboardLayoutClass string <layout class> Layout class to use. To be described below. "=en_US" -- UIKeyboardInputManagerClass string <input manager class> Input manager class to use. To be described below. -- -- CFBundleExecutable string file path Binary file that contains all executable code file name UIKeyboardLayoutClass is dictionary of (string, class name) pairs
or UIKeyboardInputManagerClass is class name PSBundle string file path Sub-bundle that contains the preference pane. -- --

The display name will be shown when switching keyboards using the international button, and also in the Settings application. If missing, the file name will be used as the display name.

UIKeyboardLayoutClass

In iKeyEx the layout class can be specified in 3 ways: referred, layout.plist and writing code.

Referred means the layout of this keyboard will use an existing one. You fill in a string starting with "=", then the input mode name to inherit the layout.

If you want to use the standard QWERTY keyboard layout, fill in "=en_US" for this field.

layout.plist means the layout will be dynamically generated using the file in this field. It will be further discussed in (Developers) How to create layout.plist.

For total customization, you can write code yourself to manage the view. In this case, the CFBundleExecutable field should be filled, and the UIKeyboardLayout field should have a layout class name as value.

You can assign different layouts to portrait and landscape layouts using a dictionary with keys Landscape and Portrait.

Take 5-Row QWERTY as an example, both the Portrait and Landscape layouts are implemented by the two different classes, this field would be written as
UIKeyboardLayoutClass = {
Portrait = "FiveRowQWERTYLayout";
Landscape = "FiveRowQWERTYLayoutLandscape";
};

If this field is missing, the standard QWERTY keyboard will be used as layout.

union <layout class> ::
type meaning string `/^=/` Refered layout. string file path and `/\.plist$/` Specification for dynamically generated standard keyboard (layout.plist). string _class name_ Code-generated layout. dictionary {`Landscape` = ``; `Portrait` = ``} Use different layout class for landscape and portrait positions.

UIKeyboardInputManagerClass

Like UIKeyboardLayoutClass, this field also can be referred using the same "=xxx" syntax. You can also write the class name of your own input manager class here.

If this field is missing, no input managers will be used.

union <input manager class> ::
type meaning string `/^=/` Refered input manager. string class name Code-generated manager.

PSBundle

Use the PSBundle key to hook a preference pane. See source code of ℏClipboard and 5-Row QWERTY for detail.

-- TO BE DONE --

variants.plist

This is an optional file that specify the variants of each key, when you're using a referred layout, layout.plist or a subclass of UIKeyboardLayoutRoman.

Variants are the list of accented characters (e.g. Z Ź Ž Ż) you'll see when you hold a key (e.g. Z). It contains a dictionary of arrays which maps each key to the corresponding list. You can see the source code of MathTyper to understand how this file works.

Note that the variants are case-sensitive. You'll have to specify both the variants of a lower and upper case letter separately.

On Firmware 2.2, the variants for A, C, E, I, L, N, O, S, U, Y and Z will be automatically provided, so you don't need to write a variants.plist for it.

As an example, the variants.plist for European languages may be
{
A = ("A", "À", "Á", "Â", "Ä", "Æ", "Ã", "Å", "Ą");
a = ("a", "à", "á", "â", "ä", "æ", "ã", "å", "ą");
# etc.
}

You can provide an array to split label and actual output, e.g.

{
"w" = (w, ("www.wikipedia.org", wiki), www)
}
pairs <variants.plist> ::
type meaning **key** string Text to give the variants list. **value** array ...of ``s List of variants.
union <variant> ::
type meaning string Simple variant. Both label and actual output will use this same string. array ...of strings Variant with label and actual output being distinct.

strings.plist

This is an optional file that specify the localized strings of some common words, e.g. Return, Space, etc.

The format is the same as /System/Library/Frameworks/UIKit.framework/Keyboard-*.plist.

Localization

Since in essence keyboard bundles are just regular bundles, the resources can be localized like a regular bundle.

Please see the source code of ℏClipboard or consult relevant http://developer.apple.com/DOCUMENTATION/MacOSX/Conceptual/BPInternational/BPInternational.html'>Apple documents on how to localize resources.

Loading Keyboard Bundles

Keyboard bundles are handled in the KeyboardLoader module of iKeyEx. In case you want to refer to resources in the bundle, you can import <iKeyEx/KeyboardLoader.h>, and call the class method [KeyboardBundle activeBundle] to obtain the current KeyboardBundle object.

You can access the following properties in a KeyboardBundle:
Type Property name Usage UIKeyboardInputManager* | manager | The current UIKeyboardInputManager instance. | | Class | layoutClassPortrait | The current layout class in portrait orientation. | | Class | layoutClassLandscape | The current layout class in landscape orientation. | | NSString* | displayName | The localized display name. | | NSDictionary* | variants | The variants. | | NSBundle* | bundle | The underlying bundle object. |