Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 772
Bin Avatar asked Oct 19 '25 13:10

Bin


1 Answers

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

like image 188
pergy Avatar answered Oct 21 '25 01:10

pergy