Not logged inOpenClonk Forum
Up Topic Development / Developer's Corner / [Implementation] Keyboard layout independent controls
- - Date 2013-03-02 19:15
Parent - - By Newton [de] Date 2013-01-26 15:13 Edited 2013-01-26 15:18
So now we know what has to be done and actually it looks like there is really not much left to do:


Scancodes docs: http://www.barcodeman.com/altek/mule/scandoc.php

ker, you have been very keen to contribute to the project. Would you like to make it your first project for OpenClonk to scout out how much effort this really is to implement? This will solve all of our troubles regarding defining the controls for different keyboard layouts and thus is a feature that is greatly appreciated by players and devs alike.
Attachment: scancodes.png (49k)
Parent - - By ker [de] Date 2013-01-26 15:47
sounds doable. I'll start looking into it.
thanks for the graphical overview
Parent - - By ker [de] Date 2013-02-04 18:52 Edited 2013-02-05 16:38
i have no clue where to continue in the tree structure of this thread…
so I'll do this here:
I have implemented everything mentioned below.
Running oc on windows in a vm didn't work out sadly, so I need someone else to test my windows code (it compiles fine :) I just can't get an opengl window to show up)
I have no clue if cocoa still works, or what it does with the current code (most likely you won't be able to control your clonk).

you can find the preliminary patch here.
Be aware: if you apply this patch, and run oc, your personal config file might get messed up if the keys defined in it are unknown now, or not in the same place on a US-layout keyboard. (ÄÖÜẞ for example, or if I just mistyped a name for some key)
I also left a note in C4PlayerControl.cpp:310, anyone who knows their way around that file please check it out, might be unnecessary code there.

1. saving custom player controls is always done as a keycode scancode
2. loading player controls (custom and default) is possible from a shortened list of key-names (works with current defaults) or keycodes scancodes
3. the options dialog shows system and layout dependent names for the configured buttons
4. The colouring of letters in the options dialog now depends on keycodes instead of the string representation (custom vs default was done by string comparison of the key's name)
Parent - - By Günther [de] Date 2013-02-04 23:22
Hm, C4EditCursor::KeyUp/Down, OnKeyPressStatic and whatever the other platforms equivalents are could use some actual design. Kinda independent of this patch, except that you might have broken C4EditCursor::KeyUp/Down.

Under X11, the human-readable name should probably be generated by gtk_accelerator_get_label_with_keycode, passing the keysym as accelerator_key and hardware_keycode as keycode. I think that gives slightly nicer names than XKeysymToString.

Looks good otherwise.
Reply
Parent - By ker [de] Date 2013-02-05 16:41
done, made to work for both gtk2 and gtk3 (_with_keycode is not available in gtk2).
also fixed a regression caused by 3. (see 4.)
Parent - By Günther [de] Date 2013-03-25 00:00

> except that you might have broken C4EditCursor::KeyUp/Down.


I've fixed that up, it was indeed broken. I'll wait another week to give anyone interested in the macosx port a chance to catch up, and then merge the branch.
Reply
Parent - By ker [de] Date 2013-02-12 13:12
JCaesar tested the windows implementation, and it works.
Also, the patch was fed to the autobuilder. Broke at first, but now it works there, too.
Parent - - By Newton [de] Date 2013-03-02 18:51

> you can find the preliminary patch here.


After a follow-up in IRC, turns out that this patch is already mature and ready to be pushed and tested on master. Could somebody review and push it?
Parent - - By Günther [de] Date 2013-03-02 19:15 Edited 2013-03-02 19:18
It's currently in a "scancodes" branch. Builds are available here:
http://hg.openclonk.org/openclonk/autobuild/582e75d3da77a38199a6b7ded7b85e2ea54f233d000000

If I remember correctly, testing C4EditCursor::KeyUp/Down (that is, pressing Ctrl or Shift or what is was in an editor viewport), and Macosx are the missing things.
Reply
Parent - Date 2013-03-13 23:09
Parent - By ker [de] Date 2013-03-14 09:11
something that needs to be tested: taking fullmap screenshots doesn't work on my machine right now, Ctrl+F9 does nothing, simply F9 works just fine.
Parent - By Günther [de] Date 2013-01-26 17:51
This document has some interesting information about how keyboard layouts differ worldwide: https://dvcs.w3.org/hg/d4e/raw-file/tip/source_respec.htm#key-codes
Reply
Parent - - By Sven2 [de] Date 2013-01-26 22:58
You're missing control config overrides: When changed keys are stored, they would either need to be converted to virtual codes as well, or saving/loading of direct scan codes needs to be added to compile/decompile functions.

Alternatively, key codes are converted to key strings when saved. However, this might be bad idea, because you would lose some functionality such as using left and right shift key as individual controls.

Also, every place where key constants are used internally (e.g. all the standard keys like Escape, Fkeys, etc. defined in C4Game::InitKeyboard) need to be updated.
Parent - By ker [de] Date 2013-02-03 11:10
key codes are already converted to strings, if a string name exists. Otherwise they are converted to a keycode.

currently right/left shift/control keys are not handled nicely anyway, since alt/ctrl/shift cannot be remapped to anything else b/c they are hardcoded (windows and x11 alike)

yea, key constants have a nice list in C4Window.h, no trouble at all to replace that :)
Parent - - By ker [de] Date 2013-02-02 15:55 Edited 2013-02-02 16:32
so… for windows these conversions are rather trivial (as MapVirtualKey offers scancode<->virtualkey conversion).
with x11 it becomes more difficult. For all letter keys, numbers, F1-F10, most Num Keys and (Left|Right)-(Shift|Ctrl|Alt) it's no problem, but even the delete key is in a range, where apparently it is possible to create mappings, but the way I understand it, udev might load a different mapping than you expect (or the user is evil and does completely custom scancode->keycode mappings).
I have not found a way to tickle scancodes out of x11 functions.

If it's fine that special scancodes differ between x11 and windows and that users messing badly with their system are left to solve this on their own, I can implement this (have it already running for x11).

edit: I'm not sure where Console.EditCursor.KeyDown(key, event->state); belongs… is that what's used when oc is run with --editor for changing drawing tools?
Parent - - By Zapper [de] Date 2013-02-02 16:03
Thumbs up for the progress :)

I am looking forward to finally get rid of the DVORAK etc. specific files.

Will gamepads be affected by this in any way?
Parent - By ker [de] Date 2013-02-02 16:10
Nope, gamepads and mouse keys are completely separate.
Parent - - By Newton [de] Date 2013-02-03 00:10

> so… for windows these conversions are rather trivial (as MapVirtualKey offers scancode<->virtualkey conversion).


Are you sure you need the mapping function at all there? It is possible to get the scancode directly from the keyboard event call from the WndProc:


uint virtualCode = (uint)m.WParam;
uint keyState = (uint)m.LParam;
uint scanCode = keyState >> 16 & 0xFF;
(source)

As far as I understood Sven2, this is exactly the place where he thought the "conversion" should happen (for WM_KEYDOWN/... etc)

Perhaps at that point in Linux and Mac it is also possible to "easily" get a raw scancode?
Parent - By ker [de] Date 2013-02-03 09:29
thanks! Those few lines were all I needed.

I believe my code will now run on windows… I just need to figure out how to compile oc under windows :D

For key names of "unusual keys" the GetKeyNameText-function should be enough, eliminating the need for os dependent key<->string maps
Parent - - By Günther [de] Date 2013-02-03 03:15
I think I still want X11 to work like I've described in http://bugs.openclonk.org/view.php?id=729 :-) In practice, all that matters is that the default runs on evdev - the kbd driver is obsolete on Linux. I'll expand on the text from the bug a bit.
Essentially this line and its siblings:
  DWORD key = XKeycodeToKeysym(GDK_WINDOW_XDISPLAY(event->window), event->hardware_keycode, 0);
should be replaced by
  DWORD key = event->hardware_keycode;
Then, C4KeyCodeEx::KeyCode2String and C4KeyCodeEx::String2KeyCode have to be changed to match. The former has to handle two modes.
First, presenting the KeyCode to the player. This needs to use XKeysymToString(XKeycodeToKeysym(...)) to have a good chance of matching what's printed on the physical keyboard, or perhaps some GTK+ function if that gets us even nicer strings. This doesn't need to match between platforms.
Second, converting it to a form that's stored in the config file. That has to be the inverse function of String2KeyCode, and the string stored in the config file has to be common for all platforms, at least for the keys used in the default config. For the keys not used by the default config we can use platform-dependant stuff. Probably simplest to just store the KeyCode as a number. The current code here pretty much cheats and assumes that XKeysymToString agrees with the names in the KeyCodeMap. It's really amazing how little problems that has caused so far.
The next point are the various K_* constants in C4Window.h. We probably ought to replace them with the names C4KeyCodeEx::String2KeyCode takes. Alternatively, we could simply change them from Keysyms to Keycodes.
Reply
Parent - - By ker [de] Date 2013-02-03 09:23
well, if we only support evdev, we can support scancodes. Subtracting 8 from the keycode doesn't kill anybody.
And about the string conversion… we can support both "Clonk Key Names" and XKeysymToString(XKeycodeToKeysym(scancode+8)) (preferring the clonk key name for output and trying either for input)
Parent - By Günther [de] Date 2013-02-04 13:11

> (preferring the clonk key name for output and trying either for input)


No. As mentioned, for String2Keycode we only need to support configuration files and the PlayerControls.txt. Being liberal risks someone putting platform-dependent codes in the PlayerControls.txt, so we shouldn't do that. Keys that do not have a name for the PlayerControls.txt can use a number to make it clear that they are platform-dependent.

Keycode2String has a parameter that indicates whether the key will be stored in the configuration or displayed to the user. Those have totally different requirements: If you change your keyboard layout, the name of the key in the configuration should not change, but the name shown in the configuration dialog should.
Reply
Parent - - By ker [de] Date 2013-02-03 13:20
A slight issue I have found: Allowing players to write "Ä" into the config file is rather simple to implement, writing it back out would be very messy, since you don't know whether it came from an Ä or from whatever lies there on a US-keyboard (gets even worse when you think about z/y conversion, you have no clue which one the user means).
A related issue: When reconfiguring one's keys, the config displays US-layout keys, as it simply uses the Keycode->String conversion.

So: how about always saving and loading the keys in US-layout, but creating a custom C4KeyCodeToDisplayString function that is solely for ingame display of the keys?
Parent - By Sven2 [de] Date 2013-02-03 13:36
I'd say manually configured keys should always be saved as scan codes regardless of whether they are on the US layout or not. This saves us from extra conversions that could potentially fail or map distinct keys to the same key code. This should be easy to do, as all manually configured keys are in an extra list that can just be compiled with some compilation parameter (i.e. use mkParAdapt).

Something like C4KeyCodeToDisplayString with various parameters (short/long format, human readable or not) exists already.
Parent - By Sven2 [de] Date 2013-02-03 13:44
Actually, if I think of it, no extra parameter is needed. Just always write scan codes. The US layout keys are only ever needed when a human writes the PlayerControls.txt.
Parent - By Newton [de] Date 2013-02-03 17:27
Thumbs up for your progress! Otherwise, see Sven ;-)
Parent - - By ker [de] Date 2013-02-04 09:02
should I even bother about the USING_SDL_MAINLOOP?
Is that just old code noone uses or is it actively used on some system?
Parent - By Günther [de] Date 2013-02-04 13:14
The CR mac port used it, and I'm keeping it working because its a trivial amount of code, and might be useful some day. Feel free to ignore it.
Reply
Parent - By Günther [de] Date 2013-05-25 23:45
While searching for clues why windows scancodes differ from the evdev one, I found this: http://msdn.microsoft.com/en-us/library/ms645536%28v=VS.85%29.aspx

With luck, using that would help Windows 7 users who have a graphics tablet which gets some weird special treatment interfering with pen input.
Reply
Up Topic Development / Developer's Corner / [Implementation] Keyboard layout independent controls

Powered by mwForum 2.29.7 © 1999-2015 Markus Wichitill