-
-
Notifications
You must be signed in to change notification settings - Fork 407
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
Different keyboard layouts #22
Comments
Its on my TODO list. But since I dont know the different keyboard layouts I never had a deeper look into this. Also I think its not that important. Why not simply switch to an english keyboard? On my Windows for example I've installed German and english layout, I can switch. By the way on Windows you can switch with Control + Shift. Or Windows + Space. This way you could automatically switch forth and back very fast and silent. I will keep it in mind. Feel free to contribute anything to this. I'll probably have a look though, shouldnt be too hard but its time consuming. |
Of course for expert users this is not a problem, but it sure is for novices. I also want to be able to use my devices on as many computers as possible and not to depend on a workaround. Think of a scenario like this:
We will leave this little scene now before we start imagining how she tries to paint over the letters on the keyboard using an Edding... I think I will contribute my solution when I implemented it. |
https://github.com/PaulStoffregen/cores/blob/master/teensy/keylayouts.c The easiest thing would be just to copy those definitions and make the Keyboard API work with it. I decided to not work on that for now, rather try a full NKRO keyboard instead. |
htho, have you seen the PR? You may want to try this out and give some feedback. I still havent tested it though. |
Hey @NicoHood , I havent tried it yet. Right now I am focussing on the hardware development. I'll give feedback when I am working on the firmware again. |
@RingoM @htho You still interested in this? You can do this by calling Keyboard.useLayoutGerman(); The patch was added here: Important Notes
Feel free to copy the US layout, modify it for you language and open a Pullup request Please test this if you can. |
This a great step ahead. Now I am very busy writing my masters thesis (10 days left). I can't wait to try it. For my purposes the special characters are important too. I will contribute when I am done with my thesis and had a little time to relax. |
No hurries. Maybe the code will change in those 10 days. I am finding a way to not type all layouts myself, maybe we can use the Teensy code here. Good Luck with your thesis ;) Implementing this would be nice: |
There are 4 options on how to implement different layouts:
I'd like to know which one you like the most. Opinions? |
In fact it would be great to have an option to change the keyboard layout without needing to re-compile and upload the code. Until then any stable solution is sufficient. The boards.txt is not desired. I did not understand the last option. From a programmers point of view the current solution is very "arduinish", while not being able to change the layout at runtime with the same function is unintuitive. Therefore I prefer |
Example: The same would be for Keyboard layouts. Switching them at runtime takes tons of flash and wont be implemented. I think there is a way to even provide a default instance, If you do not create a new one and overwrite it. But this needs to be tested. The point is, if we add this "feature" with templates you have to declare this in every sketch once. Not a big deal, but default examples wont work this way. But well thats the price. Or we create whole new names like GermanKeyboard.write('x') but I dont like that. |
This could easily fix our problem without any complicated workarounds: I'll wait until there is some progress in yes/no |
I now adapted the Teensy Keyboard to the library. Its set to german layout right now. The problem I am, currently having is that ESC and Backspace doesnt work. And I dont know why. these unicode wrappers are so complicated. I found a similar post in the forum, but the provided solution didnt help. The error occurs on german and english layout. The other solution would be porting the whole Arduino ascii array to each language. I am not that happy to do that, at least not for other languages. The good thing about this idea is that the Arduino library uses less flash, so I'd prefer this if I really want to use a keyboard. The Teensy API is more flexible and has lots of definitions, also for those é keys and other stuff like that. Maybe someone can help here (finding the teensy bug)? |
@NicoHood I just did a quick test with the code in my PR, which is essentially the same code you used with the teensy implementation and it seems that TeensyKeyboard.press(KEY_BACKSPACE); works just fine. I didn't have the time to install and test your code, but I have a strong feeling that it would also work with press and release. In fact TeensyKeyboard.write() doesn't work with any keycode, so TeensyKeyboard.write(KEY_A) doesn't work, but TeensyKeyboard.press(KEY_A); does. That's what I understand from a quick reading on the teensyduino website: https://www.pjrc.com/teensy/td_keyboard.html Keep up the good work! |
That fixes the problem. Seems the Teensy Keyboard behaves different. One problem left: Please remind me to add this information (press+release instead of write) to the docs later if I forget this. I will move those definitions (KEY_WHATEVER) to a general file, since the NKRO keyboard also uses the same keys. I'd also pledge for a multilayout patch for the original HID core, since the teensy is not that relyable in this case as you see. I want to keep it as option, but users who want to switch the layout should be able to use the standard API as well. Give me some time to work on this and also apply NKRO ;) |
I tried to adapt the official keyboard API to another layout (german as example). The problem here is, that english layout works with normal keys + shift. On a german keyboard for example you need to press ALT GR in order to get {[]} . So we need something like the SHIFT flag. But there is no option to set another bit in the array. >=128 is used for shift and the rest is used for normal keys. We could use uint16_t which will blow the Array size (I guess thats what the Teensy code does). So for a german keyboard {[]}|@ are out of scope with this api. You can use the Teensy or better switch to english layout. I also tried to sitch the keyboard layout dynamically before pressing a key. Ctrl + Shift for windows and for linux alt space. However this needs some delay and is not relyable. I think I will buy an english main keyboard then. Also I tried to set the keyboard layout for a specific keyboard on linux, but that changed it for both keyboards (arduino and usb keyboard). And not everyone is using linux too. Any suggestions how to solve this? |
Arduino uses UTF-8 encoding, so when you send the letter 'b', you're actually doing Keyboard.write(0x62); Since the first 128 characters of UTF-8 correspond to the ASCII characters, arduino is using an ASCII lookup table to convert ASCII to HID keycodes. Now, let's say you're trying to type the '€' sign, which is 0xe282ac, you're sending Keyboard.write(0xe2); The teensy code converts the UTF-8 encoding to Unicode and then the Unicode to keystrokes. So adapting the official API to german layout is not going to work without rewriting the entire API. I think arduino should import the teensy code. Although it's not perfect, the approach of converting UTF-8 to HID keycodes and allowing to switch layouts is better, according to me. Arduino & UTF-8: http://playground.arduino.cc/Code/UTF-8 |
Sorry for the late response, but you are totally right. Thx for the explanation. |
Closing this now since Teensy now works. There will be no other (fast) solution yet. I think thats fine now since you have 3 keyboard you can choose from. 2 working even at boot time now. Keyboard layout needs to be manually set in HID-Project.h right now. More documentation coming soon. Thx for all the help. If you have tested this with success feel free to still post it here, even if this issue is closed. |
I want to add here that I am probably going to implement the UK keyboard for the normal API. It seems that every key is pressable via shift. However this is still impossible for most other languages. Edit fixed: |
Reminder for myself: |
Just realized that we CAN use multiple modifiers for the keylayouts and that there IS enough space for 2 more bits. I will try to work on this tomorrow. You can see it here: BTW: |
Also if I do |
The guys who asked for this feature: |
You can imagine a factory like API
I think it would be great, but we have to consider impact on code size. |
Also, to support multiple layout at runtime, Keycode values should no be defines. You made good progress in this direction using enums. |
I've notices that most keycodes are the same for all layouts. actually just the ascii codes are country specific. Meaning a,b,c123!"£$% etc. So the basic API keeps the same, just the print("I am a euro sign €"); can be changed. I am probably going to make US default and you can add other layout on top of that. This way you can also change the layout at runtime, but only the used layouts + default US are compiled. But I have to deal with some inheritance errors atm. |
If you have any idea... Feel free to join the chat on freenode irc #arduino |
First step was done: Requires: If you look at the normal source file it is better visible: We now have more layers. The language "packs" would now just use the base class pointer "KeyboardAPI" from one of the keyboards and use the Keycode functions to write raw data. With this technique you can code almost anything with the reports now. I am not sure where to put the language packs so. As described above it could just access the data via the public functions (or via friends directly). It could also be a pointer inside the API which you can switch at runtime. Or it could be inherited in a layer above (or below??). Last option would be a static/fixed implementation. However there is a lot more work that needs to be done to tear down the #define values into enums or arrays. So one header doesnt overwrite the other. But I will fix the NKRO API first. Tests appreciated! |
Wow, You're quick. Making this patch rely on arduino/Arduino#4027 that isn't reviewed / integrated is a bit hardcore. Yet, I will create a new branch on trustline to follow you, but I can't keep it on develop where cloners would fail to build because of non-void HID::SendReport (I don't want to expect developers to patch Arduino before build). I'll digg into your library this week. I first have to understand the relationship between Keycode / Keyboard layout and printed characters. If you have any resources... |
Keycodes are the raw definition of the usb protocol. Different keyboard layouts remap those. Which is annoying. but otherwise you would not be able to press ae oe ue on a german keyboard for example. And some keys are just flipped like y and z. And it seems that there is no simple way to get rid of this since every keylayout is so different. sometime with shift modifier, alt gr and even many others. Docs will follow. If i had updated them every time... wow i changed so much and will probably change in the future. Too bad we are between two versions and the wiki is somehow "floating". The PR requirement is hardcore I know. But they will merge it for sure, because they like my work and know that its required if I need it :D Just wait for monday or maybe Tuesday. |
The Teensy API requires to read the current pressed modifiers when a deadkey is used. Its not a problem to implement this, but this messes up the whole API and adds even more overhead. I dont want this. Also what is a deadkey, do we need this? If we need it, we could use the DefaultKeyboard layer to read this data, meaning NKRO will be layout incompatible. Also this code is quite a mess. The original Teensy code and the adaption I am trying to create. On top of this the IDE UTF8 encoding is not perfect. So I dont really have the intention to implement this stuff. Its just... "dont use fucking other keylayouts". I just dont know how to implement this smart enough. On the other side there is now room for another library that can be placed on top of mine. So the limit is not set, its just not implemented by me. And because the IDE handles UTF8 as shit it is hard to do something like Keyboard.press('€');. Since you never know what that should be. It just conflicts too much. Not saying its impossible. So the frustrated nicohood is stopping work here for now.
To work around this we could use shift AND alt gr together as special modifier sign. Then we can make a few more layouts compatible. Another option would be to keep it as teensykeyboard again, with separate API, completely different from the normal API. But then we just can use the defaultkeyboardapi layer... Any opinions? Anyone willing to implement this? I can share my dev code though. |
My 2cts: C++11 standard introduces utf8 and utf16 encoded string as part of the language with u* prefix. That should solve the code source issue when you want to print(''€"), but it depends how the editor handles utf characters. Clearly, arduino editor fails short in this. One way to go would be:
the Arduino print API cannot handle such task, it was designed to handle ASCII characters, and that's all. So if we want to solve this problem, we will have to break something. If character encoding / code points are still a mystery, this is an helpful resource: http://www.joelonsoftware.com/articles/Unicode.html |
Didnt read that text, but saw this line: "And all was good, assuming you were an English speaker." The Teensy API supports uint8_t utf8 and converts them into a uint16_t utf8. so we can use both with the given code. In the end you need a character map I think. But I will not do that now, I already spent too much time on that feature even though I will never use it. |
Why dont we use the alt + numbers trick to press different UTF keys? This way we could be able to:
|
I have created a new repository on GitHub that contains a working prototype which uses this library and UTF-8 to allow sending strings to a host that expects German language layout: https://github.com/donid/akuhell Please consult the "readme" for more information. |
This looks interesting. You did it all right, as you used the HID Project as backend. If the example keys in your sketch all work, then its a huge progress. If you can pack this into a working Keyboard inherited class, that'd be perfect. Maybe something like a big lookup table would clean up the code more and support for other languages might also be simpler to add. If you have any progress, please let us know here. Thanks for sharing :) |
I learned a lot from this discussion implementing my idea of sending the keycodes from a raspberry pi to the arduino via i2c, so I am doing most of it in python and not on the arduino (https://github.com/schneirob/i2ckeyboard). So thank you for discussing! Allow me to comment something I stumbled upon (and haven't implemented, yet): One thing to keep in mind, when designing a new lookup table / keymap feature that there are characters that are composed by multi key action and require key releases in between (e.g. ÈÉèéÀÁàá). When running a German keyboard Layout you produce those by pressing KEY_LEFT_SHIFT, KEY_EQUAL, Release All, (KEY_LEFT_SHIFT), KEY_E/KEY_A. Or with Grave âêôÂÊÔ. Just things that came to my mind, hope it helps! |
sorry but i've never in my life seen a keyboard that somehow physically, or in its firmware, "supports" a specific layout. All keyboards send the same scan code for each corresponding key, and the OS then decides which character to assign to that scan code depending on the language you set. What you're suggesting: how would this even work? You plug the keyboard in, and the OS says your keyboard layout is US English, but the keyboard instead writes some unrelated foreign characters? Wut? What if you want to actually switch to US English? A suggestion for your mom: next time you install Windows, don't forget to set the right keyboard language for her. That way you won't have to build her specialized keyboards with specialized firmware that do the layout conversion for her OS. |
@paulens12 In non english environments it is very common that you have special characters. And you are right, that the keycodes are always the same, that you send. But the keyboard API abstrcts that layer. You dont specify which key was pressed, instead you want an API that tells you wich character should be written on a specific layout. The requirement is totally legit, but not trivial to implement. Not in a way that would make it general enough, or in a way I was motivated to do so. |
Don't worry, you don't have to explain me how international keyboards are different - I have used 6 different keyboard layouts regularly (for 5 different languages, although I don't speak them all, sometimes it's cheaper to import laptops from certain countries).
But can't we just send scan codes using your API? I really don't get this whole fuss about "layouts". This concept should not exist at all in keyboard controller firmwares. Either use scancodes, or for easier configuration, add #defines with all US QWERTY keys, e.g.
#define KEY_A 0x00
#define KEY_ENTER 0x00
and so on (I don't know the actual scan codes so I just used 00 everywhere)
I really don't see the point in any further abstraction. Even game engines handle user input this way :)
Sorry if I'm saying the obvious - I haven't had time to get more in depth with your library yet.
…________________________________
From: Nico <notifications@github.com>
Sent: Saturday, January 26, 2019 8:57:40 PM
To: NicoHood/HID
Cc: paulens12; Mention
Subject: Re: [NicoHood/HID] Different keyboard layouts (#22)
@paulens12<https://github.com/paulens12> In non english environments it is very common that you have special characters. And you are right, that the keycodes are always the same, that you send. But the keyboard API abstrcts that layer. You dont specify which key was pressed, instead you want an API that tells you wich character should be written on a specific layout.
The requirement is totally legit, but not trivial to implement. Not in a way that would make it general enough, or in a way I was motivated to do so.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<#22 (comment)>, or mute the thread<https://github.com/notifications/unsubscribe-auth/ADg7zfZvoFWQUdNmuweNHQq9JltYpb-Kks5vHKUkgaJpZM4D_lhH>.
|
It is not that simple. Some keys can only be reached with Shit or Alt GR combinations. This required some coding overhead that is not handled yet. And thats the problem. Please go ahead and write some code... |
ummm, what's keeping the user from pressing shift and alt-gr? Why does it require special handling when it's actually the same as writing A by pressing shift+a? |
Because no user is pressing the key, the API simulates those keystrokes. I guess you totally miss the point. I will stop discussing here, as this will not bring us any further. |
Leonardo international keyboard support MultiLanguage library Keyboard library for Arduino for all languages and keys mapping This library allows an Arduino board with USB functions to act as a keyboard. The following languages are integrated: English, German, Russian, French, Greek, Hebrew, Italian, Georgian |
Different keyboard layouts are now supported. |
@NicoHood If you have time, could you please explain why paulens12 is wrong and you actually do need keyboard layouts in firmware. Cause I was thinking the same thing, if the keyboard layout is set by the OS, why would you also need different layouts in firmware. I don't see need for the api to simulate keystrokes. |
It would be nice to have multiple keyboard layouts available. This should be as simple as putting the definition of the
_asciimap
variable into a separate, layout depended, header.My knowledge about key-codes is too limited to fork this repository myself. I also think in order to make this feature actually usable, similar to teensy, there should be a menu available in the IDE - And I don't have a clue how to alter the IDE-Menu-Structure.
Simply using code from teensy is no option as the keyboard layout implementation for teensy seems to be too different from Arduino/HID.
The text was updated successfully, but these errors were encountered: