Trouble tipping shifted characters over a remote desktop connection

I’ve setup my keyboard to directly type shifted characters. E.g. LSHIFT(Key_1) (Types ‘!’ on a german layout). That works like a charm on my local computer. Now I’m working over a windows remote desktop connection for the first time and more then half of the time only the unshifted character is recognized by the remote system.

Has anyone else experienced a similar issue and found a solution to it? Since every once in a while the expected character is printed I imagine that either the Shift-down event or the Shift-Up event is sent in a different frame (not exactly sure how the keyboard communicates with the host) and that they somehow end up getting processed out of sync.

@jesse: Could that have anything to do with the NKRO-functionality? As far as I understood the trick was to simulate beeing more then one keyboard in order to be able to send as many keys at once as are pressed. Is that correct?

No, NKRO does not simulate more than one keyboard, nor should it matter for remote hosts, because they don’t get the raw report, but the symbols the host sends them.

They are sent in the same report when used as LSHIFT(Key_1), always. And this might be the issue too. Can you try turning them into a macro like this:

case SHIFT_1:
  return MACRODOWN(I(50), D(LeftShift), T(1), U(LeftShift));

This should send Shift and 1 separately. As in, hold Shift first, then tap 1, then release Shift, with a few ms delay inbetween, to give time to the OS and the remote host to process the information. Not sure this’ll work, but I have a hunch that it may.

What I find curious is that every once in a while the correct character is typed on the remote system.

I will try the macro solution. In case that yields the correct result: Is there a chance to turn the LSHIFT() Macro into exposing the same behaviour? Otherwise it will be a lot of cumbersome work in order to get all the shifted characters working as expected.

This works just fine. At 50ms the delay is quite noticeable. It still works at 10ms. At 5ms it starts showing the unshifted character again every now and then. At 1ms it doesn’t work at all any more.
What doesn’t work with the macro is repetiton of the character when the key is held. That wouldn’t really bother me with the ‘!’ but it might with other keys.

Here is some test-output:

5ms 
!!!!!!!!!!!!!!!!!!!!!!1!!!!!1!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1!!!!!!!!!!!!!!!!!!
10ms
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

other shifted characters without macros
?????????????????????ß??????ßß?????????????????ßßßßßßßßßßßßßßßßßßßßßßßßß?ß??ß??ß?ß????ßßßßß
88888888(8888888888888888888888888888888888888888888888888888888((888888888888888888888888888
99)999999999999999999999)999999999999999999)999999999999999)999999999999999999999999999999999

key held
9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
999999999999999999999999999999999999999999999999999999999
99999999999999999
9999999
9999999999999999
999999999999999999
999999999999999
9999999999999999999
9999999999999999

Software works in mysterious ways… ¯\(ツ)

Sadly, I do not have a good explanation why it works from time to time.

Mmm… We may be able to, but that would be a regression for other use cases, where the current behaviour is desired (eg, implementing an Alt+Control+Shift+GUI key). So I’m afraid that in the short term, some work is required :frowning:

That’s harder to do… I’ll get back to you later about it (lunch calls right now). The basic idea is that on keyToggledOn(keyState), the macro would send Shift and 1 separately. When keyIsPressed(), we’d go around the MACRO thing, and use kaleidoscope::hid::pressKey() to hold both Shift and 1 at the same time (without delay). We need not do anything on keyToggledOff() because the report is cleared every cycle.

TBH:

if (keyToggledOn(keyState)) {
  return MACRO(I(10), D(LeftShift), D(1));
} else if (keyIsPressed(keyState)) {
  // either this:
  return MACRO(Dr(LSHIFT(Key_1)));
  // or if that doesn't work, then this:
  kaleidoscope::hid::pressKey(LSHIFT(Key_1));
  return MACRO_NONE;
}

Hope this helps!

Actually, the firmware already sends the shift in a separate report, before it sends the printable keycode, in order to work around a ChromeOS bug.

1 Like

I don’t have any Windows machines to try this on, but it definitely sounds like Windows Remote Desktop sends key events, not characters, to the remote host, and has a frame rate that’s too low to guarantee that the two HID reports on the local host stay separate on the remote host. And that report to the remote host probably orders the keys by keycode, and doesn’t use the modifiers byte, so the shift gets processed last by the remote host (so it’s the same problem as the aforementioned ChromeOS bug).

That would explain why it works every once in a while; if the boundary between the two reports happens to coincide with a frame being transmitted to the remote host, you’d get lucky and get a frame with just the shift, then one with the 1. Since (without the macro) they’re sent one immediately after the other, rather than in subsequent scan cycles, I’d expect it to be rare.

If you want to try a different solution, you could try adding a delay in a different spot instead of a macro for each key you need this fixed for.

Depending on the version of Kaleidoscope you have, the place to add that delay is different. If you’re working with the latest, it’s here (in Kaleidoscope-HIDAdaptor-KeyboardioHID):

Just put a delay(10); after that line (57), and it should work.

If you’ve got an older version, though, that file is in the Kaleidoscope repository: src/kaleidoscope/hid.cpp

1 Like

Now, that works like a charm. Thank you very much for your quick help!

1 Like

Now I do experience another glitch:
When typing the two characters - and > in quick succession it sends -_> to the host.
That makes sense, because - is just a simple key press but > is Shift+'<' on the german keyboard. I believe that the workaround, that sends the keyboard-report in order to get the Shift on it’s way, doesn’t clear the report and therefor still sends the - though it isn’t pressed any more. _ is Shift+'-'

Do you have a key mapped to > (with the shift applied, so you don’t need to hold a separate shift key)?

Yes. I have a single key mapped to Shift+< in order to produce >. That’s what I was trying to say.

Are you sure it isn’t pressed any more? If you’re typing fast, it’s normal to have “rollover” where two keys are pressed at the same time. Also, the keyswitch activates well before the key bottoms out, so it’s quite common for overlap to occur even when we perceive two keypresses to be distinct, particularly if they’re done fast.

The second thing to consider is that when you hold down a key, then press shift quickly (before the key starts repeating), you don’t immediately get a second, shifted character (but you will get shifted characters when it starts to repeat. So the only way to get “-_>” from tapping the two keys quickly without holding them down long enough for a repeat is if the “-” gets erroneously removed from a report that gets sent, then added back in on the following report.

That said, here’s what I think is going on:

First, key - is pressed, and a report is generated and sent. A report is sent with just -.

Next, key shift + < is pressed. The key that you’ve got this on is (I’m guessing) scanned before the - key (it’s probably on a higher row, or to the right of - in the same row if they’re on the same side of the keyboard). At that point, the - hasn’t been added to the report, and the LSHIFT() key causes an extra report to be sent immediately with shift added to whatever was in that partial report. Since the - key got cleared from the report at the end of the previous scan cycle, and hasn’t been added back in yet, a report is sent with just shift, but without -, causing the host to think that the - key has been released.

Then the < keycode is added, and the report now contains shift and < (but no report is sent yet).

Then the - key is processed, adding it back into the the report, which now contains shift, <, and -. This report gets sent to the host, and because (I’m guessing again; I don’t know the German scancode mapping) - has a lower scancode number, it gets handled first, and you end up with _> in the output.

If I’m right, I have a fix for this, involving to PRs: KeyboardioHID#29 & Kaleidoscope-HIDAdaptor-KeyboardioHID#3. I think there’s a good chance that those two changes will solve both problems.

That sounds like a perfect explanation for the behaviour and indeed the key for ‚>‘ is in a higher row then the ‚-‚. I’ll merge your changes to see if it fixes the behaviour. Thank you for your help and time!

1 Like

I finally came around to merging your pull requests into my local firmware. I made sure to delete the cached compiled files in order to recompile everything. The good news is, that typing shifted characters over a remote desktop connection is still working. Unfortunately the problem with getting -_> out of typing - and > in quick succession still remains.

Further testing reveals that “typing in quick succession” really means that I’m still holding the --Key while typing the key that sends Shift+< in order to produce the >. Interestingly this effect can also be observed with other keys that send shifted characters but not all of them. E.g. -!_ (Shift+1) -=_ (Shift+0) but not -? (Shift+ß) nor -% (Shift+5).

2 Likes

Interesting. Can you tell me what version of Kaleidoscope you’re building from? It might also help if you share your sketch file (i.e. Model01-Firmware.ino), and the OS layout you use, so I can see where each of those keys is. If some keys are affected, but not others, that’s almost certainly the scan order bug that I thought I had fixed.

Thank you for your continuous help.
I’m building Kaleidoscope from b6fe84799734ee29a2d4bcf618618e69817ea0dc + my Change to have constants for a German keyboard layout 0a305fcd5a4d8eb87865786c9a6fcd4ee2866493 which you can find as pull request #302.

Kaleidoscope-HIDAdaptor-KeyboardioHID cab61498ce12fa745ad182a6e7acb6d902d5c0ba
KeyboardioHID e300fbed0ff878ffed9c4dd40156f9790b02193b
KeyboardioScanner 02f37af8d64debc5810a27ff949a995d1904f93c

Here is my sketch-File
Model01-Firmware-using-de-Keys.ino (13.1 KB)

I also shared a .zip of my libraries folder via Dropbox.

Thanks for the info; I’ll do some debugging tomorrow.

Aha! Thanks for including that zip file; therein lies the answer (I’m 99% sure).

Your working directory isn’t clean. You’ve still got a copy of the old kaleidoscope/hid.cpp file, with the old version of _pressModifierKey(), which sends that extra report. If you delete that file and re-flash the firmware, you should stop seeing that scan-order bug that causes the repeated keycode.

1 Like