https://bugs.kde.org/show_bug.cgi?id=429400

--- Comment #12 from BXLSTNRD <[email protected]> ---
Comment on attachment 197016
  --> https://bugs.kde.org/attachment.cgi?id=197016
Zip file with testcase analysis and workaround

I have been investigating what appears to be the same underlying issue on a
current Fedora/KDE Connect setup, and I think I can add some detail to the
point reached in comment 10.

Tested environment:

- Fedora 44, Plasma Wayland
- kde-connect 26.08.1-1.fc44
- KWin / plasma-workspace 6.7.5
- libei 1.6.0
- libxkbcommon 1.13.1
- KDE Connect Android remote input using Samsung's software keyboard
- US and Belgian (be/oss) desktop layouts tested

I did not record the exact Android, Samsung keyboard or KDE Connect Android
versions, so I do not want to infer those.

On the unmodified 26.08.1 desktop release I could reproduce, among others:

- "A -> a"
- ": -> ;"
- "? -> /"
- "! -> 1"
- "@ -> 2"

With Belgian AZERTY, shifted number-row characters were affected as well.

A debugger check at "NetworkPacket::unserialize" showed that "key="A"" was
already arriving intact at the desktop side, while the receiving application
got lowercase "a". This led the investigation further into the Wayland/libei
input path.

The issue appears to be in the keysym-to-keycode conversion.

In 26.08.1, "Xkb::keycodeFromKeysym()" searches the XKB keymap levels until it
finds the requested keysym, but returns only the physical keycode. Information
about the modifier(s) required to select that XKB level is discarded.

"RemoteDesktopSession::keyboardKeysym()" then injects that physical keycode
through libei without synthesizing the required level modifier.

In simplified form:

"A -> find physical key containing A on Shift level -> return only keycode ->
inject keycode -> a"

The same mechanism explains cases such as "@ -> 2", "! -> 1", ": -> ;", etc.

I made a local proof-of-concept correction which resolves a keysym to a
keystroke consisting of:

- the evdev keycode
- any required Shift / ISO_Level3_Shift / ISO_Level5_Shift modifiers derived
from the active XKB keymap

Only modifiers not already held by the remote input state are synthesized. They
are pressed before the target key and released afterwards.

With that locally rebuilt mousepad plugin, live tests produced exact expected
output for both:

US:
"aA zZ 1234 https:// ; : / ? ! @"

Belgian be/oss:
"aA zZ 1234 https:// ; : / ? ! @ €"

A regression test covering all 95 printable ASCII characters on the tested
layouts, modifier ownership, AltGr/Level3 and simulated Caps Lock also passes.

This is not claimed to be a complete upstream-ready solution. In particular,
the following still need maintainer review:

- synchronization of the stored XKB state with physical lock/group changes
- layout/group changes during an active session
- the current implementation uses one pending synthetic keystroke and assumes
the existing synchronous press/release pattern
- more complex XKB layouts may expose cases beyond Shift/Level3/Level5
- the full KDE Connect test suite has not been run

I also inspected current upstream master (HEAD inspected:
"32c1764305ce116685ef6f8331144006db8e4bd2", 2026-10-10).

Master now has a direct libei text path when "EI_DEVICE_CAP_TEXT" is available,
so my 26.08.1 reproduction should NOT be taken as evidence that this newer
direct text path is broken.

However, "keyboardKeysym()" is still used as a fallback (including modified
text), and the inspected fallback keysym conversion still appears to reduce the
result to a physical keycode without retaining the XKB level modifiers. I have
not rebuilt or live-tested current master, so that observation is source
inspection only.

This also seems related to Bug 489524. That fix allowed uppercase keysyms to
reach portal input, but if the later keysym-to-keycode conversion discards the
Shift level again, uppercase input can still become lowercase further
downstream.

For transparency: the diagnosis, proof-of-concept implementation and
documentation involved substantial AI assistance. I performed the live Android
tests and reviewed the resulting technical analysis. I am reporting the
findings rather than submitting a merge request.

I am also not committing to maintain this patch or shepherd an MR through
review. The goal is to provide the reproduction, identified failure point and a
locally validated possible solution so that a maintainer or another contributor
can take it further if useful.

I have a review package containing the technical report, test results,
sanitized live-test records and the exact tested release patch, and can attach
it here.

-- 
You are receiving this mail because:
You are watching all bug changes.

Reply via email to