Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special character input using right alt does not work correctly in Chrome on Android #1183

Open
RagingCactus opened this issue Jun 11, 2023 · 6 comments

Comments

@RagingCactus
Copy link

RagingCactus commented Jun 11, 2023

Describe the issue

When using a physical keyboard on Android, special character input using right alt (Sometimes called AltGr) does not work correctly in Chrome. It works correctly in Firefox.

Steps to reproduce:

  • Use a physical keyboard on Android. I use a USB keyboard plugged in via USB C.
  • Configure a physical keyboard layout in Android that outputs special characters using RightAlt + <letter>. The following steps assume the US International Layout provided by Android (“English (US), International style” in the settings).
  • Place the cursor in the editor at https://codemirror.net/try/ (I tested both in "Minimal editor" and "https://codemirror.net/try/?example=Markdown%20code%20block%20highlighting") Try the following test cases:
    • Press RightAlt + a. The character á appears.
    • Press RightAlt + o. The character ó appears.
    • Press RightAlt + u. No character appears in the text area! In Firefox and all other text inputs, ú appears.

Browser and platform

Chrome 114 on Android 12; Using physical keyboard layout "English (US), International style"

Reproduction link

https://codemirror.net/try/

@RagingCactus
Copy link
Author

I have managed to gather more information through debugging. Please note that I haven't worked with CodeMirror before, so take this with a grain of salt. I used the Chrome remote debugger to gather this information.

The fundamental issue is that CodeMirror sees the combination RightAlt + u and executes the keybind for Alt-u (which seems to be redoSelection by default). This seems to be caused by this line in runHandlers https://github.com/codemirror/view/blob/ed10f076c4a2e7a6cd683de4912189287674f6e6/src/keymap.ts#L227 This is the snippet in question:

  let scopeObj = map[scope], baseName, shiftName
  if (scopeObj) {
    if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)])) return true
    if (isChar && (event.altKey || event.metaKey || event.ctrlKey) &&
        // Ctrl-Alt may be used for AltGr on Windows
        !(browser.windows && event.ctrlKey && event.altKey) &&
        (baseName = base[event.keyCode]) && baseName != name) {
// Suspect line below vvvvvvvvvvvvvvvvv
      if (runFor(scopeObj[prefix + modifiers(baseName, event, true)])) return true
// Suspect line above ^^^^^^^^^^^^^^^^^
      else if (event.shiftKey && (shiftName = shift[event.keyCode]) != name && shiftName != baseName &&
               runFor(scopeObj[prefix + modifiers(shiftName, event, false)])) return true
    } else if (isChar && event.shiftKey) {
      if (runFor(scopeObj[prefix + modifiers(name, event, true)])) return true
    }
    if (runFor(scopeObj._any)) return true
  }
  return fallthrough

At that point, event.key is ú, which is correct. prefix + modifiers(name, event, !isChar) is therefore Alt-ú. However, the line in question also looks for bindings with the baseName, i.e. in this case Alt-u, which resolves to a keybind in the playground and therefore it gets handled as a hotkey instead of a key input.

As a test, I cleared the historyKeymap array which adds the conflicting keybind in the playground and it solves the issue, confirming that this is indeed the cause.

As I'm not familiar with CodeMirror, I cannot offer any insight on what would be the correct way to resolve this. Speaking as a user, I would expect the keybinds to only work on an exact match with the binding. If I wanted to press Alt-u, I would use the left alt key for that, as that one doesn't switch to the special character layer.

I hope this clears up my bug report a bit. Please reach out if you need any additional information.

@marijnh
Copy link
Member

marijnh commented Jun 27, 2023

Does Android set ctrlKey as well as altKey for AltGr key events? Some platforms don't set altKey for it (which makes sense, since it doesn't behave like Alt), but I'm not sure how Android works. I found a comment suggesting that it works like that but it'd be great if you could confirm.

@RagingCactus
Copy link
Author

RagingCactus commented Jun 27, 2023

I looked into this again. I set a breakpoint somewhere where I could get access to the key event and started testing. For this, I used my actual EurKEY keymap instead of US International, so I get slightly different special characters (Umlauts), but I'm confident this doesn't change anything regarding the general mechanism.

TLDR: RightAlt/AltGr usage has altKey: true on Android, but it also has ctrlKey: false.
Ctrl+LeftAlt is also not equivalent to RightAlt/AltGr on Android (unlike on Windows, where Ctrl+LeftAlt is equivalent to pressing RightAlt/AltGr).

I have made screenshots for multiple different cases:

RightAlt + a -> ä (this one works):
grafik

RightAlt + Shift + a -> Ä (but does not work, triggers a block comment keybinding instead!):
grafik

RightAlt + u -> ü (but does not work, triggers a keybinding instead):
grafik

RightAlt + Shift + ü -> Ü (this one works):
grafik

As a sidenote:

Some platforms don't set altKey for it [AltGr functionality] (which makes sense, since it doesn't behave like Alt), but I'm not sure how Android works

I agree that that would be reasonable behavior, as I would use the left alt key if I really wanted the alt key in there as well.

@marijnh
Copy link
Member

marijnh commented Jun 27, 2023

It seems there is no straightforward way to distinguish between Alt and AltGr on this platform then. This is problematic, because for example people using a Cyrillic keyboard expect Ctrl-z bindings to fire when they press Ctrl-ю, despite event.key holding "ю" (which is what the fallback branch you traced this to handles).

@RagingCactus
Copy link
Author

I understand the problem. Even if you kept the fallback in for Ctrl and only inserted special handling for Alt, this fails when using Ctrl+Alt Keybinds.

It looks to me that you can only distinguish which alt is pressed in the keydown event for the alt key itself (using event.location). Using that would require buffering which alt was pressed. I'm not a frontend developer, but that sounds terribly error-prone.

The most similar platform available to me is Chrome on Linux (X11), where event.altKey is false when typing RightAlt/AltGr + u, which sounds reasonable.
grafik

Is this perhaps something you could bring up to the Chrome team? It looks like there would be no good way to provide a native-feeling editor experience to international layout users then.

@marijnh
Copy link
Member

marijnh commented Jun 27, 2023

I don't have any special leverage with the Chrome team, but this inconsistency between platforms seems something you could report on https://bugs.chromium.org/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants