Can electron webview transform mouse event to touch event? - electron

I want to simulate a mobile device in desktop environment. I can't find a argument to transform mouse event to touch event.
How can I approach this job? Any hint will be great. Thank you so much.

I think I figured it out. Dev environment:
node 7.4.0
Chromium 54.0.2840.101
Electron 1.5.1
const app = electron.app
const BrowserWindow = electron.BrowserWindow
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1024,
height: 768,
frame: false,
x: -1920,
y: 0,
autoHideMenuBar: true,
icon: 'assets/icons/win/app-win-icon.ico'
});
try {
// works with 1.1 too
mainWindow.webContents.debugger.attach('1.2')
} catch (err) {
console.log('Debugger attach failed: ', err)
}
const isDebuggerAttached = mainWindow.webContents.debugger.isAttached()
console.log('debugger attached? ', isDebuggerAttached)
mainWindow.webContents.debugger.on('detach', (event, reason) => {
console.log('Debugger detached due to: ', reason)
});
// This is where the magic happens!
mainWindow.webContents.debugger.sendCommand('Emulation.setTouchEmulationEnabled', {
enabled: true,
configuration: 'mobile',
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true,
show: false,
backgroundColor: '#8e24aa ',
}));
// Show the mainwindow when it is loaded and ready to show
mainWindow.once('ready-to-show', () => {
mainWindow.show()
})
}
// Listen for app to be ready
app.on('ready', createWindow);

Take a look at this Electron github issue or this Atom Discussion for ideas on how to get the touch working with Electron.
As far as how to approach it, I would look through the mouse events and touch events and just wire up a function that combines the Electron api and the relevant web api for mouse/touch.

Looking at the web-contents API, the only thing you can do is to open the dev tools with:
// win being a BrowserWindow object
win.webContents.openDevTools();
Then you will have to manually click on the responsive tools (the smartphone icon), and you will get into the mode you want.
But I am afraid there is no way to do it programatically. Mostly because it is considered as a development tool, and not a browser feature, so you will have the toolbar at the top and all these things. Not really something you want on Production.

You can try to use Microsoft Windows Simulator. You need to install Visual Studio 2019 with Universal Windows Platform development then run the simulator through:
C:\Program Files (x86)\Common Files\Microsoft Shared\Windows Simulator\16.0\Microsoft.Windows.Simulator.exe
I tested my electron app that also needs to run well both on touchscreen devices and devices without touch screen using this and it works really well to simulate touchscreen devices.
Do not forget to switch to touchscreen input on the right side of the panel, otherwise, the default input will simulate a mouse pointer.

Related

Electron: Maximize Window on Start

I'm creating a electron app and am trying to allow it to open so that it is maximized on start. Is there a function of some kind that you put in the main.js to maximize the window? Thanks!
win.maximize() will maximize your window.
One caveat: even if you instantly call this function after creating the BrowserWindow you may still see the small window before maximizing. So hiding the window and showing it only after maximizing should do the trick.
const { BrowserWindow, app } = require("electron");
let win;
app
.whenReady()
.then(() => {
win = new BrowserWindow({
show: false,
});
win.maximize();
win.show();
})
.catch(console.error);

Electron: remove beforeunload event listeners

I have an electron-application that is used to show webpages which I have no control over.
The app is used so a different page can be shown every few seconds.
One of the pages shown attaches an 'beforeunload' listener like so
window.addEventListener('beforeunload', function(event) {
event.returnValue="test";
});
This causes electron to fail when loading a new url, so the switching does not work anymore.
This is a known issue: https://github.com/electron/electron/issues/9966
Even worse, is also prevents the whole application from being closed.
Is there anything that can be done from the main process that removes/disables the beforeunload listener, so the switching works again?
To test this, I have a fiddle that shows this behavior:
https://gist.github.com/9a8acc3bf5dface09d46aae36807f6f9
You can simply prevent this event:
const { BrowserWindow, dialog } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('will-prevent-unload', (event) => {
event.preventDefault()
})
See Electron docs for details

How to set mouse click as global shortcut in electron app

I want to trigger an action on double right-click of mouse when electron app is running in the background.
I read the documentation and seems like there are no globalshortcuts for mouse events.
Any other way to achieve this? perhaps some node module compatible with electron app?
Unfortunately, we can't achieve that yet.
As MarshallOfSound commented on this official issue
"globalShortcut intercepts the key combination globally and prevents any application from receiving those key events. If you blocked apps from receiving mouse button presses things would break everywhere very quickly 👍"
https://github.com/electron/electron/issues/13964
For macOS, I'm currently using Keyboard Maestro App.
I'm getting my mouse keys with this app and triggering a globalShortcut key combination register in my Electron App.
Maybe for Windows, AHK (auto hot keys)
I found this nice solution for HTML code
<script type = "text/javascript">
const {remote} = require('electron')
const {Menu, MenuItem} = remote
const menu = new Menu()
// Build menu one item at a time, unlike
menu.append(new MenuItem ({
label: 'MenuItem1',
click() {
console.log('item 1 clicked')
}
}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))
menu.append(new MenuItem ({
label: 'MenuItem3',
click() {
console.log('item 3 clicked')
}
}))
// Prevent default action of right click in chromium. Replace with our menu.
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
}, false)
</script>
Put this as first item in your HTML Body and it should work. At least it worked on my project
EDIT, cause I forgot it: Credits to google for answer on 6th entry

electron-packager - Generated exe stays in memory after closing the window

So I am using the electron-packager cli tool and everything is working EXCEPT the generated exe (only tried on Windows so far) doesn't unload from memory when I close the window (my one and only renderer process). I have to close it (kill the process) using task manager.
Is there something inside of electron I can call to ensure that this happens or is this a bug in electron-packager or what?
After thinking about this I considered that unloading the window doesn't automatically unload the node process and added the following 'closed' event to my mainWindow:
app.on('ready', function () {
mainWindow = new BrowserWindow({
width: 1024,
height: 768
});
// This 'closed' handler solves the problem
mainWindow.on('closed', function () {
mainWindow = null;
process.exit(0);
});
var menu = Menu.buildFromTemplate(menuTemplate);
mainWindow.setMenu(menu);
mainWindow.loadURL('file://' + __dirname + '/index.html');
});

Using console.log() in Electron app

How can I log data or messages to the console in my Electron app?
This really basic hello world opens the dev tools by default, by I am unable to use console.log('hi'). Is there an alternative for Electron?
main.js
var app = require('app');
var BrowserWindow = require('browser-window');
require('crash-reporter').start();
var mainWindow = null;
app.on('window-all-closed', function() {
// Mac OS X - close is done explicitly with Cmd + Q, not just closing windows
if (process.platform != 'darwin') {
app.quit();
}
});
app.on('ready', function(){
mainWindow = new BrowserWindow({ width: 800, height: 600});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.openDevTools();
mainWindow.on('closed', function(){
mainWindow = null;
});
});
console.log works, but where it logs to depends on whether you call it from the main process or the renderer process.
If you call it from the renderer process (i.e. JavaScript that is included from your index.html file) it will be logged to the dev tools window.
If you call it from the main process (i.e. in main.js) it will work the same way as it does in Node - it will log to the terminal window. If you're starting your Electron process from the Terminal using electron . you can see your console.log calls from the main process there.
You can also add an environment variable in windows:
ELECTRON_ENABLE_LOGGING=1
This will output console messages to your terminal.
There is another way of logging to the console from inside the renderer process. Given this is Electron, you can access Node's native modules. This includes the console module.
var nodeConsole = require('console');
var myConsole = new nodeConsole.Console(process.stdout, process.stderr);
myConsole.log('Hello World!');
When this code is run from inside the renderer process, you will get Hello World! in the terminal you ran Electron from.
See https://nodejs.org/api/console.html for further documentation on the console module.
Yet another possibility is accessing the main process console using remote.getGlobal(name):
const con = require('electron').remote.getGlobal('console')
con.log('This will be output to the main process console.')
Adding to M. Damian's answer, here's how I set it up so I could access the main process's console from any renderer.
In your main app, add:
const electron = require('electron');
const app = electron.app;
const console = require('console');
...
app.console = new console.Console(process.stdout, process.stderr);
In any renderer, you can add:
const remote = require('electron').remote;
const app = remote.app;
...
app.console.log('This will output to the main process console.');
process.stdout.write('your output to command prompt console or node js ')
You can use the npm package electron-log https://www.npmjs.com/package/electron-log
It will log your error, warn, info, verbose, debug, silly outputs in your native os log.
var log = require('electron-log');
log.info('Hello, log');
log.error('Damn it, an error');
Sorry to raise an old thread but this is the top result for "how to output console.log to terminal" (or similar searches.
For anyone looking to gain a bit more control over what is output to the terminal you can use webContents.on('console-message') like so:
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
console.log(message + " " +sourceId+" ("+line+")");
});
See:
webContents Documentation
webContents entry on BrowserWindow docs
This is a follow up to cscsandy5's answer for some addition information, info from here
process.stdout.write('your output to command prompt console or node js ')
This code works great for just outputting a simple debug message to the terminal window you launched the electron app from and is is what console.log is build on top of.
Here is an example snippet (based on tutorialspoint electon tutorial) of a jQuery script that will write hello to the terminal every time the button is pressed (warning: you need to add your own line breaks in the output strings!)
let $ = require('jquery')
var clicks = 0;
$(function() {
$('#countbtn').click(function() {
//output hello <<<<<<<<<<<<<<<<<<<<<<<
process.stdout.write('hello')
$('#click-counter').text(++clicks);
});
$('#click-counter').text(clicks);
});
This is what I use:
let mainWindow // main window reference, you should assign it below 'mainWindow = new BrowserWindow'
function log(...data) {
mainWindow.webContents.executeJavaScript("console.log('%cFROM MAIN', 'color: #800', '" + data + "');");
}
Example use (same as console.log):
log('Error', { msg: 'a common log message' })
log('hello')
Source: https://github.com/fuse-box/fuse-box-electron-seed/tree/master/src/main in the logger.js file, here you can see a real use case.
After some investigation, here my understanding:
Code
(1) main.js
const createPyProc = () => {
console.log('In createPyProc')
...
console.log('scriptStart=%s', scriptStart)
...
console.log('scriptOther=%s', scriptOther)
...
}
...
let mainWindow = null
const createWindow = () => {
mainWindow = new BrowserWindow(
{
width: 1024,
height: 768,
webPreferences: {
nodeIntegration: true,
}
}
)
mainWindow.loadURL(require('url').format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
mainWindow.webContents.openDevTools()
mainWindow.on('closed', () => {
mainWindow = null
})
}
...
Note: which use openDevTools to opened Electron Dev Tools
(2) render.js
const zerorpc = require("zerorpc")
...
console.log("clientStart %d server is ready", PORT_START)
...
})
(3) render.js is called by: index.html
<!DOCTYPE html>
<html>
...
<script>
require('./renderer.js')
</script>
</html>
console.log
Output Logic
two process and its console.log output:
main process = NodeJS process = here Electron UI process
-> console.log in main.js will output log to here
render process
-> console.log in render.js will output log to here
Screenshot Example
DEBUG=Development mode
run ./node_modules/.bin/electron .
Production=Release mode = the xxx.app pacakged by eletron-builder
run /path_to_your_packaged_mac_app/xxx.app/Contents/MacOS/yourBinaryExecutable
added export ELECTRON_ENABLE_LOGGING=true, render.js console.log ALSO output to main process terminal
console.log() will work fine for debugging. As the electron is built on top of browser, it has DevTools support you can use devtools for debugging purpose. However, there is a hysterical behaviour of console.log() method. When you call the console.log() from main process of electron app, it will output to the terminal window from where you just launched the app and when you call it from renderer process it will output to the DevTools console.
Everything Alex Warren wrote is true. Important here is how Electron is started. If you use the standard script in the package.json file it will not work. To make console.log() work replace the old script with this new one.
Old one:
"scripts": {
"start": "electron ."
}
New one:
"scripts": {
"start": ".\\node_modules\\electron\\dist\\electron.exe ."
}
Now all console.log() calls are displayed in the terminal as well.
With this You can use developer tools of main Browser window to see logs
function logEverywhere(s) {
if (_debug === true) {
console.log(s);
// mainWindow is main browser window of your app
if (mainWindow && mainWindow.webContents) {
mainWindow.webContents.executeJavaScript(`console.log("${s}")`);
}
}
}
Example logEverywhere('test')
will output // test in console panel of main browser window's developer tools
You may need enhance this method to accept multiple args (You can done it with spread operator by es6)
Well, this is 2019 and I cant believe no one mentioned this trick in all the answers above.
Ok, so, how about logging directly to the browser console directly from the main?
I provided my answer here: https://stackoverflow.com/a/58913251/8764808
Take a look.
A project I'm working on was using electron-react-boilerplate. That has electron-devtools-installer#2.4.4, which somehow via cross-unzip causes a process to crash with Error: Exited with code 9 .
Upgrading to electron-devtools-installer#3.1.1, as proposed in electron-react-boilerplate#v2.0.0 resolved it so my console.log, console.error, etc statements worked as expected.
for log purpose, i would recommend you to use the electron-log package

Resources