Electron does not listen keydown event - javascript

I am a backend developer who got a little project to fix it.
So my boss gives me an electron project which runs on touch devices.
I know that I can listen any key events in Javascript if I use the document object, but in electron it does not work, it says the docuemnt cannot be found.
So implemented this when I or other support guy press the F12 button then the dev tools be rendered out in the electron app.
mainWindow = new BrowserWindow({
'web-preferences': {'web-security': false}
});
mainWindow.onkeydown = function (e) {
console.log("Key down");
if (e.which === 123) {
console.log("Key is F12");
mainWindow.webContents.openDevTools();
}
};
But this code is not working to me. I have no idea how I can listen the F12 button is pressed.
Unfortunately I cannot render out button to the UI which can show the devtools. Because of the customers mustn't press it.
Sometimes I need to see the realtime console tab in devtools on the device.

There is a known issue in Electron ( which has lately been marked as wontfix ) that prevents the usual approach to catch key events using the traditional JS approach.
There also is a small library called electron-localshortcut that circumvents this issue by hijacking the Electron global shortcuts API when the window is active.
Use like this in your main.js:
const electronLocalshortcut = require('electron-localshortcut');
electronLocalshortcut.register(mainWindow, 'F12', () => {
// Open DevTools
});

Without additional libraries you can use "globalShortcut" of electron
const { app, BrowserWindow, globalShortcut } = require("electron");
globalShortcut.register("CmdOrCtrl+F12", () => {
mainWindow.isFocused() && mainWindow.webContents.toggleDevTools();
});
I think F12 is preserved so I use ctrl+f12 which is not far off

You can use the library mousetrap to add global short cut, because it can be installed through node and could bypass the problem of electron mentioned in the accepted answer.
A code example in the render process would be:
var Mousetrap = require('mousetrap');
Mousetrap.bind('4', function() { console.log('4'); });

Related

Electron "ready-to-show" event not working as expected

Here is a block of code from my application Codey.
src/main.py
// Show window once it has finished initialising
docsWindow.once("ready-to-show", () => {
if (darkMode) {
docsWindow.webContents.send("dark-mode:toggle");
}
if (!isDarwin) {
docsWindow.webContents.send("platform:not-darwin");
}
docsWindow.webContents.send("docs:jump", section);
docsWindow.show();
});
src/docs/renderer.js
window.api.darkMode.toggle.receive(toggleDarkMode);
When darkMode = true, toggleDarkMode is never run.
My application has two different windows - an editor and a docs window. For both windows, on the "ready-to-show" event, "dark-mode:toggle" is sent to the renderer process. However, the docs window fails to run the toggleDarkMode function whilst it works for the editor window.
Note: The application must be packaged using "yarn package" as some features do not work in the dev environment.
Any help will be much appreciated.
(Repo: https://github.com/Liamohara/Codey)
For anyone that's interested. I found a solution to my issue.
src/main.py
// Show window once it has finished initialising
- docsWindow.once("ready-to-show", () => {
+ docsWindow.webContents.once("did-finish-load", () => {
if (darkMode) {
docsWindow.webContents.send("dark-mode:toggle");
}
if (!isDarwin) {
docsWindow.webContents.send("platform:not-darwin");
}
docsWindow.webContents.send("docs:jump", section);
docsWindow.show();
});
In the docs window, there is more HTML content to be renderered than in the editor window. As a result, the DOM takes longer to load and the "ready-to-show" event is emitted before it has finished. Using the "did-finish-load" event, ensures that the API functions are not called before the DOM has finished loading.

How to make page search on electron like in Chrome or VS Code or Firefox? [duplicate]

Does the Electron application framework have built-in text search?
The quick-start application doesn't provide any apparent search functionality (e.g. using Ctrl-F or from the menu options). I would have expected this to be a BrowserWindow option (or an option of its WebContents), but I don't see anything helpful in the docs.
I know this is an old thread, but might still be relevant for people out there.
Had the same problem, and first fixed by using electron-in-page-search, but this component doesn't work properly with Electron 2 or greater.
Then finally found electron-find resolved my problem. Using with Electron 4.
You just add the component to your project:
npm install electron-find --save
Add a global shortcut in your Electron main process to send an event to the renderer in a ctrl+f:
globalShortcut.register('CommandOrControl+F', () => {
window.webContents.send('on-find');
});
And then you can add this to your page (the renderer process)
const remote = require('electron').remote;
const FindInPage = require('electron-find').FindInPage;
let findInPage = new FindInPage(remote.getCurrentWebContents());
ipcRenderer.on('on-find', (e, args) => {
findInPage.openFindWindow()
})
Hope that helps.
Try webContents.findInPage just added in the latest version.
There is an issue with the solution Robson Hermes offered. globalShortcut is, by definition, global, so the shortcut will be detected even when the app is not focused. This will result in the Ctrl+F shortcut being "stolen" from everywhere else.
I have found no ideal solution (see this issue on the electron repository), but a hacky one can be achieved by doing what Robson said and adding
win.on('focus', () => {
globalShortcut.register('CommandOrControl+F', () => windows.main.send('on-find'))
})
win.on('blur', () => {
globalShortcut.unregister('CommandOrControl+F')
}
Note that as seen here, this is not ideal and can lead to several issues:
Other applications can get a lock on the shortcut when you lose focus, i.e. the shortcut will magically stop working when you switch back to the app later.
Some apps can appear on screen without taking focus (spotlight I believe has this behavior) and during the app's appearance the shortcuts will still be captured by your application.
There's also gonna be those weird one in a thousand situations where somehow you switch focus and the shortcut is not removed.
Instead of using global shortcuts , use Accelerators ( normal Keyboard shortcut )
{
label : 'help',
click : function(){.
electron.shell.openExternal('http://....').
},
accelerator : 'CmdOrCtrl+ Shift + H'
}
The above shown is just an example of How to use accelerator

Cordova backbutton breaking application

I have a problem with Cordova's android application based on Angular 5+. I've found that window.history.back() and similar native JS back functions make two problems:
when going back, a page is flashing. It seems like first, all HTML content loaded and after it CSS
In one page on a back action, my layout is broken (screens below)
Orginal view:
After back button:
What's curious - after changing phone orientation all backs to normal.
I've found a solution - instead of using vanilla JS back functions I've created mine using Angular Router:
I've subscribe on router's events and save all routes:
this._subs.push(this._router.events.subscribe((e) => {
if (e instanceof NavigationEnd) {
this._cordovaService.saveRoute(e.url);
}
}));
And if I want back, I use navigateByUrl function:
back(): void {
const lastRoute = this._routingHistory[this._routingHistory.length - 2];
if (lastRoute) {
this._router.navigateByUrl(lastRoute);
this._routingHistory.pop();
}
}
After implementing this functionality for my inApp back buttons all work fine - there is no flashing or breaking layout.
Although, after implemented this function for my physical back button, the error is the same - layout breaking or flashing. Below my implementation:
Service:
this.deviceReady = Observable.fromEvent(document, 'deviceready').publishReplay(1);
(this.deviceReady as ConnectableObservable<Event>).connect();
this.restore = Observable.fromEvent(document, 'resume').publishReplay();
(this.restore as ConnectableObservable<Event>).connect();
this.backbutton = Observable.fromEvent(document, 'backbutton').publishReplay();
(this.backbutton as ConnectableObservable<Event>).connect();
Using it:
this._subs.push(this._cordovaService.deviceReady.subscribe(
() => {
document.addEventListener('backbutton', function (e) {
e.preventDefault();
e.stopPropagation();
this._cordovaService.back();
}.bind(this), false);
}
)
);
I'm sure that function in backbutton is executed (I've logged some information) but the problem still occurs.
More information:
I'm using cordova version 8.0.0
I'm using the following plugins:
https://github.com/TheMattRay/cordova-plugin-wkwebviewxhrfix.git" />
Some hints:
Once, I've built Cordova's android applications which work great (with native JS back function) but after next build, all come back. In hockeyapp I see that in good working version lowest available Android version was 4.1. In new apps, it is 4.4.
I've tried to downgrade Cordova/android engine version but without any positive results.
Additionally, I want to work with the newest libraries available.
Thanks for any help in that case.
I've finally found the solution, based on the following blog's post: http://weblogs.thinktecture.com/thomas/2017/02/cordova-vs-zonejs-or-why-is-angulars-document-event-listener-not-in-a-zone.html, I've added below script just before cordova.js import:
<script>
(function () {
'use strict';
window.addEventListener = function () {
EventTarget.prototype.addEventListener.apply(this, arguments);
};
window.removeEventListener = function () {
EventTarget.prototype.removeEventListener.apply(this, arguments);
};
document.addEventListener = function () {
EventTarget.prototype.addEventListener.apply(this, arguments);
};
document.removeEventListener = function () {
EventTarget.prototype.removeEventListener.apply(this, arguments);
};
})();
</script>
<script type="text/javascript" src="cordova.js"></script>
More about why this error occurring you can read in this GitHub issue: https://github.com/angular/angular/issues/22509

Electron app.makeSingleInstance is allowing unlimited instances

My Main.js code is:
let mainWindow = null;
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (mainWindow.isMinimized()){
mainWindow.restore();
}
mainWindow.show();
mainWindow.focus();
}
});
if (shouldQuit) {
app.quit();
}
This is basically identical to the Electron docs, and to all examples I can find on the web. Has anyone else had this issue? I see on the web a good deal of people saying this code doesn't work for them.
I am building my app using Electron-Builder.
Thank you.
This started working some time ago, and I have since upgraded Electron a few times, so I am forced to assume this was an Electron bug in versions below 1.4.
Countless other experiences on the web that also went unsolved during this time lend credence to this idea.
...
// Force Single Instance Application
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (win) {
if (win.isMinimized()) win.restore()
win.focus()
}
})
if (shouldQuit) {
app.quit()
return
}
...
Refs: app.makeSingleInstance(callback): and dominikfiala's comment

globalShortcut from electron will disable the original keypress

I am trying to intercept Ctrl+C and Ctrl+V commands and get the value from the clipboard in Electron.
I tried doing it using GlobalShortcut from electron
const ret = globalShortcut.register('CommandOrControl+X', () => {
console.log('CommandOrControl+X is pressed')
})
This is intercepting the keyevent but it stops the original keyevent from happening,
One way is to intercept using above code and then manually execute the key event from it.
Can anyone please help me with what can be done in this case?
There also is a small library called electron-localshortcut that enables local scope shortcuts in Electron. When the window is inactive, the referenced shortcuts are disabled and given back to Windows' control.
Use like this in your main.js:
const electronLocalshortcut = require('electron-localshortcut');
electronLocalshortcut.register(mainWindow, 'STRG+C', () => {
// Copy to Clipboard
});

Categories

Resources