denysdovhan
denysdovhan

Reputation: 986

How to send (emulate) keybinding to webContents in electron?

I'm building electron application that makes a desktop interface for a website. On the website, I already have registered keybindings, like Shift+? that shows the table of all available keybindings.

I have to create an app menu of actions that correspond to the keybindings. Technically, when a user clicks on a menu item, it should trigger the keybinding on a webpage. Example:

When user press Help on the menu → Shift+? keybinding is being triggered → webpage detects keypress → webpage shows the table of all registered keybindings appears.

The problem is that I can't send the Shift+? keybinding to the webContents. These attempts are failing:

webContents.sendInputEvent({type:'char', keyCode: 'Shift+?' });
webContents.sendInputEvent({type:'keydown', keyCode: 'Shift+?' });
webContents.sendInputEvent({type:'keyup', keyCode: 'Shift+?'});

How can I force the webpage to perform an action based on specific keybinding (a.k.a send keybinding to the webpage)?

UPD: I've found out few details. The order of events should be keyDown, char, keyUp. I made a handy function for sending keybindings:

function sendKeybinding(win, keyCode) {
  win.webContents.sendInputEvent({ type: 'keyDown', keyCode });
  win.webContents.sendInputEvent({ type: 'char', keyCode });
  win.webContents.sendInputEvent({ type: 'keyUp', keyCode });
}

The MenuItem that uses this might look like this:

{
  label: 'Show Keymap',
  accelerator: ['Shift+/', '?'],
  click(menuItem, browserWindow) {
    sendKeybinding(browserWindow, '?');
  },
}

Also, there is a hatch in a case with Shift+?: ? can be entered only with Shift pressed, so actually, there is a two accelerators Shift+/ and ?.

However, I still don't know how to enter the keybinding like CmdOrControl+B.

Upvotes: 5

Views: 3322

Answers (1)

pergy
pergy

Reputation: 5531

Additionally to the event order you found out, you can use the modifiers property of sendInputEvents argument to send shift/ctrl/alt etc. modifiers with the key input. See docs for further details

With the following code HTML can detect the shortcut you want:

main.js

const {app, BrowserWindow, Menu} = require('electron')
const path = require('path')

function sendKeybinding (win, keyCode) {
  let modifiers = []
  modifiers.push('shift') // 'control', 'meta', etc.
  win.webContents.sendInputEvent({ type: 'keyDown', modifiers, keyCode })
  win.webContents.sendInputEvent({ type: 'char', modifiers, keyCode })
  win.webContents.sendInputEvent({ type: 'keyUp', modifiers, keyCode })
}

app.on('ready', function () {
  let win = new BrowserWindow()
  win.loadURL(path.resolve(__dirname, 'keybind.html'))
  const menuTemplate = [
    {
      label: 'Show Keymap',
      click (menuItem, browserWindow) {
        sendKeybinding(browserWindow, '?')
      }
    }
  ]
  const menu = Menu.buildFromTemplate(menuTemplate)
  Menu.setApplicationMenu(menu)
})

keybind.html

<html>
<body>
<p id="demo">Pressed Key: </p>
<script>
document.onkeypress = function (event) {
  var elem = document.getElementById("demo")
  elem.innerHTML = 'Pressed Key: ' + event.key
  if (event.shiftKey) elem.innerHTML += ' + Shift '
  if (event.ctrlKey) elem.innerHTML += ' + Ctrl '
  if (event.metaKey) elem.innerHTML += ' + Win/Cmd '
}
</script>
</body>
</html>

Upvotes: 3

Related Questions