keymanapp / keyman

Keyman cross platform input methods system running on Android, iOS, Linux, macOS, Windows and mobile and desktop web
https://keyman.com/
Other
391 stars 108 forks source link

bug(web): `detachFromControl` causes subsequent hardware keystrokes to throw an error #10031

Closed mcdurdin closed 10 months ago

mcdurdin commented 10 months ago

Describe the bug

If you call detachFromControl on an element in a webpage, then subsequently type with the hardware keyboard into that element, the following error is raised:

Uncaught TypeError: Cannot read properties of null (reading 'interface')
    at Ue (outputTargetForElement.ts:45:31)
    at he (outputTargetForElement.ts:11:10)
    at l._KeyDown (hardwareEventKeyboard.ts:301:20)

This appears to be a regression in 17.0, because I cannot repro with 16.0.142.

Reproduce the bug

The following page was sufficient to reproduce the problem.

  1. Click in the textarea, type, see that Keyman is not active.
  2. Click Attach button, type again into text area, see that Keyman is active (may need to switch to Thai keyboard in KeymanWeb to prove)
  3. Click Detach button, type again into text area, see that Keyman is not active, but error is raised on each keystroke.
<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>

    <!-- Set the viewport width to match iOS device widths -->
    <meta name="viewport" content="width=device-width,user-scalable=no" />
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <title>detachFromControl</title>

    <!-- <script src='https://s.keyman.com/kmw/engine/16.0.142/keymanweb.js'></script>
    <script src='https://s.keyman.com/kmw/engine/16.0.142/kmwuitoggle.js'></script> -->
    <script src='https://s.keyman.com/kmw/engine/17.0.213/keymanweb.js'></script>
    <script src='https://s.keyman.com/kmw/engine/17.0.213/kmwuitoggle.js'></script>
    <script>
      (function(kmw) {
        kmw.init({attachType:'manual'});
        kmw.addKeyboards('@en'); // Loads default English keyboard from Keyman Cloud (CDN)
        kmw.addKeyboards('@th'); // Loads default Thai keyboard from Keyman Cloud (CDN)
      })(keyman);
    </script>

  </head>

<body>

  <textarea id="ta1" style="width:80%; height: 200px"></textarea>
  <br>
  <button id="attach">Attach</button>
  <button id="detach">Detach</button>

  <script>
    const ta1 = document.getElementById('ta1');
    document.getElementById('attach').addEventListener('click',() => {
      keyman.attachToControl(ta1);
      ta1.focus();
    });
    document.getElementById('detach').addEventListener('click',() => {
      keyman.detachFromControl(ta1);
      ta1.focus();
    });

  </script>
</body>
</html>

Expected behavior

No response

Related issues

No response

Keyman apps

Keyman version

17.0.213-alpha

Operating system

Windows 10

Device

No response

Target application

No response

Browser

Chrome 119.0.6045.124

Keyboard name

No response

Keyboard version

No response

Language name

No response

Additional context

No response

jahorton commented 10 months ago

Sounds like the keyboard event listeners aren't being properly disconnected for the setup provided in the issue above; that should help narrow down what control paths aren't being handled properly.