Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

communication between 2 browser windows in electron

I need to build an app that will span across multiple monitor screens, something like this: multiple windows on different monitors Electron supports multiple windows but how do I communicate between them?

like image 576
AIon Avatar asked Oct 25 '16 23:10

AIon


People also ask

How do two Electron Windows communicate?

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.

How do you close a browser window in an Electron?

getElementById("close-btn"). addEventListener("click", function (e) { var window = remote. getCurrentWindow(); window. close(); });

What is IPC Electron?

Inter-process communication (IPC) is a key part of building feature-rich desktop applications in Electron.


3 Answers

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: enter image description here 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: enter image description here

Enjoy the power of Electron !

like image 95
AIon Avatar answered Oct 08 '22 04:10

AIon


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
  }
})
like image 30
Felix Turner Avatar answered Oct 08 '22 04:10

Felix Turner


EDIT: I've created a repository for this: electron-multi-monitor: enter image description here

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:

  • BrowserWindows should have the same affinity (see BrowserWindow docs)
  • Enable nativeWindowOpen of your webPreferences

FYI: you can also use this technique straight in the browser, but they still don't let you move around windows

like image 36
Pieter-Jan Van Robays Avatar answered Oct 08 '22 03:10

Pieter-Jan Van Robays