Bug introduced in Cameroon Keyboard by KM 15 Web/Android

H all,
I just had a user signal to me that there is a problem with my Cameroon keyboard, but it only seems to exist in Keyman Android 15 (My custom Android app uses an older version of KMEA, so I hadn’t noticed).
The bug DOES NOT appear in the web-based debugger of Keyman Developer 16.0.88a or on older versions of KM Android

Baseline Test:

  • Open Cameroon_Qwerty or Cameroon_Azerty in Keyman Developer 16.
  • Compile and Test on Web (Android)
  • Click the
    button, and then
    -It correctly outputs a lower-case ɗ.

Broken in KM Android 15.0.271:

  • Install Cameroon_Qwerty or Cameroon_Azerty in Keyman Android from the Web.
  • Activate the Keyboard
  • Click the
    button, and then
    -It incorrectly outputs an upper-case ɗ.
    -The opposite happens if you try to type anything from the ralt-shift layer, it exports in lower-case.

I don’t have an iPhone handy to test.
I guess it is an unintended regression as a consequence of the addition of CAPS to Android, as I can’t see a conflict in my code.


Hi @Matthew_Lee

On the keymanweb.com site with the mobile viewport (F12)


I clicked on the layer button and the ɗ key and it also outputs upper-case ɗ. It seems every key on that symbol layer is getting upper-cased.

Maybe KeymanWeb is enforcing the current layer with a rule…

Yes, anything on the RALT layer gets uppercased, and anything on the RALT-SHIFT gets lower-cased.

So things work on older versions of Keyman Android, work on Keyman Developer, but do not work on KM Android 15 or websites based on 15. Yes, it mases sense that the problem is Web, and something recent.

I look forward to your diagnosis.

I looked through the other keyboards to find another that was malfunctioning in the same way.

Among the keyboards I could find, it seems to be rare to be using this combination:

  • using rightalt and rightalt-shift in my touch keyboard (exceptCzech Basic)
  • outputting letters and using nextlayer on the same keys on a rightalt-shift and rightalt layer in touch (Czech Basic only uses deadkeys and modifier keys with nextlayer).

In other words, my keyboards seem to be the only ones malfunctioning in this way. :face_with_raised_eyebrow:

I dug into this issue this morning. I do like to try and prioritise regressions, and this is a beautifully clear regression – unlike some of our thorny issues!

Thanks @darcy for your rapid repro as well :slight_smile:

I reproduced this in the latest 16.0 alpha, so not sure why it didn’t come up for you?

It turns out that the issue is the use of nocaps in the layer id is triggering a substring match for "caps" in keyboardProcessor.ts:getStateFromLayer():

      if(layerId.indexOf('caps') >= 0) {

Prior to Keyman 15, we did not support Caps on touch layouts, so this never arose. Yes, your keyboards are the only ones that use nocaps in their layer ids in the keyboard repo!

There are three places we could fix this:

  1. The obvious fix would be to add a secondary check on the layerId match in getStateFromLayer:

      if(layerId.indexOf('caps') >= 0 && layerId.indexOf('nocaps') < 0) {

    This would ‘fix’ the problem but does perpetuate a poor design choice on our part – see point 3 below.

  2. You could update your keyboards to remove the nocaps string from the layer name, i.e. renaming from rightalt-nocaps to rightalt. This will then work with existing Keyman 15 versions; nocaps is inferred by the lack of a caps identifier, so it is unnecessary.

  3. We remove the nocaps identifier from the extended list of modifier options in the touch layout editor. The presence of nocaps in the list introduces a distinction that isn’t real: including nocaps in the layout id has exactly the same meaning as excluding caps from the layout id. That also removes the really stupid last entry in the list: caps-nocaps :joy: #7551


  4. It’s unfortunate that ‘reserved’ components of layer ids are a little arbitrary and fragile; nocaps is not currently a reserved substring, although caps is. Going forward, a better fix would be to improve the .keyman-touch-layout format to include a “default modifier” property for each layer, which is completely isolated from the layer id; if this was present in the file, then the layer id then becomes more arbitrary. #7552

Given this problem is isolated to two keyboards, my preference is for you to implement #2, and me to work on #3, immediately, and approach #4 as a future improvement.

Your thoughts appreciated!

Thanks for digging.

I was getting ready to implement #2, but I didn’t see “nocaps” or “caps” in my touch layer names (or anywhere in either keyboard).

I had removed all the nocaps from my local copy in May 2021, but apparently I didn’t upload the touch changes. I’ll work on finalizing and committing what I have, which will take a while as several changes were made to the version on keymanapp/keyman, and a few need to be modified and tested. I need to remove some NCAPs that were added and I’ll need to keep two separate copies of my KPS and KPJ if the online version uses
\shared\fonts\sil\andika_subsets\AndikaAfr-R.ttf because my Android app doesn’t have that folder.


1 Like

I had a few false starts with the Pull Requests, but it’s ready now. I’ve bumped them both to 6.0.8 to avoid my own confusion.

Since I’m trying to keep the keyboards synchronized, it’s MUCH easier for me to submit updates to both keyboards at the same time.

1 Like

Thank you @Matthew_Lee! I see the changes have already been merged :grin:

1 Like

And the user now has a working keyboard. Light-speed turnaround!

1 Like