Bin
Bin

Reputation: 484

Can't understand `sendInputEvent ` in webContents in ElectronJS

In Gmail, the shortcut of compose is c, and I use forcedWindow.webContents.sendInputEvent({type: 'keyDown', keyCode: 'c'}); to call the feature compose, but it doesn't work, I should add keyUp and char, and then it will works

forcedWindow.webContents.sendInputEvent({type: 'keyDown', keyCode: 'c'});
forcedWindow.webContents.sendInputEvent({type: 'char', keyCode: 'c'});
forcedWindow.webContents.sendInputEvent({type: 'keyUp', keyCode: 'c'});

Here are my questions

  1. What does char stand for?

  2. If I call Go to Tasks shortcut g + k, how should I update the code?

Thanks.

Updated: Here are full codes

 {
label: 'Edit',
submenu: [
  {
    label: 'Compose',
    accelerator: 'CmdOrCtrl+N',
    click(menuItem, forcedWindow, options) {
      if (forcedWindow) {
        forcedWindow.webContents.sendInputEvent({type: 'keyDown', keyCode: 'c'});
        forcedWindow.webContents.sendInputEvent({type: 'char', keyCode: 'c'});
        forcedWindow.webContents.sendInputEvent({type: 'keyUp', keyCode: 'c'});
      }
    }
  }
 ]
}

If I change the codes like this

{
label: 'Edit',
submenu: [
  {
    label: 'Compose',
    accelerator: 'CmdOrCtrl+N',
    click(menuItem, forcedWindow, options) {
      if (forcedWindow) {
        forcedWindow.webContents.sendInputEvent({type: 'keyDown', keyCode: 'c'});
      }
    }
  }
 ]
}

or like this

{
label: 'Edit',
submenu: [
  {
    label: 'Compose',
    accelerator: 'CmdOrCtrl+N',
    click(menuItem, forcedWindow, options) {
      if (forcedWindow) {
        forcedWindow.webContents.sendInputEvent({type: 'char', keyCode: 'c'});
      }
    }
  }
 ]
}

or like this

{
label: 'Edit',
submenu: [
  {
    label: 'Compose',
    accelerator: 'CmdOrCtrl+N',
    click(menuItem, forcedWindow, options) {
      if (forcedWindow) {
        forcedWindow.webContents.sendInputEvent({type: 'keyUp', keyCode: 'c'});
      }
    }
  }
 ]
}

none of them work, why?

Upvotes: 4

Views: 3616

Answers (2)

pergy
pergy

Reputation: 5531

When sending manually from Electron we can emit the following events on the HTML page:

  • keydown: Send keyDown
  • keypress: Send keyDown + char
  • keyup: Send keyUp

The char event representing that the key pressed contains character value to match the description of keypress event in general.

The keypress event is fired when a key that produces a character value is pressed down. Examples of keys that produce a character value are alphabetic, numeric, and punctuation keys. Examples of keys that don't produce a character value are modifier keys such as Alt, Shift, Ctrl, or Meta.

When pressing an alphabetic key on your keyboard it instantly produces keydown and keypress events, thus it's reasonable from a website to listen to keypress event (what Gmail seems to do)

To manually activate those listeners you should send keyDown + char at least. Here's an example for your cases

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

app.once('ready', () => {
  const win = new BrowserWindow()
  win.loadURL('https://gmail.com')

  win.webContents.once('did-finish-load', () => {
    // Compose
    setTimeout(() => {
      console.log('compose...')
      win.webContents.sendInputEvent({type: 'keyDown', keyCode: 'c'})
      win.webContents.sendInputEvent({type: 'char', keyCode: 'c'})
    }, 1000)
    // Cancel Compose
    setTimeout(() => {
      console.log('cancel...')
      win.webContents.sendInputEvent({type: 'keyDown', keyCode: 'escape'})
      win.webContents.sendInputEvent({type: 'char', keyCode: 'escape'})
    }, 2000)
    // Go to Tasks
    setTimeout(() => {
      console.log('go to tasks...')
      win.webContents.sendInputEvent({type: 'keyDown', keyCode: 'g'})
      win.webContents.sendInputEvent({type: 'char', keyCode: 'g'})
      win.webContents.sendInputEvent({type: 'keyDown', keyCode: 'k'})
      win.webContents.sendInputEvent({type: 'char', keyCode: 'k'})
    }, 3000)
  })
})

For the sake of completeness you should send keyUps after every keyDown + char if you want to avoid emitting keypress for every subsequent char. But that's the minimum Gmail seems to be listening to.


The relevant Chromium code if you're interested: https://cs.chromium.org/chromium/src/third_party/blink/public/platform/web_input_event.h

Upvotes: 2

Joshua
Joshua

Reputation: 5332

I think you're on the right track but in the documentation for sendInputEvent it says the keyCode needs to be a valid accelerator key.

From the docs:

keyCode String (required) - The character that will be sent as the keyboard event. Should only use the valid key codes in Accelerator.

And if you look at the docs for accelerator it says letters have to be upper cased.

So the c in your code would be upper cased like this:

forcedWindow.webContents.sendInputEvent({type: 'keyDown', keyCode: 'C'});

sendInputEvent Docs

Accelerator valid key codes

Upvotes: 0

Related Questions