Keyboard Shortcuts

Overview

This feature allows you to configure local and global keyboard shortcuts for your Electron application.

Example

Local Shortcuts

Local keyboard shortcuts are triggered only when the application is focused. To configure a local keyboard shortcut, you need to specify an accelerator property when creating a MenuItem within the Menu module.

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

  • index.html
  • main.js
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World!</title>
  6. <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  7. </head>
  8. <body>
  9. <h1>Hello World!</h1>
  10. <p>Hit Alt+Shift+I on Windows, or Opt+Cmd+I on mac to see a message printed to the console.</p>
  11. </body>
  12. </html>
  1. const { app, BrowserWindow, Menu, MenuItem } = require('electron')
  2. function createWindow () {
  3. const win = new BrowserWindow({
  4. width: 800,
  5. height: 600,
  6. })
  7. win.loadFile('index.html')
  8. }
  9. const menu = new Menu()
  10. menu.append(new MenuItem({
  11. label: 'Electron',
  12. submenu: [{
  13. role: 'help',
  14. accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
  15. click: () => { console.log('Electron rocks!') }
  16. }]
  17. }))
  18. Menu.setApplicationMenu(menu)
  19. app.whenReady().then(createWindow)
  20. app.on('window-all-closed', () => {
  21. if (process.platform !== 'darwin') {
  22. app.quit()
  23. }
  24. })
  25. app.on('activate', () => {
  26. if (BrowserWindow.getAllWindows().length === 0) {
  27. createWindow()
  28. }
  29. })

Open in Fiddle

NOTE: In the code above, you can see that the accelerator differs based on the user’s operating system. For MacOS, it is Alt+Cmd+I, whereas for Linux and Windows, it is Alt+Shift+I.

After launching the Electron application, you should see the application menu along with the local shortcut you just defined:

Menu with a local shortcut

If you click Help or press the defined accelerator and then open the terminal that you ran your Electron application from, you will see the message that was generated after triggering the click event: “Electron rocks!”.

Global Shortcuts

To configure a global keyboard shortcut, you need to use the globalShortcut module to detect keyboard events even when the application does not have keyboard focus.

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

  • index.html
  • main.js
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World!</title>
  6. <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  7. </head>
  8. <body>
  9. <h1>Hello World!</h1>
  10. <p>Hit Alt+Ctrl+I on Windows or Opt+Cmd+I on Mac to see a message printed to the console.</p>
  11. </body>
  12. </html>
  1. const { app, BrowserWindow, globalShortcut } = require('electron')
  2. function createWindow () {
  3. const win = new BrowserWindow({
  4. width: 800,
  5. height: 600,
  6. })
  7. win.loadFile('index.html')
  8. }
  9. app.whenReady().then(() => {
  10. globalShortcut.register('Alt+CommandOrControl+I', () => {
  11. console.log('Electron loves global shortcuts!')
  12. })
  13. }).then(createWindow)
  14. app.on('window-all-closed', () => {
  15. if (process.platform !== 'darwin') {
  16. app.quit()
  17. }
  18. })
  19. app.on('activate', () => {
  20. if (BrowserWindow.getAllWindows().length === 0) {
  21. createWindow()
  22. }
  23. })

Open in Fiddle

NOTE: In the code above, the CommandOrControl combination uses Command on macOS and Control on Windows/Linux.

After launching the Electron application, if you press the defined key combination then open the terminal that you ran your Electron application from, you will see that Electron loves global shortcuts!

Shortcuts within a BrowserWindow

Using web APIs

If you want to handle keyboard shortcuts within a BrowserWindow, you can listen for the keyup and keydown DOM events inside the renderer process using the addEventListener() API.

  • index.html
  • main.js
  • renderer.js
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
  6. <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  7. <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  8. <title>Hello World!</title>
  9. </head>
  10. <body>
  11. <h1>Hello World!</h1>
  12. <p>Hit any key with this window focused to see it captured here.</p>
  13. <div><span>Last Key Pressed: </span><span id="last-keypress"></span></div>
  14. <script src="./renderer.js"></script>
  15. </body>
  16. </html>
  1. // Modules to control application life and create native browser window
  2. const {app, BrowserWindow} = require('electron')
  3. const path = require('path')
  4. function createWindow () {
  5. // Create the browser window.
  6. const mainWindow = new BrowserWindow({
  7. width: 800,
  8. height: 600,
  9. })
  10. // and load the index.html of the app.
  11. mainWindow.loadFile('index.html')
  12. }
  13. // This method will be called when Electron has finished
  14. // initialization and is ready to create browser windows.
  15. // Some APIs can only be used after this event occurs.
  16. app.whenReady().then(() => {
  17. createWindow()
  18. app.on('activate', function () {
  19. // On macOS it's common to re-create a window in the app when the
  20. // dock icon is clicked and there are no other windows open.
  21. if (BrowserWindow.getAllWindows().length === 0) createWindow()
  22. })
  23. })
  24. // Quit when all windows are closed, except on macOS. There, it's common
  25. // for applications and their menu bar to stay active until the user quits
  26. // explicitly with Cmd + Q.
  27. app.on('window-all-closed', function () {
  28. if (process.platform !== 'darwin') app.quit()
  29. })
  1. function handleKeyPress (event) {
  2. // You can put code here to handle the keypress.
  3. document.getElementById("last-keypress").innerText = event.key
  4. console.log(`You pressed ${event.key}`)
  5. }
  6. window.addEventListener('keyup', handleKeyPress, true)

Open in Fiddle

Note: the third parameter true indicates that the listener will always receive key presses before other listeners so they can’t have stopPropagation() called on them.

Intercepting events in the main process

The before-input-event event is emitted before dispatching keydown and keyup events in the page. It can be used to catch and handle custom shortcuts that are not visible in the menu.

Starting with a working application from the Quick Start Guide, update the main.js file with the following lines:

  • index.html
  • main.js
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Hello World!</title>
  6. <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  7. </head>
  8. <body>
  9. <h1>Hello World!</h1>
  10. <p>Hit Ctrl+I to see a message printed to the console.</p>
  11. </body>
  12. </html>
  1. const { app, BrowserWindow } = require('electron')
  2. app.whenReady().then(() => {
  3. const win = new BrowserWindow({ width: 800, height: 600 })
  4. win.loadFile('index.html')
  5. win.webContents.on('before-input-event', (event, input) => {
  6. if (input.control && input.key.toLowerCase() === 'i') {
  7. console.log('Pressed Control+I')
  8. event.preventDefault()
  9. }
  10. })
  11. })

Open in Fiddle

After launching the Electron application, if you open the terminal that you ran your Electron application from and press Ctrl+I key combination, you will see that this key combination was successfully intercepted.

Using third-party libraries

If you don’t want to do manual shortcut parsing, there are libraries that do advanced key detection, such as mousetrap. Below are examples of usage of the mousetrap running in the Renderer process:

  1. Mousetrap.bind('4', () => { console.log('4') })
  2. Mousetrap.bind('?', () => { console.log('show shortcuts!') })
  3. Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')
  4. // combinations
  5. Mousetrap.bind('command+shift+k', () => { console.log('command shift k') })
  6. // map multiple combinations to the same callback
  7. Mousetrap.bind(['command+k', 'ctrl+k'], () => {
  8. console.log('command k or control k')
  9. // return false to prevent default behavior and stop event from bubbling
  10. return false
  11. })
  12. // gmail style sequences
  13. Mousetrap.bind('g i', () => { console.log('go to inbox') })
  14. Mousetrap.bind('* a', () => { console.log('select all') })
  15. // konami code!
  16. Mousetrap.bind('up up down down left right left right b a enter', () => {
  17. console.log('konami code')
  18. })