最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Make global shortcut configurable in electron app - Stack Overflow

programmeradmin3浏览0评论

I packaged a webapp (a softphone) into an electron app to benefit from few automatisms I can code into the app with electron.
I'm using electrons globalShortcut to register a global shortcut to bring the app into the front and focus on the search bar of the web app.

However, because my colleagues started to use the app as well, I want to make the used global shortcut configurable.
As I do not have the possibility to alter the web app itself (it's hosted by a third party), I'm clueless on how to create a menu where a user may setup the shortcut.
I know there is the menu and menuItem objects but I don't know how to ask the user for a key or key bination to set up as globalShortcut using that.

How do I do that?

Edit:
To clarify what I expect: As I already explained, I'm looking for any solution that would make it possible to offer a menu where you can configure a shortcut. That menu may live in the menubar/toolbar or may be put inside the web document through javascript DOM manipulation - maybe using an iframe as last resort?
Any Idea on how to save the setting over restarts of the app are also appreciated.

I packaged a webapp (a softphone) into an electron app to benefit from few automatisms I can code into the app with electron.
I'm using electrons globalShortcut to register a global shortcut to bring the app into the front and focus on the search bar of the web app.

However, because my colleagues started to use the app as well, I want to make the used global shortcut configurable.
As I do not have the possibility to alter the web app itself (it's hosted by a third party), I'm clueless on how to create a menu where a user may setup the shortcut.
I know there is the menu and menuItem objects but I don't know how to ask the user for a key or key bination to set up as globalShortcut using that.

How do I do that?

Edit:
To clarify what I expect: As I already explained, I'm looking for any solution that would make it possible to offer a menu where you can configure a shortcut. That menu may live in the menubar/toolbar or may be put inside the web document through javascript DOM manipulation - maybe using an iframe as last resort?
Any Idea on how to save the setting over restarts of the app are also appreciated.

Share Improve this question edited Apr 14, 2020 at 14:42 wullxz asked Apr 6, 2020 at 9:54 wullxzwullxz 19.6k8 gold badges34 silver badges52 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4 +200

After seeing this question I did a small research on your topic. First thing came to mind is does electron give access to listen to key events, but according to this thread electron devs are stopping electron being a keylogger. So I have following method for this issue. I don't know whether these are the best ones for this scenario, but this is the way how I see it can be done. This is basically build around electron-store where it can be used to persist user's defined key bination. So app can retrieve the defined key bination from the store (if there is no binations configured it uses default key bination provided on the schema) and register an globalshortcut using it. I have provided steps how to implement it

  1. Install and configure a default key value using electron-store. Like follows

main.js

const Store = require('electron-store'); 
const schema = {
    defaultKeyCombination: {
        type: 'string',
        default: 'CommandOrControl+Y'
    }
}
const store = new Store({schema});
  1. Importing this defaultKeyCombination you can register a global-shortcut when the app is ready. (dont forget to remove the globalshortcut when the app is destroyed)
app.on('ready', () => {
    // Register a defaultKeyCombination shortcut listener.
    globalShortcut.register(store.get('defaultKeyCombination'), () => {
    // Do stuff when Y and either Command/Control is pressed.
    })
})
  1. Create and open a another browserWindow from a menu-click (menubar> options> configure) and let users to create/enter an accelerator modifiers in to input box using the available modifiers and key codes (its better to show these on the new window below the input box); For example: User can can enter a MODIFIER+KEY_CODE like CmdOrCtrl + A in to input on the browswer.

  2. Once the user press submit button send the entered key bination using IPCRenderer to the main process and set the store defaultKeyCombination value by the received value.

  3. Trigger the IPC to send reply saying to the user "Please Restart the app" and display it on alert or anything.

renderer process

let args = "CmdOrCtrl+A"
ipcRenderer.send('set::keybine',args)
    
ipcRenderer.on('done::keybine', (event, arg) => {
// display message to restart the app
})

main process

ipcMain.on('set::keybine', (event, arg) => {
    console.log(arg) // prints "keybine"
    //setting the new value
    store.set('defaultKeyCombination', arg)
    // sending reply to renderer work is done
    event.reply('done::keybine')
})

Once the app is restarted store will load out the new configured key bination and register an shortcut event using it.

This is what I got in to mind while doing this small research. Here I found a key event listener called iohook ,but this only available for electron 2.XX . In the above process there can be bugs and flow issues, I just posted with some code to get an idea.

Edit 1:

This is my samples. On my index.html I defined an button to call set() function. You can integrate inputbox so you can enter the mands. Once the key is set with the store, it always loading with this new key-value unless user changes it. You can read more about electron-store from here Hope this will give you an idea :)

Main.js

const {app, BrowserWindow, ipcMain } = require('electron')
const Store = require('electron-store'); 
const schema = {
  defaultKeyCombination: {
    type: 'string',
    default: 'CommandOrControl+Y'
  }
}
const store = new Store({schema});

console.log(store.get("defaultKeyCombination"))

function createWindow () {
  const window = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  window.loadFile('./index.html')
  // window.loadURL("https://www.zap.co.il")
  window.webContents.openDevTools()
}
ipcMain.on('set::keybine', (event, arg) => {
  console.log(arg) // prints "keybine"
  //setting the new value
  store.set('defaultKeyCombination', arg)
  // sending reply to renderer work is done with new key 
  event.reply('done::keybine', store.get('defaultKeyCombination'))
})


app.wheReady().then(createWindow)

//app.on('ready', createWindow)

app.on('window-all-closed', () => {
  // On macOS it is mon for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

Renderer.js

const { ipcRenderer } = require('electron')
function set() {
  console.log("clicked")
  let args = "CmdOrCtrl+A"
  ipcRenderer.send('set::keybine',args)

}
ipcRenderer.on('done::keybine', (event, arg) => {
  console.log("DONEEEEEEEEEE", arg)
})

Let's say hotkeySettings.html

<!DOCTYPE html>
<html lang="en">
  <head> </head>
  <body>
    <input id="hotkey" onkeyup="keyUp(event)" />
    <button id="save" onclick="saveHotkey()">save</button>
    <script>
      const storage = require("electron-json-storage");
      async function loadHotkey() {
        storage.get("hotkey", function (error, key) {
          document.getElementById("hotkey").value = key;
        });
      }
      async function saveHotkey() {
        const { globalShortcut } = require("electron").remote;

        const hotkey = document.getElementById("hotkey").value;
        await storage.set("hotkey", hotkey);
        globalShortcut.register(hotkey, () => {
          console.log(hotkey, "key pressed");
        });
      }
      function keyUp(event) {
        const keyCode = event.keyCode;
        const key = event.key;
        const charCode = event.code;

        if ((keyCode >= 16 && keyCode <= 18) || keyCode === 91) return;

        const value = [];
        event.ctrlKey ? value.push("Control") : null;
        event.shiftKey ? value.push("Shift") : null;
        event.isAlt ? value.push("Alt") : null;
        value.push(key.toUpperCase());

        document.getElementById("hotkey").value = value.join("+");
      }
      loadHotkey();
    </script>
  </body>
</html>

loadHotkey function: will load the prev registered hotkey. hotkey is in appData.

saveHotKey function: will register new Hotkey based on your input and save this value to appData so this will be persist.

At main.js

...
// Open this browserWindow when you click menuItem to see the registered hotkey
// And to update the hotkey
const hotkeySettingsWindow = new BrowserWindow({
    height: 600,
    width: 600,
    webPreferences: {
      nodeIntegration: true
    }
})
hotkeySettingsWindow.loadFile('hotkeySettings.html')
发布评论

评论列表(0)

  1. 暂无评论