Shift-enter in mobile phones

Hello! I use shift-enter in prosemirror in desktop browsers to add hard breaks and it works fine. But the same key combination seems to be ignored on iOS/safari and also Android/firefox, though all keyboard events are the same, and shift modifier comes as intended in an arbitrary textarea/editor. How to fix this? Thank you in advance!

On Android virtual keyboards, ‘holding shift’ doesn’t really seem to be a thing, and I wasn’t able to produce any key event with shiftKey true. What kind of test are you doing with an ordinary textarea?

We used this form and it displays all events and keypresses ok: https://unixpapa.com/js/testkey.html

But then we tried to reproduce it with contenteditable element, and had limited success - the shift modifier is there, but it worked as a trigger: https://codepen.io/vsvasya-the-selector/pen/PoeGVJK

The first form shows that it is physically possible to track the shift key. May it be of some help?

It just doesn’t seem like users will expect to be able to press shift-enter on virtual keyboards. At least the ones I am familiar with, the shift key just acts as a toggle to turn the next typed letter uppercase, and is not a modifier that can be combined with arbitrary keys. As such, I’m not sure it makes sense to support such a thing, as it’s not a thing that the platform provides, even if we can somehow detect the act of tapping shift and then enter.

Hi there!

I’m currently dealing with that topic too and I agree with @marijn that on mobile there’s no “actual modifier key concept”. Because a user can not press Shift and Enter at the same time, which would be the only clear signal for the keymapper that a user intentionally wants a hardbreak/newline. Yes, on iOS you do get event.shiftKey is true, but that might be because the user clicked it before, or because of auto capitalization. On Android you never get the event.shiftKey set to true. So things are quite a bit inconsistent too.

Anyways, I’d like to handle this for svedit.dev like ProseMirror does it: To just ignore all key handlers with modifiers when users are typing on a soft keyboard (no matter if on mobile, or use a soft keyboard on a desktop).

Now my problem is, how do I reliably tell apart if a user is on a soft keyboard and keymaps with modifiers should be ignored? My first attempt was checking for a touch device, but that’s too naive, because you might have a Touch display on a laptop with physical keys.

@marijn how do you make that check? Is there a reliable native API for this or do I need a state machine that checks for an explicit sequence of keydown events like “Shift” followed by “Enter”?

Thank you for the help!

Hahah, you’d think so, right? But no. Actually, Chrome sort of has something like this now but of course, Apple, the company that pioneered this whole touchscreen web tradition, never sat down to actually think deeply about any of it, nor will they listen to developers who run into issues. So there’s only a kludge: comparing the size of the visual viewport to document.documentElement.clientHeight, and hoping that when it’s unexpectedly small, that means the keyboard is open.

Thank you @marijn for the hint! That likely saved me a ton of time!

Since I’m taking part in the W3C Editing working group meetings since last December, I’d like to bring up this issue, because I really think there should be a proper way to check for this.

In your view, what would be the ideal API for that?

Would the new VirtualKeyboard API (once supported everywhere) be enough to solve this?

Because I suspect knowing if the virtual keyboard is visible “inside a browser” is not enough. E.g. I’d also want to ignore modifier keys for virtual keyboards on a desktop, that the browser has nothing to do with. E.g. in MacOS when you open the Keyboard Viewer, click on Shift and then Enter, ProseMirror (and my editor) still interpret that modifier. And inserts a newline, not a paragraph.

So isn’t it rather something you want to have access to in an onkeydown handler?

function onkeydown(event) {
  console.log(event.virtual) // returns true when KeyboardEvent originated from a virtual keyboard
}

Anyways, I might also be wrong here with my intuition about soft keyboards on a desktop. Maybe it’s okay there to interpret modifiers like “click Shift” + “click Enter” the same way as when pressed at the same time on a physical keyboard. The MacOS also allows you to do Cmd+C etc. with that Virtual Keyboard. It also doesn’t seem to do stuff like auto capitalization like the mobile keyboards, so maybe the desktop case is okay. Still this whole virtual keyboard behavior stuff is so fuzzy, I’d wish there’s a proper spec for it. :face_with_peeking_eye:

I agree that some kind of origin device information on key events would be a good approach, at least for this use case.

Explicitly pressed shift modifier + enter you could reasonably treat as a shift-enter press, but the annoying thing with iOS is that it’ll also set shiftKey for enter when autocapitalization would have made the next character upper-case. So that means that there’s a good reason to ignore the shift modifier on non-character key events on iOS. I suppose the proper solution there would be for Apple to stop doing that, since it makes no semantic sense, but getting through to them on stuff like this is a whole issue in itself.