arduino-libraries / Keyboard

GNU Lesser General Public License v3.0
223 stars 157 forks source link

Fix French circumflex & umlaut accents #73

Open ysard opened 1 year ago

ysard commented 1 year ago

Hi, This PR replaces the circumflex accent obtained by modifier with the key directly available on French keyboards. This brings the 0x2f scan code available and allows to be able to generate letters with umlaut using the modifier shift + '^'.

Keyboard.write(KEY_CIRCUMFLEX);
Keyboard.write('i');

Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press('^');
Keyboard.releaseAll();
Keyboard.write('i');

Gives: îï

The KEY_CIRCUMFLEX macro is now redundant but I guess that's syntactic sugar.

CLAassistant commented 1 year ago

CLA assistant check
All committers have signed the CLA.

github-actions[bot] commented 1 year ago

Memory usage change @ 83c76f3cbd3b761051ae3899207243c08b7f46fc

Board flash % RAM for global variables %
arduino:avr:leonardo 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
arduino:sam:arduino_due_x_dbg 0 - 0 0.0 - 0.0 N/A N/A
arduino:samd:mkrzero 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
Click for full report table Board|examples/Serial
flash|%|examples/Serial
RAM for global variables|% -|-|-|-|- arduino:avr:leonardo|0|0.0|0|0.0 arduino:sam:arduino_due_x_dbg|0|0.0|N/A|N/A arduino:samd:mkrzero|0|0.0|0|0.0
Click for full report CSV ``` Board,examples/Serial
flash,%,examples/Serial
RAM for global variables,% arduino:avr:leonardo,0,0.0,0,0.0 arduino:sam:arduino_due_x_dbg,0,0.0,N/A,N/A arduino:samd:mkrzero,0,0.0,0,0.0 ```
edgar-bonet commented 1 year ago

This isn't a “fix”: it breaks the normal operation of the keyboard.

Take this for example:

Keyboard.println("un oiseau : ^o^");

With the master version of the library, it types:

un oiseau : ^o^

With this pull request applied, it instead types:

un oiseau : ô

(and my computer barked because it didn't know what to make of the sequence Circumflex + Enter that followed the “ô”).

ysard commented 1 year ago

Hi, I don't know what system you are working on, but the expected behavior of the keyboard is precisely to press this key 2 times to get the diacritic alone.

By the way, the current implementation of ` doesn't print the character directly either.

Ex: You have to press Altgr + è twice to get ` and not ỳùìò etc.

Also note that I'm on GNU/Linux, but you can also press 1 time then followed by a keystroke on space to display the diacritic alone. This last method is common to GNU/Linux, Windows and MacOS.

Your example should be: Keyboard.println("un oiseau : ^ o^ ");

See more about dead keys: https://fr.wikipedia.org/wiki/Touche_morte


As is from what I see of the code, it is impossible to generate a character with an umlaut.

Stop me if I'm wrong but the press() function accepts 3 types of codes:

A workaround exists by defining some additional macros in the headers of the layouts but these only apply to simple keys. Impossible to add a modifier to them because the numerical value obtained (136+scancode+modifier) would exceed 255 which would generate an overflow on the uint8_t argument sent to press().

https://github.com/arduino-libraries/Keyboard/blob/a5611787986d733c11aba7d27e0e307397a6553c/src/Keyboard_fr_FR.h#L36-L38

To avoid the overflow it would be necessary to overload write(), press(), and release() to accept values greater than a uint8_t. I have a working implementation but I doubt that it coincides with the desire to keep the project simple...

edgar-bonet commented 1 year ago

I don't know what system you are working on

Ubuntu 20.04 with the default desktop, French Keyboard, “French (alt.)” (a.k.a. fr-oss) layout.

the expected behavior of the keyboard is precisely to press this key 2 times to get the diacritic alone.

The expected behavior of a real French keyboard is:

and yes, you could also abuse the dead circumflex to obtain a caret, but you don't have to. And the Keyboard library doesn't.

Most importantly, the expected behavior of the library is that print() types exactly what you ask it to type, as long as it is ASCII only:

You should get what you ask for: if ^ o^ becomes ^o^, that's a bug.

the current implementation of ` doesn't print the character directly either.

Keyboard.print("`");

does exactly that.

it is impossible to generate a character with an umlaut.

Typing non-ASCII characters is inconvenient, but not impossible. It is inconvenient because you have to tell the library exactly what keys to press:

Keyboard.press(KEY_LEFT_SHIFT);
Keyboard.press(KEY_CIRCUMFLEX);
Keyboard.releaseAll();
Keyboard.print("u");

types ü.

Stop me if I'm wrong but the press() function accepts 3 types of codes: [...]

ysard commented 1 year ago

Most importantly, the expected behavior of the library is that print() types exactly what you ask it to type, as long as it is ASCII only

I think this is indeed a point to be clarified.

Keyboard.print("`");

Thank you for giving your precise keyboard layout, because I have just understood that it is this layout in particular that makes the ` character not a dead key for you. Hence my misunderstanding about the difference in treatment between the ^ and the ` (the fact remains that the ´ AltGr + 1, is dead in any case).

Honestly, this is the first time I've come across a keyboard with this variant, which experimentally is never the default configuration either on Windows or on GNU/Linux (Debian, Fedora or Arch). The default variant is "often" something like latin9, but it does not exhibit the behavior you describe for the `. Idem for the layout of the virtual consoles.

On this certainly minor point, the result depends on the variant of the layout used.

edgar-bonet commented 1 year ago

it is this layout in particular that makes the ` character not a dead key for you.

Interesting, I didn't know that ` (I mean, AltGr-è) could be a dead grave. Seems quite inconvenient for typing Markdown! I tried all the Linux layouts that seemed relevant to me:

Of these, only the one labeled “legacy” makes ` a dead grave. All the others have a regular backtick there, which is consistent with the article on the AZERTY keyboard in the English Wikipedia. This “legacy” layout is also the only one to have a dead acute at AltGr-&.

And then, the French Wikipedia article on AZERTY states (emphasis mine):

[...] sur certains AZERTY français, l’accent grave ` et le tilde ~ sont également des touches mortes [...]

It also carries a picture of the Windows layout, which does map ` to a dead grave.

Now, back to the Keyboard library. If the user has a variant of the French layout with a dead grave at AltGr-è, then there is no way the library can properly support the backtick, and they would have to add a space after the backtick as a workaround. Regardless, the caret would always work without needing any workaround.