pushkin
pushkin

Reputation: 10209

How to toggle devtools in an Electron app while focused on devtools?

I want to make my Electron app toggle developer tools in response to F12.

In the renderer page, I added:

const currentWebContents = require("electron").remote.getCurrentWebContents();
window.addEventListener("keydown", (e: KeyboardEvent) => {
    if (e.keyCode === 123) { // F12
        currentWebContents.toggleDevTools();
    }
});

This works when I'm focused on the main page. However, immediately after the dev tools opens up, focus goes to the dev tools, so F12 is no longer detected.

I tried fixing this by adding a listener to the devtools webcontents right after calling toggleDevTools() like so:

if (currentWebContents.devToolsWebContents) {
    currentWebContents.devToolsWebContents.on("before-input-event", (event: Electron.Event, input: Electron.Input) => {
        if (input.type === "keyDown" && input.key === "F12") {
            currentWebContents.toggleDevTools();
        }
    });
}

However, currentWebContents.devToolsWebContents is null right after opening it. My first question is how to ensure that it isn't null - is there a way to wait until it's fully opened?

I worked around this by putting the if (currentWebContents.devToolsWebContents) code into a setTimeout(..., 1000);

However, upon doing that, my before-input-event handler does not get triggered when pressing keys while focused on the devtools.

Does anybody know why that is?

Upvotes: 7

Views: 4420

Answers (1)

pushkin
pushkin

Reputation: 10209

There is no easy way to do this.

As per this issue, you can't detect input from devtools.

An Electron developer posted a comment here:

I think this is because the toggleDevTools menu role doesn't properly check for the 'parent' window of a devtools window. it would probably be possible to have the toggleDevTools menu role check to see if the currently focused window is a devtools window, and if so, call toggleDevTools on the webcontents for which the devtools is opened, instead of on the devtools window itself.

In any case, this requires Electron development to solve.

Update: Someone here suggested this workaround - I haven't tried it myself:

mainWindow.webContents.on("before-input-event", (e, input) => {
    if (input.type === "keyDown" && input.key === "F12") {
      mainWindow.webContents.toggleDevTools();

      mainWindow.webContents.on('devtools-opened', () => {
        // Can't use mainWindow.webContents.devToolsWebContents.on("before-input-event") - it just doesn't intercept any events.
        mainWindow.webContents.devToolsWebContents.executeJavaScript(`
            new Promise((resolve)=> {
              addEventListener("keydown", (event) => {
                if (event.key === "F12") {
                  resolve();
                }
              }, { once: true });
            })
          `)
          .then(() => {
            mainWindow.webContents.toggleDevTools();
          });
      });
    }
  });

Upvotes: 6

Related Questions