Topic Inhibiting lots of keys.

We have two new locations for Keyman technical support:

The Tavultesoft Forums are now read only.


# Inhibiting lots of keys.   2016-02-28 11:31:25.997
br Julian Griffin OSL
:
Store(&MnemonicLayout)   '1' c Make keyboard independent of user's keyboard layout.

Begin Unicode > Use(GiM)

Group(GiM) Using Keys

c Initiate TPA Grapheme Input mode. If, and only if, at the beginning of a line.
   nul + $GrahemeKey > $TPAcursor Set(TPAgraphemeInputFlag='Yes')

c Close the TPA Grapheme Input mode.
c Clean up the text; delete the TPA Glue & TPA Cursor and reset the grapheme input flag.
   $TPAcursor + [K_UP]    > [K_BKSP] [K_UP]    Set(TPAgraphemeInputFlag='No')
   $TPAcursor + [K_ESC]   > [K_BKSP] [K_ESC]   Set(TPAgraphemeInputFlag='No')
   $TPAcursor + [K_TAB]   > [K_BKSP] [K_TAB]   Set(TPAgraphemeInputFlag='No')
   $TPAcursor + [K_DOWN]  > [K_BKSP] [K_DOWN]  Set(TPAgraphemeInputFlag='No')
   $TPAcursor + [K_RIGHT] > [K_BKSP] [K_RIGHT] Set(TPAgraphemeInputFlag='No')

c Backspace for editing entered graphemes. Delete TPA Cursor, TPA Glue, Grapheme and replace TPA Cursor.
   $TPAcursor + [K_BKSP]  > [K_BKSP] [K_BKSP] $TPAcursor

   Store(LatinLetter)   "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
   Store(LatinLetterLC) "abcdefghijklmnopqrstuvwxyz"
   Store(LatinLetterUC) "ABCDEFGHIJKLMNOPQRSTUVWXYZ"   Store(Numbers)       '0123456789'
   Store(Symbols)       "'" ' !"£$%^&*()-_=+[{]};:@#~,/?`¬\|'
   Store(AltGrs)        'áéíóúÁÉÍÓÚ€¦'
   Store(CursorKeys)    [K_UP] [K_DOWN] [K_LEFT] [K_RIGHT] [K_HOME] [K_END] [K_PGUP] [K_PGDN] [K_KP5]
   Store(NumberPad)     [K_NP0] [K_NP1] [K_NP2] [K_NP3] [K_NP4] [K_NP5] [K_NP6] [K_NP7] [K_NP8] [K_NP9] [K_NPDOT] [K_NPSTAR] [K_NPSLASH] [K_NPPLUS] [K_NPMINUS]
   Store(FunctionKeys)  [K_F1] [K_F2] [K_F3] [K_F4]  [K_F5]  [K_F6] [K_F7] [K_F8] [K_F9] [K_F10] [K_F11] [K_F12]
   Store(Specials)      [K_BKSP] [K_DEL] [K_ENTER] [K_ESC] [K_INS] [K_oE2] [K_SPACE] [K_TAB] [K_SEL] [K_PRINT] [K_EXEC] [K_HELP] [K_?05] [K_NPENTER]
   Store(Punctuations)  [K_BKQUOTE] [K_COLON] [K_COMMA] [K_HYPHEN] [K_LBRKT] [K_PERIOD] [K_QUOTE] [K_RBRKT] [K_BKSLASH] [K_SLASH] [K_EQUAL]
   Store(WholeKeyboard) Outs(Numbers) Outs(Symbols) Outs(AltGrs) Outs(CursorKeys) Outs(NumberPad) Outs(FunctionKeys) Outs(Specials) Outs(Punctuations)

c Inhibit some keys from functioning.
   $TPAcursor + Any(WholeKeyboard) > $TPAcursor
   $TPAcursor + Any(LatinLetterUC) > $TPAcursor

c If Grapheme Input Mode is in force pass processing to the GraphemeInput group.
   If(TPAgraphemeInputFlag = 'Yes') + Any(LatinLetter) > Use(GraphemeInput)

c TPA Grapeme Input Mode not requested nor running.
   Nomatch > Use(MenuHandler)
The above code will allow a very limited set of keys to function in this group. It all seems to work ok, except '|' (Key 102) is not court.

   However, my real question is this, surly there must me a simpler/better way to limit a vast range of keys. How about?
:
$TPAcursor + NotAny(LatinLetterLC) > $TPAcursor

   But Notany cannot be in the Key part of the Rule. I have tried calling a Context Only group, but I could not get it to work.

By this point in the code
:
c Inhibit some keys from functioning.
   $TPAcursor + Any(WholeKeyboard) > $TPAcursor
   $TPAcursor + Any(LatinLetterUC) > $TPAcursor
I wish to only allow lowercase letters to be valid. But to do this creates very ugly code.

Regards
Julian Griffin
# RE: Inhibiting lots of keys.   2016-02-29 07:23:02.733
Marc Durdin
Tavultesoft Staff
Am I right in thinking that the nomatch(all) functionality that we discussed in another forum post is what you are looking for?

Could you not do this as an alternative:

:
group(GiM) using keys

...

+ any(LatinLetterUC) > use(latin)

group(latin) using keys

...


I should note also the virtual key output as you are using in that example is not supported (though it may work in some situations, it won't work in all) - you would need to match the TPA Glue in the context and delete that as well, then use the special empty final "using keys" group to push out the original keystroke (http://help.keyman.com/developer/language/guide/groups):

:
$TPAglue $TPAcursor + [K_UP] > Set(TPAgraphemeInputFlag='No') use(finalkey)

group(finalkey) using keys
  c empty 'using keys' group as final group
  c ensures original keystroke is emitted
# RE: Inhibiting lots of keys.   2016-03-01 09:54:33.193
br Julian Griffin OSL
Yes, possibly 'Nomatch(All)' is the sort of thing I'm thinking of. I am still pondering on that.

Let me flow diagram the GiM group.
   1) See if Grapheme Input Mode is required, if it is; set a flag and display a cursor.
   2) Check if GiM is to end, if it is; clean up and reset flag.
   3) Check if Edit 'Backspace' has been pressed, if it is; remove Grapheme & Glue, and replace Cursor.
   4) If GiM flag set; Ignore all Left Cursor.
   5) If GiM flag set & Lowercase Latin letter pressed, call GiM Input Group.
   6) If none of the above has Fired, GiM is not in use so check for menu use.

   All this you know from the code. My thoughts on 'Nomatch(all)' and my code are:
      a) Would it be possible to:
:
If(Flag='On') Nomatch(All)

      b) What would the precedence be on Nomatch, or Match for that matter, be?
      c) If one were to precede a 'Nomatch(All)' with a number of Rules using some keys, this would be a very good way of locking down keyboard behaviour.
      d) How would it be used Context Only groups?
      e) What would the reserved keys; untrappable keys be?

    The code below is closer to working but it shows some oddities. {No validation code is in this block}
:
c *******************************************************************
Begin Unicode > Use(GiM)
c *******************************************************************

Group(GiM) Using Keys

c Initiate TPA Grapheme Input mode (GiM). If, and only if, at the beginning of a line.
   nul + $GrahemeKey > $TPAcursor Set(TPAgraphemeInputFlag='On')

c Close the TPA Grapheme Input mode.
c Clean up the text; Delete TPA Glue, Set the grapheme input flag to 'No, Perform Key press.
   $TPAglue $TPAcursor + '?'       > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)
   $TPAglue $TPAcursor + [K_UP]    > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)
   $TPAglue $TPAcursor + [K_ESC]   > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)
   $TPAglue $TPAcursor + [K_TAB]   > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)
   $TPAglue $TPAcursor + [K_DOWN]  > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)
   $TPAglue $TPAcursor + [K_RIGHT] > Set(TPAgraphemeInputFlag='Off') Use(GiMcloseEdit)

c Backspace is the only editing possible in GiM.
c Delete: TPA Glue & Grapheme, Then replace TPA Cursor.
   $TPAglue $TPAcursor + [K_BKSP]  > Use(GiMcloseEdit) $TPAcursor

c Through away the Left Cursor key.
   If(TPAgraphemeInputFlag = 'On') + [K_LEFT] > nul
                       
c If Grapheme Input Mode is in force pass processing to the GraphemeInput group.
   If(TPAgraphemeInputFlag = 'On') + Any(LatinLetterLC) > Use(GraphemeInput)

c TPA Grapeme Input Mode not requested nor running.
   Nomatch > Use(MenuHandler)

Group(GiMcloseEdit) Using Keys 
c empty 'using keys' group as final group
c ensures original keystroke is emitted

   In the Close GiM block above, none of the keys function correctly, except the '?', and that's only there for testing. The empty Group(GiMcloseEdit) only seems to function on keys that produce a glyph.

   The Backspace Rules functions correctly, but gives a warning re: Use() and following commands. Though Use(G1) Use(G2) on the same line functions one after the other, but give no warning.

   The line below functions correctly. But I can get lost in the Debug and Test modes on the Debugger as to which control keys function and when.
:
If(TPAgraphemeInputFlag = 'On') + [K_LEFT] > nul
Sometimes it seems to be in force when I am unsure what others keys should be doing. Could you point me to the article covering Test/Debug modes and there differences. Thank you.

   But I'm getting a headache now, so I'm going to bed.

Goodnight
Regards
Julian Griffin
# RE: Inhibiting lots of keys.   2016-03-02 07:33:09.337
Marc Durdin
Tavultesoft Staff
Yes, I can see the issue you are describing. I'm not sure what is causing this but will investigate.
# RE: Inhibiting lots of keys.   2016-03-02 22:02:17.687
Marc Durdin
Tavultesoft Staff
Okay, I've done some research. Here are some of my notes. Not sure if this will make any sense, but we are running into one of the tricky parts of Windows integration.

This is because these are TSF preserved keys. This means that TSF intercepts them for Keyman. Keyman cannot then tell TSF to pass them to the app. If we try and emit a new one with SendInput, TSF captures this as well and we get a loop.

Two possible solutions:

* Use PostMessage. This is subject to order issues with other input sent via SendInput being interleaved with PostMessage input. This is not easy (or performant) to solve but theoretically possible. For example, we could have SendInput sending a set of keystrokes including a terminal flag keystroke. When the GetMessageProc sees this terminal flag keystroke, it emits the wanted final keystroke. This could possibly work for keyboards where only the typed keystroke is wanted at the end of any context changes, but still runs the risk of interleaving with user input of other kinds.

* Setup the preserved keys based on context. This would mean at the end of each keystroke, run through the ruleset again to determine which keys will be captured by the input manager, and preserve only those keys. This preserved key setup would also need to be run at any time that the context is reset, e.g. with cursor movement, mouse click, focus changes.
# RE: Inhibiting lots of keys.   2016-03-03 07:48:23.280
br Julian Griffin OSL
Well that covered that!?!
I feel that was clearer to you than to me.

   I persume this pertains to the 'Close the TPA Grapheme Input mode' section. You say the output of [K_UP] is not reliable in all conditions. The TPA keyboard is intenden for English only, and on PC, Mac, and Adroid. If it will work on PC & Mac only, I can reduce the functionallity on Android.

   I can test PC and Adnroid. Am I safe to assume that what works on a PC will most likely work on Mac?

Until you have a go at 'All' I'm pressing forward with my large strings of keys. But they are getting quite big eg:
:
Store(LatinLetterAll) \
 [K_A]  [K_A] [K_B] [K_C] [K_D] [K_E] [K_F] [K_G] [K_H] [K_I] [K_J] [K_K] [K_L] [K_M] [K_N] [K_O] [K_P] [K_Q] [K_R] [K_S] [K_T] [K_U] [K_V] [K_W] [K_X] [K_Y] [K_Z] \
 [ALT K_A] [ALT K_B] [ALT K_C] [ALT K_D] [ALT K_E] [ALT K_F] [ALT K_G] [ALT K_H] [ALT K_I] [ALT K_J] [ALT K_K] [ALT K_L] [ALT K_M] [ALT K_N] [ALT K_O] [ALT K_P] [ALT K_Q] [ALT K_R] [ALT K_S] [ALT K_T] [ALT K_U] [ALT K_V] [ALT K_W] [ALT K_X] [ALT K_Y] [ALT K_Z] \
 [CTRL K_A] [CTRL K_B] [CTRL K_C] [CTRL K_D] [CTRL K_E] [CTRL K_F] [CTRL K_G] [CTRL K_H] [CTRL K_I] [CTRL K_J] [CTRL K_K] [CTRL K_L] [CTRL K_M] [CTRL K_N] [CTRL K_O] [CTRL K_P] [CTRL K_Q] [CTRL K_R] [CTRL K_S] [CTRL K_T] [CTRL K_U] [CTRL K_V] [CTRL K_W] [CTRL K_X] [CTRL K_Y] [CTRL K_Z] \
 [SHIFT K_A] [SHIFT K_B] [SHIFT K_C] [SHIFT K_D] [SHIFT K_E] [SHIFT K_F] [SHIFT K_G] [SHIFT K_H] [SHIFT K_I] [SHIFT K_J] [SHIFT K_K] [SHIFT K_L] [SHIFT K_M] [SHIFT K_N] [SHIFT K_O] [SHIFT K_P] [SHIFT K_Q] [SHIFT K_R] [SHIFT K_S] [SHIFT K_T] [SHIFT K_U] [SHIFT K_V] [SHIFT K_W] [SHIFT K_X] [SHIFT K_Y] [SHIFT K_Z] \
 [CTRL ALT K_A] [CTRL ALT K_B] [CTRL ALT K_C] [CTRL ALT K_D] [CTRL ALT K_E] [CTRL ALT K_F] [CTRL ALT K_G] [CTRL ALT K_H] [CTRL ALT K_I] [CTRL ALT K_J] [CTRL ALT K_K] [CTRL ALT K_L] [CTRL ALT K_M] [CTRL ALT K_N] [CTRL ALT K_O] [CTRL ALT K_P] [CTRL ALT K_Q] [CTRL ALT K_R] [CTRL ALT K_S] [CTRL ALT K_T] [CTRL ALT K_U] [CTRL ALT K_V] [CTRL ALT K_W] [CTRL ALT K_X] [CTRL ALT K_Y] [CTRL ALT K_Z] \
 [SHIFT ALT K_A] [SHIFT ALT K_B] [SHIFT ALT K_C] [SHIFT ALT K_D] [SHIFT ALT K_E] [SHIFT ALT K_F] [SHIFT ALT K_G] [SHIFT ALT K_H] [SHIFT ALT K_I] [SHIFT ALT K_J] [SHIFT ALT K_K] [SHIFT ALT K_L] [SHIFT ALT K_M] [SHIFT ALT K_N] [SHIFT ALT K_O] [SHIFT ALT K_P] [SHIFT ALT K_Q] [SHIFT ALT K_R] [SHIFT ALT K_S] [SHIFT ALT K_T] [SHIFT ALT K_U] [SHIFT ALT K_V] [SHIFT ALT K_W] [SHIFT ALT K_X] [SHIFT ALT K_Y] [SHIFT ALT K_Z] \
 [SHIFT CTRL K_A] [SHIFT CTRL K_B] [SHIFT CTRL K_C] [SHIFT CTRL K_D] [SHIFT CTRL K_E] [SHIFT CTRL K_F] [SHIFT CTRL K_G] [SHIFT CTRL K_H] [SHIFT CTRL K_I] [SHIFT CTRL K_J] [SHIFT CTRL K_K] [SHIFT CTRL K_L] [SHIFT CTRL K_M] [SHIFT CTRL K_N] [SHIFT CTRL K_O] [SHIFT CTRL K_P] [SHIFT CTRL K_Q] [SHIFT CTRL K_R] [SHIFT CTRL K_S] [SHIFT CTRL K_T] [SHIFT CTRL K_U] [SHIFT CTRL K_V] [SHIFT CTRL K_W] [SHIFT CTRL K_X] [SHIFT CTRL K_Y] [SHIFT CTRL K_Z] \
 [SHIFT CTRL ALT K_A] [SHIFT CTRL ALT K_B] [SHIFT CTRL ALT K_C] [SHIFT CTRL ALT K_D] [SHIFT CTRL ALT K_E] [SHIFT CTRL ALT K_F] [SHIFT CTRL ALT K_G] [SHIFT CTRL ALT K_H] [SHIFT CTRL ALT K_I] [SHIFT CTRL ALT K_J] [SHIFT CTRL ALT K_K] [SHIFT CTRL ALT K_L] [SHIFT CTRL ALT K_M] [SHIFT CTRL ALT K_N] [SHIFT CTRL ALT K_O] [SHIFT CTRL ALT K_P] [SHIFT CTRL ALT K_Q] [SHIFT CTRL ALT K_R] [SHIFT CTRL ALT K_S] [SHIFT CTRL ALT K_T] [SHIFT CTRL ALT K_U] [SHIFT CTRL ALT K_V] [SHIFT CTRL ALT K_W] [SHIFT CTRL ALT K_X] [SHIFT CTRL ALT K_Y] [SHIFT CTRL ALT K_Z]

Regards
Julian Griffin
# RE: Inhibiting lots of keys.   2016-03-03 21:47:54.267
Marc Durdin
Tavultesoft Staff
Yes, those were rather deep technical notes. Making changes to Keyman at that level is not much fun, because there is a huge amount of complexity in Windows that is not documented and results in very unexpected behaviours. So I always take these types of changes very slowly. I am usually hesitant to take over control of non-character keys as these can have different meanings in many apps: for example in Excel, it can mean 'move to next cell' instead of move right a character.

So at this point, I am thinking about these issues but not currently making plans to change Keyman's behaviour with these keys, without a lot more design work up front.
# RE: Inhibiting lots of keys.   2016-03-05 22:04:26.440
br Julian Griffin OSL
I understand completely.

   The first hardware I ever built was a ROM writer for a computer character set (ASCII); a 5 by 7 dot matrix set.

   In use, to display a character;
:
      Read from system Ram
      Write to ROM
      Read from ROM
      Write to display RAM.

   This is not exactly simple, but it can be easily traced across each step. Whilst it is true that today's systems can be traced, they are stunningly more complex, and there can be many areas of uncertainty. It can be more like being an explorer trying to map a new territory, than an engineer designing and building a machine to do a specific task.

   Exploring can be great fun, but also incredibility frustrating. And one must assign a good stretch of time to do it, and have the right frame of mind.

   But, for now, I know the issue. I can now set my design with it in mind. Knowing what can't be done is often as important as knowing what can be done.

God bless.
Julian Griffin