I need to build an app that will span across multiple monitor screens, something like this: Electron supports multiple windows but how do I communicate between them?
You actually can communicate between 2 Electron windows via JS if you open the popup window from the renderer process of the main window, by using window. open(). This avoids the need to communicate via IPC calls.
getElementById("close-btn"). addEventListener("click", function (e) { var window = remote. getCurrentWindow(); window. close(); });
Inter-process communication (IPC) is a key part of building feature-rich desktop applications in Electron.
The main thing to remember is that in Electron, interProcess communication is done by ipcMain (in the main process) and ipcRenderer(in all the created windows). Like below: From what i've seen in the GitHub comments - direct communication between the Renderer instances is not allowed. Everything must pass trough the mainProcess.
the code: mainProcess.js:
function createWindow1 () {
window1 = new BrowserWindow({width: 800,height: 600})
window1.loadURL(`file://${__dirname}/window1.html`)
window1.webContents.openDevTools()
window1.on('closed', function () {
window1 = null
})
return window1
}
function createWindow2 () {
window2 = new BrowserWindow({width: 1000, height: 600})
window2.loadURL(`file://${__dirname}/window2.html`)
window2.webContents.openDevTools()
window2.on('closed', function () {
window2 = null
})
return window2
}
app.on('ready', () => {
window1 = createWindow1();
window2 = createWindow2();
ipcMain.on('nameMsg', (event, arg) => {
console.log("name inside main process is: ", arg); // this comes form within window 1 -> and into the mainProcess
event.sender.send('nameReply', { not_right: false }) // sends back/replies to window 1 - "event" is a reference to this chanel.
window2.webContents.send( 'forWin2', arg ); // sends the stuff from Window1 to Window2.
});
window1.html:
<body>
<input type="text" id="name" value="" placeholder="Enter your name">
<button type="button" id="sendName" >Send the name! </button>
</body>
<script>
// You can also require other files to run in this process
require('./window1.js')
</script>
window1.js:
const ipcRenderer = require('electron').ipcRenderer
let name = document.getElementById('name');
ButtonSendName = document.getElementById('sendName');
ButtonSendName.addEventListener('click', (event) => {
ipcRenderer.send('nameMsg', name.value);
})
ipcRenderer.on('nameReply', (event, arg) => {
console.log(arg) // why/what is not right..
});
window2.html:
<body>
<p id = "showName"></p>
</body>
<script>
require('./window2.js')
</script>
window2.js:
const { ipcRenderer } = require('electron')
showName = document.getElementById('showName')
ipcRenderer.on('forWin2', function (event, arg){
console.log(arg);
showName.innerHTML = arg;
});
console.log("I'm Window2");
A demo would be better, but I don't know how to build an electron CodeBin app. This image gives you an idea:
Enjoy the power of Electron !
You actually can communicate between 2 Electron windows via JS if you open the popup window from the renderer process of the main window, by using window.open(). This avoids the need to communicate via IPC calls. See Docs.
For example:
//renderer process
let popupWindow = window.open(
'./popup.html',
'popup'
'width=800,height=600'
);
popupWindow.onload = () => {
//now we have access to popup window dom
popupWindow.document.body.appendChild(myDomElement);
};
Note that for this to work you need to set the nativeWindowOpen webPreferences option when you initially create the main window.
// main process
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nativeWindowOpen: true
}
})
EDIT: I've created a repository for this: electron-multi-monitor:
We had a similar issue for our project. However both BrowserWindows had to pass JS objects & functions back and forth.
The proposed solution via IPC calls was the first thing we tried but wasn't sufficient. It works great when you only need to pass a few small object but you'll soon reach it's limits as Electron will serialize all data passed via IPC calls.
The way we went forward was by using the window.opener functionality. We use electron to spawn one main
BrowserWindow, which then opens the wanted number of side
Browser Windows via window.open(). Electron can position those windows as they spawn.
Next each side
window will register it's HTML DOM as its JS window instance with the main
window. That way the main
window has a reference to the side
windows' DOM and JS window instance.
From here on you the main
window has full control over all the available windows, and can just render new HTML, pass JS objects, call JS functions, ... on all the windows. Personally we use React Portals to handle the rendering on the different windows.
Currently I can't share a complete example, but if I find the time I'll create a github repo.
A few things that can already help you forward:
affinity
(see BrowserWindow docs)nativeWindowOpen
of your webPreferencesFYI: you can also use this technique straight in the browser, but they still don't let you move around windows
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With