Re: KeyCode in the javafx.scene.robot.Robot interface

2024-05-17 Thread Martin Fox
Mark,

> I iterate over each key in that set, sending that keycode to a text
> field. I then do the same for each keycode but with the shift key held.
> I don't doubt that it could cause havoc in some setups!

On a German or Spanish layout on the Mac BACK_QUOTE will invoke a dead key and 
throw everything off. Dead keys are miscoded on the Mac but since they aren’t 
used while typing there hasn’t been much motivation to fix that. If sending a 
KeyCode generates an InputMethodEvent instead of a KeyEvent you hit a dead key. 
Send a SPACE to clear the dead key state. That will generate another 
InputMethodEvent and insert a character into the text control.

> In my case, I'm almost always testing whether some UI elements become
> enabled or disabled based on validation occurring on a text field of
> some kind. A recent case was checking to see if a text field correctly
> rejected input that didn't appear to be an email address. Typing '@'
> into the field was difficult to make reliable. :)

For this sort of testing you can build KeyEvents and fire them yourself. That 
would allow you to bypass a bunch of fraught areas of the Robot like incorrect 
focus or accidentally invoking input methods. The internal KeyEventFirer object 
in JavaFX takes this approach. It uses several internal API’s but illustrate 
the basics, like sending PRESSED/TYPED/RELEASED trios for KeyCodes that 
generate characters. I would not mix this approach with a Robot since you would 
lose control of the ordering of events.

Martin

Re: KeyCode in the javafx.scene.robot.Robot interface

2024-05-16 Thread Mark Raynsford
Hello!

On 15/05/2024 14:49, Martin Fox wrote:
> Mark,
> 
> You may already know this but before JavaFX 21 the Mac and Windows Robot code 
> had some long-standing bugs with non-US keyboards. Linux is in better shape 
> but you can encounter problems if the user has installed multiple layouts (I 
> have a PR pending to fix that). That might explain some of the flakey 
> behavior you’ve been seeing. Your approach might also invoke an unexpected 
> dead key depending on what modifiers you’re probing.

Very possible. I use this base set of keycodes:

https://github.com/io7m-com/xoanon/blob/ac7c9c900c7908c5760a74d6cf4056fe3ffb8e92/com.io7m.xoanon.commander/src/main/java/com/io7m/xoanon/commander/internal/XCCommander.java#L235

I iterate over each key in that set, sending that keycode to a text
field. I then do the same for each keycode but with the shift key held.
I don't doubt that it could cause havoc in some setups!

> With one exception JavaFX doesn’t have any facility for querying the keyboard 
> layout. It relies on the platform code to take in keyboard events and 
> translate them to JavaFX events on the fly. The exception is the internal 
> call Toolkit.getKeyCodeForChar which attempts to map from a character to a 
> KeyCode and is used to match shortcuts specified as KeyCharacterCombinations. 
> Unfortunately the current implementation on Mac and Linux can’t really be 
> extended to cover the sort of testing you’re trying to do.

Right.

> JavaFX needs a better framework for testing text entry and I’ve thought about 
> how that might look...

In my case, I'm almost always testing whether some UI elements become
enabled or disabled based on validation occurring on a text field of
some kind. A recent case was checking to see if a text field correctly
rejected input that didn't appear to be an email address. Typing '@'
into the field was difficult to make reliable. :)

-- 
Mark Raynsford | https://www.io7m.com



Re: KeyCode in the javafx.scene.robot.Robot interface

2024-05-16 Thread Martin Fox
In another thread someone asked whether JavaFX could report which keyboard 
layout is currently active. I don’t think there’s any useful way of doing this.

The Mac organizes layouts using language codes. There are five variants for 
German and 15 for English. The German variants are ABC-QWERTZ, Austrian, 
German, German-DIN-2137, and SwissGerman. The English variants are ABC, 
USExtended, ABC-India, Australian, British, British-PC, Canadian, Colemak, 
Dvorak, Dvorak-Left, DVORAK-QWERTYCMD, Dvorak-Right, Irish, US, and 
USInternational-PC.

Linux organizes layouts using country codes. When the user searches for a 
layout they see display names based on language but under the hood it’s all 
organized by country. On my Ubuntu 22 system there are 10 variants for Great 
Britain, 25 for the United States, and 20 for Germany.

On Windows the user configures some number of input languages and then adds 
keyboard layouts to each language. On my system I have one language (English) 
and inside it are four layouts (U.S., French, German, and Spanish). It’s easy 
to find the user’s current input language but there’s no documented way to 
retrieve information about the current layout. Folks have reverse-engineered 
this but I’ve resisted going down that rabbit hole (it involves digging around 
in the registry).

Setting aside the more specialized layouts like Dvorak most of the variants 
within a given language or country differ in the way they handle dead keys or 
the position of punctuation and symbol characters. So the variants matter but 
can’t be reported in any consistent way across platforms.

> On May 15, 2024, at 7:49 AM, Martin Fox  wrote:
> 
> Mark,
> 
> You may already know this but before JavaFX 21 the Mac and Windows Robot code 
> had some long-standing bugs with non-US keyboards. Linux is in better shape 
> but you can encounter problems if the user has installed multiple layouts (I 
> have a PR pending to fix that). That might explain some of the flakey 
> behavior you’ve been seeing. Your approach might also invoke an unexpected 
> dead key depending on what modifiers you’re probing.
> 
> With one exception JavaFX doesn’t have any facility for querying the keyboard 
> layout. It relies on the platform code to take in keyboard events and 
> translate them to JavaFX events on the fly. The exception is the internal 
> call Toolkit.getKeyCodeForChar which attempts to map from a character to a 
> KeyCode and is used to match shortcuts specified as KeyCharacterCombinations. 
> Unfortunately the current implementation on Mac and Linux can’t really be 
> extended to cover the sort of testing you’re trying to do.
> 
> (On any OS the keyboard machinery is designed to take a series of physical 
> keystrokes and produce a series of characters. Attempting to go in the 
> opposite direction is fraught with complications particularly for punctuation 
> and symbols. It’s faster and more reliable to wait for the user to type 
> something and record what happens. That’s how getKeyCodeForChar is 
> implemented on the Mac; until the user types something it yields no results. 
> Linux is currently buggy but the PR to fix it adopts the same approach as the 
> Mac.)
> 
> JavaFX needs a better framework for testing text entry and I’ve thought about 
> how that might look. But my priorities might be different than yours. Based 
> on the bugs I’ve seen the biggest issue is that developers only test on the 
> platforms and layouts they use. Much of this is due to lack of awareness but 
> it’s also a big hurdle to have to buy Mac, Windows, and Linux boxes and then 
> manually switch between layouts to test. My ideal framework would be based on 
> emulated keyboards so, say, a U.S. Windows developer could generate a key 
> event stream that corresponds to a Spanish Mac layout.
> 
> That approach wouldn’t involve sending platform events through the OS. 
> Extending the Robot to make it easier to, say, target punctuation and symbols 
> via platform events would be nice to have but not essential (IMHO).
> 
> So, no, you’re not missing anything exposed or under the hood. The approach 
> you’re taking is probably the best that can be done with the current API.
> 
> Martin
> 
>> On May 12, 2024, at 3:16 AM, Mark Raynsford  wrote:
>> 
>> Hello!
>> 
>> I maintain a test harness for JavaFX applications:
>> 
>> https://www.github.com/io7m-com/xoanon
>> 
>> I expose an interface that uses the javafx.scene.robot.Robot
>> interface internally, but I expose a slightly higher level
>> API that allows for (amongst other things) typing text as strings
>> on components rather than sending individual key codes.
>> 
>> The problem I immediately run into is that KeyCodes are keyboard
>> layout specific, and there doesn't appear to be any way to detect
>> what keyboard layout is in use. If I, for example, send the KeyCode for
>> the `@` symbol, I'll actually get `"` on some keyboard layouts. This
>> can cause some types of tests to fail, even though th

Re: KeyCode in the javafx.scene.robot.Robot interface

2024-05-15 Thread Martin Fox
Mark,

You may already know this but before JavaFX 21 the Mac and Windows Robot code 
had some long-standing bugs with non-US keyboards. Linux is in better shape but 
you can encounter problems if the user has installed multiple layouts (I have a 
PR pending to fix that). That might explain some of the flakey behavior you’ve 
been seeing. Your approach might also invoke an unexpected dead key depending 
on what modifiers you’re probing.

With one exception JavaFX doesn’t have any facility for querying the keyboard 
layout. It relies on the platform code to take in keyboard events and translate 
them to JavaFX events on the fly. The exception is the internal call 
Toolkit.getKeyCodeForChar which attempts to map from a character to a KeyCode 
and is used to match shortcuts specified as KeyCharacterCombinations. 
Unfortunately the current implementation on Mac and Linux can’t really be 
extended to cover the sort of testing you’re trying to do.

(On any OS the keyboard machinery is designed to take a series of physical 
keystrokes and produce a series of characters. Attempting to go in the opposite 
direction is fraught with complications particularly for punctuation and 
symbols. It’s faster and more reliable to wait for the user to type something 
and record what happens. That’s how getKeyCodeForChar is implemented on the 
Mac; until the user types something it yields no results. Linux is currently 
buggy but the PR to fix it adopts the same approach as the Mac.)

JavaFX needs a better framework for testing text entry and I’ve thought about 
how that might look. But my priorities might be different than yours. Based on 
the bugs I’ve seen the biggest issue is that developers only test on the 
platforms and layouts they use. Much of this is due to lack of awareness but 
it’s also a big hurdle to have to buy Mac, Windows, and Linux boxes and then 
manually switch between layouts to test. My ideal framework would be based on 
emulated keyboards so, say, a U.S. Windows developer could generate a key event 
stream that corresponds to a Spanish Mac layout.

That approach wouldn’t involve sending platform events through the OS. 
Extending the Robot to make it easier to, say, target punctuation and symbols 
via platform events would be nice to have but not essential (IMHO).

So, no, you’re not missing anything exposed or under the hood. The approach 
you’re taking is probably the best that can be done with the current API.

Martin

> On May 12, 2024, at 3:16 AM, Mark Raynsford  wrote:
> 
> Hello!
> 
> I maintain a test harness for JavaFX applications:
> 
> https://www.github.com/io7m-com/xoanon
> 
> I expose an interface that uses the javafx.scene.robot.Robot
> interface internally, but I expose a slightly higher level
> API that allows for (amongst other things) typing text as strings
> on components rather than sending individual key codes.
> 
> The problem I immediately run into is that KeyCodes are keyboard
> layout specific, and there doesn't appear to be any way to detect
> what keyboard layout is in use. If I, for example, send the KeyCode for
> the `@` symbol, I'll actually get `"` on some keyboard layouts. This
> can cause some types of tests to fail, even though the code is correct.
> 
> Consider a test where an email address is typed into a text field, and
> then the form containing the field is checked to see if the text field
> accepted/rejected the text as being a valid email address. On some
> keyboard layouts, a test that sends the string "some...@example.com"
> will fail because what ends up in the text field is actually
> "someone"example.com".
> 
> I provide a workaround for this: At the start of the test suite run,
> xoanon will send every KeyCode to a text field one at a time and see
> what character appeared in the text field as a result. It then builds a
> mapping between characters to KeyCodes, and it can then do the
> translations as necessary when running the rest of the test suite:
> 
> https://github.com/io7m-com/xoanon?tab=readme-ov-file#keymap-generation
> 
> Unfortunately, this is still rather flaky. This often seems to fail more
> or less at random for reasons that aren't clear to me.
> 
> Is there some way the Robot interface could be extended to allow for
> typing strings? Failing that, is there some way JavaFX could advertise
> the underlying keyboard map? I feel like some underlying component must
> know the information I'm trying to infer, but it doesn't seem to be
> exposed anywhere that I've been able to find.
> 
> -- 
> Mark Raynsford | https://www.io7m.com



KeyCode in the javafx.scene.robot.Robot interface

2024-05-12 Thread Mark Raynsford
Hello!

I maintain a test harness for JavaFX applications:

https://www.github.com/io7m-com/xoanon

I expose an interface that uses the javafx.scene.robot.Robot
interface internally, but I expose a slightly higher level
API that allows for (amongst other things) typing text as strings
on components rather than sending individual key codes.

The problem I immediately run into is that KeyCodes are keyboard
layout specific, and there doesn't appear to be any way to detect
what keyboard layout is in use. If I, for example, send the KeyCode for
the `@` symbol, I'll actually get `"` on some keyboard layouts. This
can cause some types of tests to fail, even though the code is correct.

Consider a test where an email address is typed into a text field, and
then the form containing the field is checked to see if the text field
accepted/rejected the text as being a valid email address. On some
keyboard layouts, a test that sends the string "some...@example.com"
will fail because what ends up in the text field is actually
"someone"example.com".

I provide a workaround for this: At the start of the test suite run,
xoanon will send every KeyCode to a text field one at a time and see
what character appeared in the text field as a result. It then builds a
mapping between characters to KeyCodes, and it can then do the
translations as necessary when running the rest of the test suite:

https://github.com/io7m-com/xoanon?tab=readme-ov-file#keymap-generation

Unfortunately, this is still rather flaky. This often seems to fail more
or less at random for reasons that aren't clear to me.

Is there some way the Robot interface could be extended to allow for
typing strings? Failing that, is there some way JavaFX could advertise
the underlying keyboard map? I feel like some underlying component must
know the information I'm trying to infer, but it doesn't seem to be
exposed anywhere that I've been able to find.

-- 
Mark Raynsford | https://www.io7m.com