1

I am writing an accessibility tool using Qt which will allow the user to operate the mouse using only the keyboard. People who just really hate mice can use it too.

enter image description here enter image description here

The unique challenges of this application are stretching what is possible with Qt, but luckily Qt is elastic.

The user presses Caps Lock to activate the tool, after which the tool steals focus. A grid appears on the screen and the user presses keys which move the mouse smaller amounts each time.

Pressing 0 left mouse clicks, and the grid disappears. Adding Alt double clicks.

Pressing Shift 0 should right mouse click, and pressing Ctrl Shift 0 should middle click.

The problem I am facing is that, while on my keyboard, Shift+0 will result in a QKeyEvent(QKeyEvent.KeyPress, Qt.NoModifier, Qt.Key_ParenRight) (so, a )), this is not at all guaranteed. If my computer is in Japanese IME, I will get a QKeyEvent(QKeyEvent.KeyPress, Qt.ShiftModifier, Qt.Key_0).

japanese kb layout

Help, how can I get information I need about the user's current keyboard layout so I can choose the right Qt.KeyEvent to listen for?

Fredrick Brennan
  • 7,079
  • 2
  • 30
  • 61

2 Answers2

0

You cannot. Even if you knew all possible layouts and the current layout, how would you make the difference between the user pressing shift+<key> or the user having Caps Lock on and pressing <key>.

The issue here is that you are using shift as a modifier which is not. So either you keep going this way an offer users a way to change their settings, or fallback to using a standard modifier key.

Update: See comments

Benjamin T
  • 8,120
  • 20
  • 37
  • Microsoft Windows already have keyboard keys defined for controlling the mouse. https://support.microsoft.com/en-us/help/14204/windows-7-use-mouse-keys-to-move-mouse-pointer – Benjamin T Jul 25 '16 at 13:05
  • Downvoted because: 1. Qt already solves the "caps lock" problem by sending different key codes, as I showed above. 2. Shift is a modifier according to Qt. See Qt.ShiftModifier. 3. If you knew all possible layouts, and the current layout (and its information), you could find "0", find the Shift key of 0, and look for QKeyEvents with that QKey. 4. MouseKeys has nothing to do with this. – Fredrick Brennan Jul 25 '16 at 13:09
  • 1. Still how can you make the difference between pressing `(` and pressing `shift+0` as the later is interpreted as `(`. 2. You get a `shift` modifier in japanese because you have no other character associated with `shift + 0`, in other layouts as the one on your computer you don't get any modifier because `shift+0` is translated to `(`. – Benjamin T Jul 25 '16 at 14:04
  • 1
    3. You could, but it would not work as expected, for instance in french azerty layout the 0 key can type '0' or 'à'. You get 'à' with no modifiers or if you have both shift and caps lock, and you get 0 if you have only shift or only caps lock. So when you get a key event with 0, the user could be pressing shift, or not, you need to check caps lock status. 4. MouseKeys has very much to do with thisn it's the same functionality: controlling the cursor with a keyboard. My comment was merely a suggestion of using the same keyboard binding as what some users might by used to. – Benjamin T Jul 25 '16 at 14:13
  • Also your should use `QGuiApplication::keyboardModifiers()` instead of `QKeyEvent::modifiers()` as stated by Qt documentation. Maybe the shift modifier is correctly set there. – Benjamin T Jul 25 '16 at 14:15
  • Thanks for the clarifications - I didn't know about azerty, or that any keyboard layout allows Caps Lock to affect the numbers. Unfortunately my downvote is locked in unless you edit - a simple edit with "See comments" would be enough. – Fredrick Brennan Jul 25 '16 at 15:09
0

Even if you could know the current layout, there is no guarantee that a given key combination is translatable between different layouts. Some keys may not be available at all, and some key combinations may be just plain impossible (because of conflicting usage of the shift key).

The only viable general solution is to treat keyboard shortcuts as translatable strings. This means deciding on a default set of shortcuts for your application, and then providing translatations of them based on the most common keyboard layout for each locale you want to support.

With that in place, at runtime you could then create a mapping of localised shortcut strings to functions - thus allowing you to interpret key-events independently of the actual key combinations that had been assigned in the current locale.

And note that a system like this would also make it easy to support user configuration of keyboard shortcuts (since the general mechanism is almost the same).

PS:

As pointed out in the comments, you should avoid using QKeyEvent.modiifiers(), as it is unreliable. Use QGuiApplication.keyboardModifiers() instead.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • In this case translatable strings is a poor solution as you enforce a keyboard layout onto the users based of their locale. Yes it will work most of the time, but not all the time. Better results could be achieved by using `QInputMethod::locale()` instead of the UI `QLocale`. It becomes a proper solution only if the user can configure its keyboard shortcuts (last paragraph). NB: Using translatable strings for keyboard shortcut is a good idea when the keyboard shortcut depends only on the language of the UI. (eg shortcuts for action in an application menu bar) – Benjamin T Jul 26 '16 at 13:25
  • @BenjaminT. Any solution has to be a compromise, given the nature of the problem. Nothing is being "enforced". The point of using translations is to provide a better set of **defaults** for all users. This should result in a good out-of-the-box solution 95% of the time. The remainder can be taken care of by making the shortcuts user-configurable. – ekhumoro Aug 03 '16 at 15:24