Support global shortcuts that trigger input events (PR #698, Fixes #15)

This adds a new flag, allowing the user to define global shortcuts that trigger input events within the main window.

That way, I could easily wrap SoundCloud and Deezer to create a native app which reacts on my keyboard media buttons.
This commit is contained in:
Benedikt Rötsch 2018-11-05 03:03:52 +01:00 committed by Ronan Jouchet
parent 35c66b02b5
commit 3029cba01f
5 changed files with 149 additions and 4 deletions

View File

@ -1,7 +1,7 @@
import 'source-map-support/register';
import fs from 'fs';
import path from 'path';
import { app, crashReporter } from 'electron';
import { app, crashReporter, globalShortcut } from 'electron';
import electronDownload from 'electron-dl';
import createLoginWindow from './components/login/loginWindow';
@ -122,6 +122,17 @@ if (appArgs.crashReporter) {
app.on('ready', () => {
mainWindow = createMainWindow(appArgs, app.quit, setDockBadge);
createTrayIcon(appArgs, mainWindow);
// Register global shortcuts
if (appArgs.globalShortcuts) {
appArgs.globalShortcuts.forEach((shortcut) => {
globalShortcut.register(shortcut.key, () => {
shortcut.inputEvents.forEach((inputEvent) => {
mainWindow.webContents.sendInputEvent(inputEvent);
});
});
});
}
});
app.on('new-window-for-tab', () => {

View File

@ -2,6 +2,7 @@
## Table of Contents
- [Table of Contents](#table-of-contents)
- [Command Line](#command-line)
- [Target Url](#target-url)
- [[dest]](#dest)
@ -10,10 +11,17 @@
- [[name]](#name)
- [[platform]](#platform)
- [[arch]](#arch)
- [[app-copyright]](#app-copyright)
- [[app-version]](#app-version)
- [[build-version]](#build-version)
- [[electron-version]](#electron-version)
- [[no-overwrite]](#no-overwrite)
- [[conceal]](#conceal)
- [[icon]](#icon)
- [Packaging for Windows](#packaging-for-windows)
- [Packaging for Linux](#packaging-for-linux)
- [Packaging for macOS](#packaging-for-macos)
- [Manually Converting `.icns`](#manually-converting-icns)
- [[counter]](#counter)
- [[bounce]](#bounce)
- [[width]](#width)
@ -29,6 +37,9 @@
- [[user-agent]](#user-agent)
- [[honest]](#honest)
- [[ignore-certificate]](#ignore-certificate)
- [[disable-gpu]](#disable-gpu)
- [[ignore-gpu-blacklist]](#ignore-gpu-blacklist)
- [[enable-es3-apis]](#enable-es3-apis)
- [[insecure]](#insecure)
- [[internal-urls]](#internal-urls)
- [[flash]](#flash)
@ -42,15 +53,20 @@
- [[verbose]](#verbose)
- [[disable-context-menu]](#disable-context-menu)
- [[disable-dev-tools]](#disable-dev-tools)
- [[zoom]](#zoom)
- [[crash-reporter]](#crash-reporter)
- [[zoom]](#zoom)
- [[single-instance]](#single-instance)
- [[tray]](#tray)
- [[basic-auth-username]](#basic-auth-username)
- [[basic-auth-password]](#basic-auth-username)
- [[processEnvs]](#processenvs)
- [[file-download-options]](#file-download-options)
- [[always-on-top]](#always-on-top)
- [[disable-gpu]](#disable-gpu)
- [[global-shortcuts]](#global-shortcuts)
- [Programmatic API](#programmatic-api)
- [Addition packaging options for Windows](#addition-packaging-options-for-windows)
- [[version-string]](#version-string)
- [[win32metadata]](#win32metadata)
- [Programmatic API](#programmatic-api)
## Command Line
@ -553,6 +569,112 @@ nativefier <your-website> --file-download-options '{"saveAs": true}'
Enable always on top for the packaged application.
#### [global-shortcuts]
```
--global-shortcuts shortcuts.json
```
Register global shortcuts which will trigger input events like key presses or pointer events in the application.
You may define multiple global shortcuts which can trigger a series of input events. It has the following structure:
```js
[
{
// Key is passed as first argument to globalShortcut.register
"key": "CommandOrControl+Shift+Z",
// The input events exactly match the event config in Electron for contents.sendInputEvent(event)
"inputEvents": [
{
// Available event types: mouseDown, mouseUp, mouseEnter, mouseLeave, contextMenu, mouseWheel, mouseMove, keyDown, keyUp or char
"type": "keyDown",
// Further config depends on your event type. See docs at: https://github.com/electron/electron/blob/master/docs/api/web-contents.md#contentssendinputeventevent
"keyCode": "Space"
}
]
}
]
```
**Important note for using modifier keys:**
If you want to trigger key events which include a modifier (Ctrl, Shift,...), you need to keyDown the modifier key first, then keyDown the actual key _including_ the modifier key as modifier property and then keyUp both keys again. No idea what this means? See the example for `MediaPreviousTrack` below!
**For more details, please see the Electron documentation:**
* List of available keys: https://github.com/electron/electron/blob/master/docs/api/accelerator.md
* Details about how to create input event objects: https://github.com/electron/electron/blob/master/docs/api/web-contents.md#contentssendinputeventevent
Example `shortcuts.json` for `https://deezer.com` & `https://soundcloud.com` to get your play/pause/previous/next media keys working:
```json
[
{
"key": "MediaPlayPause",
"inputEvents": [
{
"type": "keyDown",
"keyCode": "Space"
}
]
},
{
"key": "MediaPreviousTrack",
"inputEvents": [
{
"type": "keyDown",
"keyCode": "Shift"
},
{
"type": "keyDown",
"keyCode": "Left",
"modifiers": [
"shift"
]
},
{
"type": "keyUp",
"keyCode": "Left",
"modifiers": [
"shift"
]
},
{
"type": "keyUp",
"keyCode": "Shift"
}
]
},
{
"key": "MediaNextTrack",
"inputEvents": [
{
"type": "keyDown",
"keyCode": "Shift"
},
{
"type": "keyDown",
"keyCode": "Right",
"modifiers": [
"shift"
]
},
{
"type": "keyUp",
"keyCode": "Right",
"modifiers": [
"shift"
]
},
{
"type": "keyUp",
"keyCode": "Shift"
}
]
}
]
```
## Programmatic API

View File

@ -56,6 +56,7 @@ function selectAppArgs(options) {
basicAuthPassword: options.basicAuthPassword,
alwaysOnTop: options.alwaysOnTop,
titleBarStyle: options.titleBarStyle,
globalShortcuts: options.globalShortcuts,
};
}

View File

@ -199,6 +199,10 @@ if (require.main === module) {
'--title-bar-style <value>',
"(macOS only) set title bar style ('hidden', 'hiddenInset'). Consider injecting custom CSS (via --inject) for better integration.",
)
.option(
'--global-shortcuts <value>',
'JSON file with global shortcut configuration. See https://github.com/jiahaog/nativefier/blob/master/docs/api.md#global-shortcuts',
)
.parse(process.argv);
if (!process.argv.slice(2).length) {

View File

@ -1,3 +1,4 @@
import fs from 'fs';
import log from 'loglevel';
import inferOs from '../infer/inferOs';
@ -74,6 +75,7 @@ export default function(inpOptions) {
basicAuthPassword: inpOptions.basicAuthPassword || null,
alwaysOnTop: inpOptions.alwaysOnTop || false,
titleBarStyle: inpOptions.titleBarStyle || null,
globalShortcuts: inpOptions.globalShortcuts || null,
};
if (options.verbose) {
@ -117,5 +119,10 @@ export default function(inpOptions) {
options.y = inpOptions.y;
}
if (options.globalShortcuts) {
const globalShortcutsFileContent = fs.readFileSync(options.globalShortcuts);
options.globalShortcuts = JSON.parse(globalShortcutsFileContent);
}
return asyncConfig(options);
}