The Windows' (virtual) touch keyboard (in its standard mode) will inject fake AltGr sequences in order to send symbols that require it. E.g. it tries to send AltGr+2 when you press the "@" button. However it doesn't actually use AltGr, but instead relies on the fact that you can use CtrlL+AltL instead of AltGr on Windows. But the remote end then sees Ctrl+AltL+2, which it does not consider even remotely equivalent to AltGr+2. So it injects the a AltGr, ending up with CtrlL+AltL+AltGr+2. And the application is unlikely to handle that as "enter @". End result is that a bunch of symbols on the touch keyboard don't actually work in ThinLinc. We did improvements for AltGr on bug 5226, but it did not affect this issue. Unfortunately we cannot just play along and send AltGr when we see CtrlL+AltL as that breaks perfectly valid sequences such as CtrlL+AltL+AltGr+9, which we fixed in bug 965.
The same issue exists with Web Access.
Fixed via these? https://github.com/TigerVNC/tigervnc/commit/0f1c63060cc000ddb8b15391b1349ab6653184ba https://github.com/TigerVNC/tigervnc/commit/42d0f5dd74fa0fe3bf3f26a92ecc5846db17895b
The behavior is different, but things don't work. With the 4.11.0 client when pressing "@" we got "Ctrl+Alt+AltGr+2". Now we get "Ctrl+Alt+2" and that doesn't result in an "@" in the session like we want. We will have to look further into this.
The fix upstream wasn't for this unfortunately. It merely fixed the AltGr key itself when Windows touch keyboard is the mode where it mimics a physical keyboard. So still broken: * Windows touch keyboard when in symbol mode (it sends a left Alt instead of the expected right Alt) * The modified key (e.g. "2" should send "@" on a Swedish keyboard) doesn't respect AltGr state. Probably because we look at just right Alt and ignore left Alt. Leaving for later.
A hacky version could be to detect the on screen keyboard. Here is how Firefox does it: > HWND IMEHandler::GetOnScreenKeyboardWindow() { > const wchar_t kOSKClassName[] = L"IPTip_Main_Window"; > HWND osk = ::FindWindowW(kOSKClassName, nullptr); > if (::IsWindow(osk) && ::IsWindowEnabled(osk) && ::IsWindowVisible(osk)) { > return osk; > } > return nullptr; > }