Browse Source

fix: `keyCode`s being incorrectly converted in `webContents.sendInputEvent()` (#39821)

fix: sendInputEvent keyCodes being incorrectly converted

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 1 year ago
parent
commit
4e9c583230

+ 10 - 2
shell/common/gin_converters/blink_converter.cc

@@ -10,6 +10,7 @@
 
 #include "base/containers/fixed_flat_map.h"
 #include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversion_utils.h"
 #include "base/strings/utf_string_conversions.h"
 #include "gin/converter.h"
 #include "gin/data_object_builder.h"
@@ -275,11 +276,18 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(v8::Isolate* isolate,
 
   if ((out->GetType() == blink::WebInputEvent::Type::kChar ||
        out->GetType() == blink::WebInputEvent::Type::kRawKeyDown)) {
+    // If the keyCode is e.g. Space or Plus we want to use the character
+    // instead of the keyCode: ' ' instead of 'Space', '+' instead of 'Plus'.
+    std::string character_str;
+    if (str.size() > 1 && domKey.IsCharacter())
+      base::WriteUnicodeCharacter(domKey.ToCharacter(), &character_str);
+
     // Make sure to not read beyond the buffer in case some bad code doesn't
     // NULL-terminate it (this is called from plugins).
     size_t text_length_cap = blink::WebKeyboardEvent::kTextLengthCap;
-    std::u16string text16 = base::UTF8ToUTF16(str);
-
+    std::u16string text16 = character_str.empty()
+                                ? base::UTF8ToUTF16(str)
+                                : base::UTF8ToUTF16(character_str);
     std::fill_n(out->text, text_length_cap, 0);
     std::fill_n(out->unmodified_text, text_length_cap, 0);
     for (size_t i = 0; i < std::min(text_length_cap - 1, text16.size()); ++i) {

+ 14 - 0
spec/api-web-contents-spec.ts

@@ -818,6 +818,20 @@ describe('webContents module', () => {
       expect(altKey).to.be.false();
     });
 
+    it('can correctly convert accelerators to key codes', async () => {
+      const keyup = once(ipcMain, 'keyup');
+      w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
+      w.webContents.sendInputEvent({ keyCode: 'Space', type: 'char' });
+      w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
+      w.webContents.sendInputEvent({ keyCode: 'Space', type: 'char' });
+      w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'char' });
+      w.webContents.sendInputEvent({ keyCode: 'Plus', type: 'keyUp' });
+
+      await keyup;
+      const inputText = await w.webContents.executeJavaScript('document.getElementById("input").value');
+      expect(inputText).to.equal('+ + +');
+    });
+
     it('can send char events with modifiers', async () => {
       const keypress = once(ipcMain, 'keypress');
       w.webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Z' });

+ 8 - 2
spec/fixtures/pages/key-events.html

@@ -1,11 +1,17 @@
 <html>
 <body>
+<input type="text" id="input" autofocus/>
 <script type="text/javascript" charset="utf-8">
+const { ipcRenderer } = require('electron')
+
 document.onkeydown = function (e) {
-  require('electron').ipcRenderer.send('keydown', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
+  ipcRenderer.send('keydown', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
 }
 document.onkeypress = function (e) {
-  require('electron').ipcRenderer.send('keypress', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
+  ipcRenderer.send('keypress', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
+}
+document.onkeyup = function (e) {
+  ipcRenderer.send('keyup', e.key, e.code, e.keyCode, e.shiftKey, e.ctrlKey, e.altKey)
 }
 </script>
 </body>