Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix French circumflex & umlaut accents #73

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ysard
Copy link

@ysard ysard commented Sep 24, 2022

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.

Replace circumflex accent obtained by modifier with the keyboard key available.
This allows to be able to generate letters with umlaut using the modifier shift + '^'.
@CLAassistant
Copy link

CLAassistant commented Sep 24, 2022

CLA assistant check
All committers have signed the CLA.

@github-actions
Copy link

Memory usage change @ 83c76f3

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<br>flash,%,examples/Serial<br>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
Copy link
Collaborator

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
Copy link
Author

ysard commented Sep 24, 2022

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:

  • no printing key & not modifier (ex: function keys)
  • modifier alone
  • printing key with modifier
    size_t Keyboard_::press(uint8_t k)
    {
    uint8_t i;
    if (k >= 136) { // it's a non-printing key (not a modifier)
    k = k - 136;
    } else if (k >= 128) { // it's a modifier key
    _keyReport.modifiers |= (1<<(k-128));
    k = 0;
    } else { // it's a printing key

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().

// fr_FR keys
#define KEY_SUPERSCRIPT_TWO (136+0x35)
#define KEY_E_ACUTE (136+0x1f)

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...

@per1234 per1234 added type: imperfection Perceived defect in any part of project topic: code Related to content of the project itself labels Sep 24, 2022
@edgar-bonet
Copy link
Collaborator

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:

  • you type AltGr+9 to get a caret (^ = U+005E); that's what you call “the diacritic alone”
  • you hit the dead circumflex, then a vowel, to get that vowel with a circumflex accent on top (“ÂÊÎÔÛâêîôû”)

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:

  • print("un oiseau : ^o^"); should type un oiseau : ^o^
  • print("un oiseau : ^ o^ "); should type un oiseau : ^ o^ .

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: [...]

  • codes in the range 0–127 are interpreted as ASCII codes, and translated to key codes (potentially with modifiers) by a layout-dependent table
  • codes in the range 128–135 are modifiers
  • codes in the range 136–255 are raw key codes (technically, USB “usage codes”), shifted by 136.

@ysard
Copy link
Author

ysard commented Sep 25, 2022

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
Copy link
Collaborator

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:

  • French
  • French (AZERTY)
  • French (alt.)
  • French (alt., Latin-9 only)
  • French (legacy, alt.)

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: code Related to content of the project itself type: imperfection Perceived defect in any part of project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants