so In electron i have a parent window, and on a ipc event it opens up a child window, how would i open up the child window (which is set to a modal window) but still be able to drag the parent window? so i want the parent window of the child modal window, to still be able to be dragged even though the child window is a modal one
const { app, BrowserWindow, ipcMain } = require('electron')
let win;
let taskWin;
function createWindow() {
win = new BrowserWindow({
height: 800,
width: 1300,
webPreferences: {
nodeIntegration: true,
}
})
win.webContents.openDevTools()
win.loadFile('index.html')
win.on('closed', () => {
win = null
})
}
ipcMain.on('createTask', () => {
taskWin = new BrowserWindow({
height: 600,
width: 1000,
parent: win,
modal: true,
webPreferences: {
nodeIntegration: true,
}
})
taskWin.loadFile('createtask.html')
taskWin.on('closed', () => {
taskWin = null
})
})
app.on('ready', createWindow)
Related
is it possible to read DOM of website with given url in BrowserView?
I have code that looks like this one, and Electron is throwing an error:
"An object could not be cloned"
// Create the browser window.
const mainWindow = new BrowserWindow({
height: 800,
width: 1200,
webPreferences: {
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},
});
const view = new BrowserView({
webPreferences: {
webSecurity: false,
allowRunningInsecureContent: true,
},
});
mainWindow.setBrowserView(view);
view.setBounds({ x: 200, y: 0, width: 900, height: 800 });
view.webContents.loadURL("https://electronjs.org");
view.setAutoResize({ width: true, height: true });
view.webContents
.executeJavaScript("document.querySelector('body')")
.then((result) => {
console.log("html", result);
})
.catch((err) => console.log(err));
// and load the index.html of the app.
mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
// Open the DevTools.
mainWindow.webContents.openDevTools();
};```
I have created a createParentWindow that can invoke a createChildWindow and loads a separate html file. This createChildWindow loads my renderer.js and the renderer loads my webworker.js using Web Worker new operator for processing. Now, if I want to close the createChildWindow using close('X') button,
Does this introduce a memory leak?
Will the object created on the heap be cleaned automatically?
If there is a memory leak, how can I call my worker.terminate() to terminate my worker when the createChildWindow close('X') button is clicked?
Preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('windowExec', {
ExecFunct: () => ipcRenderer.send('asynchronous-message', 'OpenChildWindow')
})
Renderer.js
var worker = new Worker('./worker.js');
worker.addEventListener('message', function(e)
{
//..... code here
}, false);
// Stop the web worker.
function stop() {
console.log('Worker Terminated.');
worker.terminate();
worker = undefined;
}
Worker.js
const {datadecider,getosname} = require("./DatabaseWalker.node");
self.addEventListener('message', function(e)
{
var data = e.data;
switch (data.cmd)
{
case 'datadecider':
self.postMessage(datadecider(data.firstParam, data.secondParam));
break;
case 'getosname':
self.postMessage( "getosname," + getosname());
break;
case 'stop':
self.postMessage('WORKER STOPPED: ' + data.msg +
'. (buttons will no longer work)');
self.close(); // Terminates our worker.
break;
default:
self.postMessage('Unknown command: ' + data.msg);
};
}, false);
Main.js
// Create the browser child window.
function createChildWindow ()
{
singleTon = true;
datatableWindow = new BrowserWindow({
width: 1400,
height: 900,
title: 'Database',
icon: path.join(__dirname, './images/doc.ico'),
parent: parentWindow,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
nodeIntegrationInWorker: true,
enableRemoteModule: true,
contextIsolation: true
}
})
datatableWindow.loadFile('datatable.html')
datatableWindow.on('closed', function(){ // When the child windows is closed, set this to false.
singleTon = false;
datatableWindow = null;
//datatableWindow.webContents.send('destroy_childwindow', 'closed.');
console.log("Deleted datatableWindow.");
})
}
app.whenReady().then(() => {
createParentWindow()
app.on('activate', function ()
{
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0)
{
createParentWindow()
}
});
// Call the child windows when button was clicked from main renderer.
ipcMain.on('asynchronous-message', function (evt, message) {
console.log(message + " - " + singleTon);
if (message == 'OpenChildWindow' && singleTon == false)
{
createChildWindow();
}
else{
console.log("Child window is already running.");
}
})
})
// Create the browser parent window.
function createParentWindow ()
{
RunShellCommand(); // Get the OS distro name.
const parentWindow = new BrowserWindow({
width: 800,
height: 500,
title: 'Database Utility Launcher',
icon: path.join(__dirname, './images/doc.ico'),
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
nodeIntegrationInWorker: true,
enableRemoteModule: true,
contextIsolation: true
},
resizable: false
})
parentWindow.loadFile('parent.html') // Load the parent.html of the app.
parentWindow.on('closed', function(){ // Close all the window when the parent windows is closed.
app.quit();
})
}
I have a list. Click one item and then pop-up window which is named open. It's focused when it first opens, but it's out of focus the second time.
enter image description here
when I click a button, the following code execute. But, winObj.focus() not working in electron. It's only focus the main window. How do I fix it?
chatList.js (build in react)
const onClickBtn = useCallback(
(chat) => {
const winObj = window.open(
`/chatting/${chat.url}`,
chat.url,
"",
true
);
winObj.focus();
},
[]
);
electron.js (same as public/main.js)
function createWindow() {
const win = new BrowserWindow({
width: 400,
height: 700,
webPreferences: {
nodeIntegration: true,
nativeWindowOpen: true,
preload: path.join(__dirname, "/../build/preload.js"),
},
});
const pubUrl = "https://---";
win.loadURL(pubUrl);
//when i click the button above, the event come into here.
win.webContents.setWindowOpenHandler((event) => {
return {
action: "allow",
overrideBrowserWindowOptions: {
...win.webContents.browserWindowOptions,
parent: win,
},
};
});
}
This is an existing bug with Electron.
win.focus() will not actually focus the BrowserWindow. You'll want to send an ipc message down to the main process, grab your BrowserWindow and call win.focus() from there.
I'm making an app using Electron framework and I tried using buttons to close and minimize the window. I've tried multiple things for it to do this but without success.
This is what I have for the moment:
HTML:
<body>
<!-- Titlebar -->
<button id="minimize-button">-</button>
<button id="close-button">x</button>
<!-- Script -->
<script src="./js/minimize-close.js"></script>
</body>
JS (minimize-close.js):
const { ipcRenderer } = require('electron');
document.getElementById("minimize-button").addEventListener('click', () => {
ipcRenderer.send('minimize-window');
});
document.getElementById("close-button").addEventListener('click', () => {
ipcRenderer.send('close-window');
});
JS (index.js):
const { app, BrowserWindow, ipcMain } = require('electron');
function createWindow(){
const window = new BrowserWindow({
width: 960, height: 580,
resizable: false, maximizable: false,
frame: false, autoHideMenuBar: true,
icon: './icon.ico',
webPreferences: {
nodeIntegration: true,
devTools: false
}
});
window.loadFile('./src/index.html');
}
// Minimize and close window
ipcMain.on('minimize-window', () => {
window.minimize();
});
ipcMain.on('close-window', () => {
window.close();
});
app.whenReady().then(() => {
createWindow();
app.on('activate', function(){
if(BrowserWindow.getAllWindows().length === 0){
createWindow();
}
});
});
app.on('window-all-closed', function(){
if(process.platform !== 'darwin'){
app.quit();
}
});
You need to set contextIsolation: false.
Also I have read around that window must be global. If not at some point it will be collected by the garbage collector because function which created it has already finished.
let window;
function createWindow(){
window = new BrowserWindow({
width: 960, height: 580,
resizable: false, maximizable: false,
frame: false, autoHideMenuBar: true,
icon: './icon.ico',
webPreferences: {
nodeIntegration: true,
// devTools: false, // commented for debugging purposes
contextIsolation: false
}
});
window.loadFile('./src/index.html');
window.webContents.openDevTools(); // Open dev tools to see if any error arised. In this case I saw 'require is not defined' before setting contextIsolation. Remove it when going into production.
}
Option B: more "secure"
If security is a concern and you want nodeIntegration and contextIsolation to retain their default secure values then preload.js scheme is needed.
This should be the case if remote content is loaded by your App.
HTML
<body>
<!-- Titlebar -->
<button id="minimize-button">-</button>
<button id="close-button">x</button>
</body>
preload.js
const { ipcRenderer } = require('electron');
window.addEventListener('DOMContentLoaded', () => {
document.getElementById("minimize-button").addEventListener('click', () => {
ipcRenderer.send('minimize-window');
});
document.getElementById("close-button").addEventListener('click', () => {
ipcRenderer.send('close-window');
});
})
index.js
const path = require('path');
function createWindow(){
window = new BrowserWindow({
width: 960, height: 580,
resizable: false, maximizable: false,
frame: false, autoHideMenuBar: true,
icon: './icon.ico',
webPreferences: {
// devTools: false, // commented for debugging purposes
preload: path.join(__dirname, 'preload.js')
}
});
window.loadFile('./src/index.html');
window.webContents.openDevTools(); // Open dev tools to see if any error arised. In this case I saw 'require is not defined' before setting contextIsolation. Remove it when going into production.
}
I am trying to add thumbnail toolbar with specified buttons in a taskbar layout of an application from it's doc. But it's showing some problem.
The main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
const path = require('path')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
if (isSecondInstance) {
app.quit();
}
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
ipcMain.on('open-information-dialog', (event) => {
if (mainWindow) {
const options = {
type: 'info',
title: 'I am abled',
buttons: ['Ok'],
message: 'This is the way.'
}
dialog.showMessageBox(mainWindow, options, function () {})
}
})
ipcMain.on('close', (event) => {
app.quit()
})
ipcMain.on('minimize', (event) => {
mainWindow.minimize()
})
ipcMain.on('progress', (event, per) => {
mainWindow.setProgressBar(per)
})
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
])
The error:
All of my mainWindow reference working fine but when I am trying to set thumbar buttons with setThumbarButtons() it's getting the problem. I just try this one and I don't get any error but it's not showing any buttons on taskber window,
The Code:
app.on('ready', function(){
console.log(mainWindow)
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
})
I can't make any sense with this problem.
The problem is that when you run mainWindow.setThumbarButtons your window hasn't been created. Therefor mainWindow is undefined. Which is the error you are running into, and what it says in the error screenshot you posted.
Currently you are creating and setting your window in the createWindow function.
If you move your setThumbarButtons code into the createWindow function it should work.
Something like the following:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
That way you are creating the mainWindow first and defining it before calling that function. Otherwise mainWindow will be undefined which is what you were experiencing.