June 15, 2009

Keyman 7.1.267.0

We've just released another update to Keyman Desktop and Keyman Developer.  In this version:

    • We add a fix for a minor Windows 7 compatibility issue.
    • We fix a couple of reported crashes, and an install issue on Vista that was rarely experienced.
    • We address some bugs in the On Screen Keyboard export and print functions (Did you know you could right-click on the On Screen Keyboard and print it in Keyman Desktop Pro?)
    • We finally fix the proxy issue which has been making life difficult for those behind a proxy server!
    • And finally, we have improved the User Interface Language dialog box by making new translations more easily accessible with the More Updates Online button.

The Keyman Developer update includes some fixes for the KeymanWeb Compiler.

Full details are available in the Keyman Version History.

You can get the full download from http://www.tavultesoft.com/70/download.php.  Patch updates will be available soon.   

May 25, 2009

KeymanWeb Updates

We have published an update to KeymanWeb, v 1.0 build 136.  This release makes the following updates:

  • The Alt key is now released in the On Screen Keyboard correctly.  This problem was especially evident previously when switching windows with Alt+Tab.
  • Firefox now scrolls input and textarea controls correctly when typing with KeymanWeb.
  • The On Screen Keyboard has some minor formatting changes:
    • The title "Tavultesoft KeymanWeb" is no longer a link - this had the potential for confusion and made it difficult to drag the On Screen Keyboard around.
    • The name of the active keyboard is now shown in the title bar.
    • The border colours are now more consistent.
    • The position of letters on the key caps has been tweaked.
    • The font size is no longer impacted by page-level font sizes.
  • KeymanWeb_Root variable is now ignored if a full path to a keyboard file is registered.
  • KeymanWeb_AttachType is now checked before attaching to dynamically created controls.
  • KeymanWeb now attaches correctly to dynamically created controls in Safari, Chrome and Firefox.

The update has been automatically deployed for KeymanWeb subscribers.

Some additional fixes have been made to the KeymanWeb compiler, which will be available as part of Keyman Developer build 7.1.266.0 and later versions shortly.

May 21, 2009

New Keyman Desktop user interface languages

We've just published a Brazilian Portuguese user interface translation for Keyman Desktop.  It can be accessed within Keyman Desktop with the following steps:

  1. Open Keyman Desktop Configuration.
  2. Click Options tab.
  3. Click User Interface Language button.
  4. Click More Languages Online button.
  5. Click Install on the Portuguese Brazilian entry.

We've also made it easier to translate the Keyman Desktop User Interface with an online translation form.  You can learn more about this at https://secure.tavultesoft.com/keyman/support/locale/

We are currently looking for the following translations (among others):

  1. Amharic
  2. An updated Tamil translation (the current translation is missing 30% of the entries)
  3. Someone to check a German translation
  4. Someone to check a Spanish translation

June 25, 2008

KeymanWeb Subscriptions recent updates

We've just made the following updates to the KeymanWeb Subscriptions beta:

  • Updated to build 128 - fixes an incompatibility with blogspot; build 127 fixed some issues with IFRAMEs in Internet Explorer
  • Added the popular Malayalam Mozhi keyboard layout

KeymanWeb Subscriptions are free to try for 30 days, and currently free for fewer than 3,000 pageviews per month.

June 24, 2008

Robust key message handling in Windows

Handling text input correctly when developing a Win32 application is not as simple as it could be.  The different types of messages don't seem to be all that well understood...  You need to manage quite a number of different, potentially conflicting types of input.

Flaws and legacy cruft in Windows' keyboard input design create some painful limitations -- attempts by application authors to work around these flaws have introduced a number of problems, some of which I discuss in the Pitfalls section at the end of this post.

I want to talk about 4 types of input, and how to create a robust (or at least consistent) way of differentiating and prioritising them:

  • Character input -- "abc" typed into a EDIT control
  • Shortcuts or accelerators -- up-arrow, Ctrl+X.  A shortcut is defined as modifier[s]+keystroke.
  • Access keys -- Alt+F for File menu.  An access key is defined as Alt+character, not Alt+keystroke.
  • Control keys -- backspace, enter, escape, etc.  These keys map to ASCII range 1-31 (and 127).

How does Keyman come into this?

You may know that I am the author of Keyman - a tool for creating much more sophisticated keyboard layouts than Windows provides.  However, nothing in this post relates to Keyman.  All of these issues are pure Windows - they don't involve Keyman at all.  But if you get this model right for Windows, then Keyman keyboards will also just work without any further issues.

What's the Problem?

As an example, I will use the English (United Kingdom) keyboard layout, the combination AltGr+O (AltGr is the same as the right alt key) and Microsoft Word.  I use Microsoft Word as it is probably the most widely used major application in the world -- and it's written by Microsoft.

Note: the AltGr modifier is regarded as identical to Ctrl+Alt by most Windows keyboards.  This is a holdover from the times when many keyboards did not include a right Alt key.  Most keyboards today do include the right Alt key, even many laptop keyboards.

So what does AltGr+O do?

  • The English United Kingdom keyboard layout defines that this combination is character input that will insert the ó character into your document.
  • Word thinks that Alt+O is an access key (either alt key) that opens the Format menu.
  • Word also thinks that Ctrl+Alt+O is a shortcut that will switch to Outline view.

Which one takes precedence?  And which one should take precedence?  Read on to find out the answer to both questions.

Shortcuts and Characters and Accelerators ... oh my

Unfortunately, there is no clear guidance on precedence between these three types of input.  Word does the following, which is fairly typical:

  • Shortcuts take precedence over characters - Ctrl+Alt+O switches to outline view
  • Characters take precedence over access keys - AltGr+O generates the ó character
  • Left Alt+O will open the Format menu.

That sounds almost like the best possible compromise.  But is it?  What if your computer does not have a right Alt key?  Should Ctrl+Alt+O insert ó or should it switch to Outline view?  I believe that Word's current precedence is wrong:

  • There is an alternative method for accessing Outline view through the menu system;
  • It is easy to redefine a particular shortcut if you really want to use it;
  • It is not easy to redefine your keyboard layout, and accessing the ó character through Insert|Symbol is painful.

Unfortunately, Windows does not make changing this precedence easy for application authors -- in fact, it is basically impossible to do it robustly.  So, to make the best of a bad situation, let's stick with what Word does - at least it is familiar to end users!

Clean input is simple

  1. Use the Windows message loop model of TranslateAccelerator/IsDialogMessage, TranslateMessage, DispatchMessage.  If you have your own shortcut management, use that in place of TranslateAccelerator.  Read up on message loops (but please, please, use threads rather than PeekMessage polling for lengthy operations - unlike "Examining a Message Queue").
  2. Understand what the different character messages are for:
  • WM_CHAR is a character.  Apart from a few special cases discussed below, these should always be inserted into the currently focused text area.
  • WM_SYSCHAR is a system character.  Pass it to the system to allow access keys to operate.  Never insert these characters into the currently focused text area.
  • WM_DEADCHAR is a notification message.  You can probably ignore it -- as most apps do.
  • WM_UNICHAR is a legacy compatibility message.  It allows you to receive Unicode input from certain utilities (notably Keyman) even on non-Unicode systems such as Win9x.  You do not need to use this message for modern, Unicode applications.

Special cases in character input

When a WM_CHAR message is received, there are a few character codes (in wParam) that should be handled as special cases:

8: backspace
9: tab
13: enter
27: escape
127: ctrl+backspace
all other codes < 32: typically, ignore these.

You may (quite sensibly) choose to ignore these at WM_CHAR time and instead process them in your WM_KEYDOWN handler.

Pitfalls to Avoid

I have seen examples of each of these errors in many projects, both open and closed source.  I'm not going to name any names -- many of the projects have since corrected these issues ... but not all.

I discovered most of these issues while debugging compatibility issues with Keyman for some projects, but I found that in all cases, these issues also impacted standard Windows keyboards.

 

  • Don't reinvent the wheel: avoid the temptation to use the keyboard information functions (MapVirtualKeyEx and related functions) to reimplement the WM_KEYDOWN -> WM_CHAR translation.  There are several reasons why:
    • The APIs don't give enough information to do a complete implementation.  Some keyboards just will not work correctly.
    • You limit yourself to mimicking the existing infrastructure and guarantee that future enhancements to Windows keyboard input will not work on your application.
    • And finally, it's a whole lot of work and maintenance for no real gain.
  • Don't try and correlate WM_CHAR and WM_KEYDOWN:
    • Windows messages are essentially stateless.  Any assumption of state is simply a case of relying on undocumented internal behaviour.
    • Don't PeekMessage for WM_CHAR when a WM_KEYDOWN message is received to see if it has a corresponding WM_CHAR message.
    • Don't assume that each WM_CHAR has been generated by a WM_KEYDOWN message - or vice versa.
    • This can break some voice input and pen applications, as well as Keyman!
  • Don't try and match specific message sequences.  If you find yourself doing this, it's a good hint that you could probably rework your message handlers to avoid the problem.
  • Don't pay any attention to modifiers when processing WM_CHAR:
    • Don't use GetKey[board]State or local flags for managing modifiers or Caps Lock - it's a character that should not be modified before insertion into your text store.  It's not a keystroke.
    • You'll break any Windows keyboard layouts that use modifiers (hint: AltGr is only one of  the modifiers available for Windows keyboards).
    • Don't do a special-case for AltGr - other modifiers are also legal.

What's wrong with TranslateMessage?

What's wrong with TranslateMessage?  Two things:

  1. It probably shouldn't be in the message loop.  Different windows do different things with character and keystroke messages.  Performance is not an issue here nowadays.  Having TranslateMessage in the message loop has resulted in awful things such as IsDialogMessage and TranslateAccelerator calls for every message that goes through the loop.
  2. More importantly though, TranslateMessage really should return TRUE if the keystroke message generates characters.  It should return FALSE in every other situation.  Unfortunately, TranslateMessage currently returns TRUE for WM_*KEYDOWN messages, even if no characters are generated by the keystroke (think F2 or Ctrl or up-arrow or Ctrl+Shift+X).  This means that application developers have no way of knowing if the key can be safely used as a shortcut key, or should be ignored because a WM_CHAR or similar is on its way to insert into the current focus.

    This in turn means that shortcut keys are typically processed (with TranslateAccelerator or a homegrown variety thereof) before TranslateMessage - and some characters are now inaccessible on some keyboard layouts.

    The typical workaround is to add a hack for Ctrl+Alt (AltGr).  Yuck.  And that doesn't solve other supported combinations such as Ctrl+Shift.

So what's the answer to these problems? TranslateMessageEx?

November 05, 2007

While on the topic of AddLanguageProfile - Vista changes the behaviour of this function.  In Windows XP, it would install the TIP across the user's currently installed languages, and just to be helpful, add Chinese (Simplified and Traditional), Japanese, and Korean languages with the TIP installed for each of those languages.  That's not too hard to fix up.  However in Vista, this simple function call will not only , but will also add every single language installed on the system to the user's profile - resulting in the following impressive dialog:

Textservicesandinputlanguagesaftert

The list of languages goes on seemingly for ever.  Not only does this list every language - it also lists every sublanguage - Arabic (Saudi Arabia), Arabic (Iraq), Arabic (Egypt) and so on and so forth.  For good measure, the languages aren't installed alphabetically, but rather in the order of the language identifiers (0x0401 for Arabic (Saudi Arabia), 0x0402 for Bulgarian)...

Ctrl+Space, Alt+Left Shift, Ctrl+Shift and other Windows language hotkey frustrations

Some time ago, Michael Kaplan wrote about the Ctrl+Space hotkey and its broken configuration in Windows Vista.

What is particularly evil about the Ctrl+Space combination is that takes control even when the language is not selected.  So you can be happily typing away in US (English) or German (Austria) or whatever language takes your fancy, decide you want to select the current column in Excel (Ctrl+Space) and you instead will be thrown into the first available IME language.

It can even happen if the IME is not even installed.  Here's the scenario: if you have a text input processor that is registered for all languages (i.e. call  ItfInputProcessorProfiles::AddLanguageProfile with langid = -1), then Windows will behave as if the IME is installed for CJK languages, and list it in the language bar, and enable Ctrl+Space -- but without listing it in the Text Services and Input Languages dialog, and without listing the Ctrl+Space hotkey in Advanced Key Settings.  The only way to remove these bogus languages from the language bar, and disable Ctrl+Space, appears to be to remove the TIP.  Even after that, you will probably find that you have to restart Windows in order for the Language Bar to figure out which languages are actually installed...

Things are just as bad with Alt+Left Shift - the key combination that anybody who works in more than one language (and many who don't) will no doubt have experienced to their dismay...  Some of the side effects that Alt+Left Shift causes:

  • Hotkeys that use Alt+Shift+key will switch the input language as well as firing
  • Alt+Tab and Alt+Shift+Tab can switch languages in some situations
  • This hotkey is accidentally pressed so frequently that someone even created a tool to fixup text typed with the wrong keyboard!
  • If you uninstall all languages/keyboards/etc bar 1, Apply, and then add another language, the settings are reset to the defaults.  This one seems to have been fixed on Vista.
  • Dizziness may occur.

Ctrl+Shift (default behaviour - switch between keyboards for selected language) has the additional behaviour of switching text direction.  So, if you have 2 keyboards installed for a language, and press Right Ctrl+Right Shift to switch to Right-to-left in a text control, you will then have to press Ctrl+Shift AGAIN to switch back to the previous keyboard.

The grave accent [`] was added as a keyboard switch hotkey in Vista.  Once you select this hotkey, there does not appear to be any way to type a grave accent...

The next build (7.0.241.0 or later) of Keyman Desktop (Professional) will add the ability to set your own hotkeys for all installed languages...  This new version should be available in a week or two.

September 24, 2007

Managing customer licences in the Keyman Developer CRM

I have just updated the documentation around the Keyman Developer CRM - specifically, details on how to manage your customer licence records and create new customer licences for your custom Keyman-based products.  See http://tavultesoft.com/keymandev/documentation/70/tutorial_crm.html for details!

February 01, 2007

A case study on why you should NEVER, EVER check in a last minute fix

Yesterday we released Keyman 7!  The excitement may have been somewhat overshadowed by a rather larger product release on the same day in the US, and ironically, an update to MSKLC was released on the same day.

I'm not writing about the new features etc etc - if you want to read about those, visit our website. 
I'm writing about the bugs.  Perhaps this is airing the dirty laundry but here goes anyway.

The day before release, our testers identified a couple of issues.

 

The first of these was purely cosmetic.  If a user had too many languages installed, the languages tab would not fill the available space but would leave about 100 pixels of whitespace at the bottom - see image.  This space was there because the User Interface Language button was moved from there to the Options page.

Languagessmall

But for some silly reason, we decided to put in a fix.  So we put in a fix, tested it (well, obviously we didn't...  wait and see) and put the release online with only one minor issue - the Configuration dialog now did not work at *all*:

Languagessmall2

Fortunately, that was only online for a couple of minutes before we took it down - and rolled the changes back.  The second issue was more significant.  Pressing ENTER in the Activation dialog (as opposed to clicking the Activate button with the mouse) would open a Windows Explorer window instead of processing the activation:

Activate1 Activate2

We quickly put in a fix for this - and broke the Activate button.

Last minute fixes:

  • Are done in a reckless state of mind brought on by the euphoria of impending release
  • Never get tested properly
  • Do not get proper attention to design and potential side-effects

The moral of the story is: NEVER, EVER do a last minute fix.  If a fix is important enough to do at the last minute, it is important enough to delay the release by a full test cycle...