How can i capture keypress in Electron without globalShortcut and without losing the key functionality. For example i want to capture Tab press but without losing it's ability to indent for example in visual studio code.
I use Electron 13.0 because if i use higher some required modules don't work.
I tried iohook but throws iohook.node module not found. I think it doens't have support for Electron 13 yet.
Anyone ideea how can i do accomplish this? Thank you !
Electron can be a bit of a headache when it comes to communicate between the window and the main process, and for good reason: Security.
However, this problem has two solutions:
Not recommended: plain ipcRenderer required with { nodeIntegration: true } and window.electron in index.html, that can cause a lot of trouble, don't do that, you give access to the user to all nodejs functions, like fs, child_process, ...
Recomended: preload. Preload makes the bridge between the process and the window allowing you to pick what you want to share with the window, in this case, ipcRenderer without the whole electron access.
Read more about Electron secuity here
First, create a preload.js to pass scope isolated ipcRenderer.send function to the window
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
const exposedAPI = {
sendMessage: (message) => {
ipcRenderer.send('my-event', string);
}
};
contextBridge.exposeInMainWorld("electron", exposedAPI);
More about contextBridge here
In the main electron script
// main.js
const { ipcRenderer } = require('electron');
...
const window = new BrowserWindow({
...
preload: 'my/preload/path/preload.js', // Here preload is loaded when the window is created
})
...
ipcRenderer.on('my-event', (string) => {
// do struff with string
});
Great full example here
Finally, the window where you want to capture the event from without changing the behaviour
// index.html or your-script.js
document.addEventListener('keydown', (evt) => { // keyup, keydown or keypress
window.electron.exposedAPI.sendMessage('key was pressed');
});
Related
I have an Electron app using the recommended setup from https://www.debugandrelease.com/the-ultimate-electron-guide/ where access is given via window.api.receive and window.api.send to the preloader. However I need to use window.api.receive within my react component and my issue is don't know how to remove the "receive" when the component is unmounted.
From the react side of things I think i just need to add in the code in the use effect, but I don't know what code can be used to remove the window.api.receive that was added.
// On Mount
useEffect(() => {
console.log('mount APP')
window.api.receive("helpLine", (text, loading) => {
// Things are done here
})
}, []);
// on Unmount
useEffect( () => () => {
console.log("unmount App")
// window.api.receive should be removed here
}, [] );
Use ipcRenderer.removeListener(channel, listener) to remove the specified listener.
https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererremovelistenerchannel-listener
I am writing a new Electron app and to make things a bit more organized I created an object that will encapsulate my display code. My target was to connect the display renderer object with the backend code and keep things really happy.
But, I create the renderer object in the main.js module and I don't know how to get that instance into the preload.js file because all the renderer functions are being called from preload.
What is the right way to tackle this? Global? Is there a way to expose the object instance in main.cs in the preload for each instance I create? (yes, I have multiple renderers created from the same class).
Look at this code which I found on a blog. It's got a similar structure, but I don't see how to access the main.cs renderer object from the preload.
// main.js
app.whenReady().then(() => {`
let mainWindow = new BrowserWindow({`
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true
},
width:640,
height: 480,
resizable: false
})
// ... rest of code
//preload.js
const { contextBridge, ipcRenderer} = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
sendMessage: () => ipcRenderer.send('countdown-start')
}
)
// renderer.js
document.getElementById('start').addEventListener('click', _ => {
window.electron.sendMessage()
})
Basically this question is technically incorrect as I have discovered.
The object I create are in the main process, and the renderer process can't access them at all.
What I ended up doing was exposing methods in the main process to work with the object. I called these methods from Preload and things are working fine.
Sorry for a confusing question.
This question already has answers here:
With contextIsolation = true, is it possible to use ipcRenderer?
(3 answers)
Closed 1 year ago.
> index.html:
As u can see in index.html code (const electron = require('electron');this require arise an error as require is not define i use window10.
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
document.querySelector('form').addEventListener('submit',(event) =>{event.preventDefault();
event.preventDefault();
const file =document.querySelector('input').files[0];
});
</script>
> Main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
mainWindow.loadFile('index.html')
Electron is a package you should use in the nodejs environment, not in the browser. Also in the browser you can't use the require function, you should use instead the import and export syntax.
That because javascript is a script language meant to run in browsers, it doesn't make sense to require electron in your frontend script, but, since your serving your files through the electron service and not in a browser window you can access the require by calling the window.require('pckg') method, still doesn't make any sense to require electron in a client-side window tho, it's like if an express server renders a page that creates another server.
If you just want to create another window you should do that in the main electron file, in your case the Main.js file.
I've recently created an app with a Java backend and a React frontend, and I was using Electron and some Node features to bundle the app and create a desktop app for it. Basically, I decided to use Java for some Java-specific libraries I needed. The app will run on port 8080, with the React/JS stuff being served from the static folder, and the Electron wrapper will use some Node libraries to start up the Java process and then after a few seconds connect to localhost:8080.
This works like a charm about half the time, and the other half instead shows me a white screen with no errors! I have debugged this countless times and the only way to fix it is to force reload the Chromium page which sometimes works, and other times doesn't. Obviously this isn't acceptable for users to do with my app. The problem is, I have run out of ideas as to what could be causing this issue.
Here is my main.js for the electron app
const {app, BrowserWindow} = require('electron')
function createWindow () {
try {
var jarPath = './app.jar';
var kill = require('tree-kill');
var child = require('child_process').spawn('java', ['-jar', jarPath, '']);
let win = new BrowserWindow({width: 1000, height: 730});
setTimeout(function() {
win.loadURL('http://localhost:8080/index.html');
}, 2000);
console.log("PID: " + child.pid);
win.on('closed', function () {
kill(child.pid);
mainWindow = null
}
)
} catch(e) {
console.log(e);
}
}
app.on('ready', createWindow)
I have been searching for a Node module that would allow my application to draw attention from the user by flashing like this. Is this possible using Node?
You can achieve it with electronjs
const { BrowserWindow } = require('electron')
let win = new BrowserWindow()
win.once('focus', () => win.flashFrame(false))
win.flashFrame(true)
documentation