How to hook to desktop (leave in background) with electron? - javascript

so I am working on a small feature. Basically, it adds a border to the desktop. So far, I got the design and everything down, but the two windows (two monitors) layer over everything else. So I can’t click anything on my computer because the borders (which have a transparent background) are over everything.
Example:
https://user-images.githubusercontent.com/43588940/46045103-819c4480-c0d1-11e8-92ce-6c36b4ec6cc9.png
As you can see, the borders work but I can’t click anything on my desktop because it is blocking it.
So my question is, how can I link these borders to the desktop? Sort of like a desktop gadget. I just want it to stay in the background, so it isnt blocking all the computer functions.
Also, I can't click through the border because it is a transparent window and electron doesnt support clicking through transparent windows (feelsbadman). So I'm kinda screwed i just want borders on my desktop with this lol
My code:
const electron = require('electron')
const { app, BrowserWindow, globalShortcut } = require('electron')
let win
function runGouge() {
```
let displays = electron.screen.getAllDisplays();
let externalDisplay = displays.find((display) => {
return display.bounds.x !== 0 || display.bounds.y !== 0
})
win = new BrowserWindow({
name: "Gouge4 ",
width: 400,
frame: false,
toolbar: false,
transparent: true,
show: false,
parent: "explorer.exe",
x: externalDisplay.bounds.x + 50,
y: externalDisplay.bounds.y + 50
})
win.setMenu(null);
//win.webContents.openDevTools();
win.maximize();
win.show();
win.loadFile('index.html');
win.setSkipTaskbar(true);
win.showInactive();
win.center();
win2 = new BrowserWindow({
name: "Gouge2",
frame: false,
toolbar: false,
transparent: true,
show: false,
})
win2.setMenu(null);
//win2.webContents.openDevTools();
win2.setIgnoreMouseEvents;
win2.maximize();
win2.show();
win2.loadFile('index_blank.html');
win2.setSkipTaskbar(true);
win2.showInactive();
win2.center();
```
}
app.on('ready', runGouge);

Why not just use HTML to generate the border? You can create 3 divs, position one to the bottom (position: absolute; bottom: 0), float one to the left (float: left) & one to the right (float: right).
The first div will have background-color: purple, and the other two will have a gradient background-image: linear-gradient(rgba(0, 0, 0, 0), purple)
This will ensure that the bounding boxes of all of these elements will be confined and won't interfere with your site's functionality. To overlay them all you just set the z-index to be higher than all the other elements in your site.

You can disable mouse events on your BrowserWindow with setIgnoreMouseEvents. That means every event will be forwarded to the window behind that - won't block.
For example:
const {app, BrowserWindow} = require('electron')
const path = require('path')
app.once('ready', () => {
let win = new BrowserWindow({
frame: false,
focusable: false,
transparent: true,
alwaysOnTop: true,
fullscreen: true
})
win.loadURL(path.join(__dirname, 'background-frame.html'))
win.setIgnoreMouseEvents(true)
})
I've chosen properties for BrowserWindow which I think fit a window you described but it's up to you

Related

Show refresh screen without new window

Hi I use following code to show splash screen , before page is loaded
loadingx = new BrowserWindow({ width: 920, height: 1000, transparent: true, frame: false, alwaysOnTop: true });
loadingx.loadURL(`file://${__dirname}/splash.html`);
mainWindow.once("ready-to-show", () => {
loadingx.hide();
mainWindow.show();
});
mainWindow.webContents.on("did-start-loading", () => {
loadingx.show();
});
It was working fine , until i tried it in full screen mode in MAC , this small loading screen is opening into new tabs.
So is there anyway to show splash screen , without creating new window. thanks.Right now I am using onreadystatechange responses to show custom loading icon, but its not good as above method.

How can I resize a window towards the left when the Electron app is docked on the right side of the screen?

I'm creating an Electron app where we want a nav looking toolbar to be docked on the right side of the screen. It needs to be on the right side because most of our users are on Windows and docking it on the left would mean it overlaps lots of icons and it would be covered by the start menu.
When the user clicks an icon, I need the window to open/resize towards the left.
On App launch I create a new window
mainWindow = new BrowserWindow({
width: 800,
height: 600,
center: true,
backgroundColor: '#18A4FC'
})
Then after the user is authenticated, I use the ipcRender to send a success message to the main.js file. Currently this "docks" the window on the right side of the screen using the setBounds method and the screen sizes.
ipcMain.on('login-success', () => {
let display = electron.screen.getPrimaryDisplay()
const { width, height } = display.bounds
mainWindow.setBounds({
x: width - 40,
y: 0,
width: 40,
height: height
})
})
Then, when the user clicks an icon, I use setSize to "open" the dock. This means I change the width of the window from 40px to 480px. But it opens towards the right, offscreen. I need it to open towards the left.
ipcMain.on('resize-open', () => {
let display = electron.screen.getPrimaryDisplay()
const { height } = display.bounds
mainWindow.setSize(480, height)
})
Any ideas how to do this? I understand that the width,height is being set from top left corner being 0,0. Any way to reset this?
I ended up using setBounds, but instead moving it to the left the amount that I need for it to be open.
let display = electron.screen.getPrimaryDisplay()
const { width, height } = display.bounds
mainWindow.setBounds({
x: width - 320 ,
y: height,
width: 320,
height: height
})
})```
Maybe you could try something like:
mainWindow.setBounds({
x: 0,
y: 0,
width: 480,
height: height
})
Instead of:
mainWindow.setSize(480, height)
Because the setBounds function resets the window position (to 0,0 in this case) as well as set the width and height.

Small gap in very right side of window (window oversize)

i just started to make a new app by electron and find out after adding a new feature in my app, a very hard to notice white(or maybe transparent) gap added in very right side of the window.
More explanation: I made an application that fetch something from server and after some manipulation, will display them in main window. The application just has 1 window (its quite simple app) and this is configuration for window that i added into main js "Before" gap shows up:
mainWindow = new BrowserWindow({
show : false,
width : 820,
height : 520,
frame : false,
resizable : false,
title : "blah blah blah"
})
After that i decided to expand the app and cache last location of the window before user try to close window so in next time that user will open the app, the window will at the same prev place. So i added some extra function to catch window "x" and "y" and save them into a "json" file in "appData". I changed window config to this one:
mainWindow = new BrowserWindow({
show : false,
width : 820,
height : 520,
frame : false,
resizable : false,
title : "blah blah blah",
x : {get x from storage},//this is pseudo
y : {get y from storage}//this is pseudo
})
Now a small gap appears in right side as shown in pictures below. More explanation in pictures caption.
HTML:
<body>
<div class="hello-rob">
<div class="nav"></div>
</div>
</body>
CSS:
body,
html {
position: relative;
width: 820px;
font-weight: normal;
-webkit-font-smoothing: antialiased;
height: 100%;
overflow: hidden;
-webkit-user-select: none;
}
caption: Css width set to "820px" same as window "width" in main. js, as you can see there is almost "2-3px" white gap (i marked with a circle)
caption: If i comment the css width, then the window will expand to its real width that is "822.4px"
caption: When i comment "x" and "y" in main.js and css "width" presence, every thing seems fine.
P.S: i don't think this issue its just about "x" and "y" that set in main.js and regardless of that the main problem is:
Why and how the window is bigger than what we set for it in main.js and in css?
electron v1.7.11
Windows 10 64bit
Please note:
This is not a "permanent solution", this is just a temporary hotfix before electron team diagnose what is the main cause of this behavior by electron.js.
Thanks to #mplungjan and #Mike to reminding me to read documentation once again
I tried to watch/trace "window size" in every moment so that i can find out inside the electron core "window size" is inaccurate or no, something in renderer.js is involve?!
Based on this results (from main.js), its obvious changes happen in main.js part.
This is main.js console (when extra gap is evident):
[ 823, 522 ]// console.log(mainWindow.getSize());
[ 822, 521 ]// console.log(mainWindow.getContentSize());
{ x: 680, y: 101, width: 823, height: 522 }// console.log(mainWindow.getBounds());
From the results you can see electron uses setSize, getSize to demonstrate window size and obviously its not accurate because the window's size should be "820px" * "520px".
How to fix this: (please consider big part of codes below are not new, new tricky-lines has a comment)
function createWindow(){
mainWindow = new BrowserWindow({
show : false,
width : 820,
height : 520,
frame : false,
resizable : false,
title : "blah blah blah",
x : {get x from storage},//this is pseudo
y : {get y from storage}//this is pseudo
minWidth: 820,// new
maxWidth: 820,// new
minHeight: 520,// new
maxHeight: 520// new
})
// in this function i called console.log()
mainWindow.once('ready-to-show', () => {
mainWindow.show();
mainWindow.setSize(820,520);// new (i didn't checked but maybe before `mainWindow.show();` is better to place this line of code)
})
}
app.on('ready', () => {
createWindow()
})
Another test to check the effect of changes:
[ 820, 520 ]// console.log(mainWindow.getSize());
[ 820, 520 ]// console.log(mainWindow.getContentSize());
{ x: 680, y: 100, width: 820, height: 520 }// console.log(mainWindow.getBounds());
And the gap no longer exists.
P.S: personally i don't like this kind of solutions, so if any one else was able to represent a better solution i'll accept it as an answer.

How do I move a frameless window in Electron without using -webkit-app-region

I've been trying to move a frameless window on false but now I want to move the whole window just by dragging one element (the title bar), I've tried -webkit-app-region: drag; but it doesn't seem to work, I've also tried https://www.npmjs.com/package/electron-drag but it does't work either.
Since your windows are frameless you can use the property -webkit-app-region which is valid even though your IDE says it's not. You just should forbid the text selection and drag on buttons inside of your title bar too out of UX concerns.
.titlebar {
-webkit-user-select: none;
-webkit-app-region: drag;
}
.titlebar-button {
-webkit-app-region: no-drag;
}
The API documentation mentions this too https://github.com/electron/electron/blob/master/docs/api/frameless-window.md#draggable-region
First create your app window with the frame option set to false on your main.js file:
mainWindow = new BrowserWindow({
...
frame: false
})
Then in your renderer.js file create an HTML element (Ex. ) with the -webkit-app-region propperty set to drag.
var windowTopBar = document.createElement('div')
windowTopBar.style.width = "100%"
windowTopBar.style.height = "32px"
windowTopBar.style.backgroundColor = "#000"
windowTopBar.style.position = "absolute"
windowTopBar.style.top = windowTopBar.style.left = 0
windowTopBar.style.webkitAppRegion = "drag"
document.body.appendChild(windowTopBar)
I had the same problem and after opening the Developer Tools Window (Ctrl+Shift+I) I noticed that inline code was being blocked by a Content Security Policy.
The solution was to move css into an external file
index.html
<link rel="stylesheet" type="text/css" href="style.css"/>
style.css
.draggable {
-webkit-user-select: none;
user-select: none;
-webkit-app-region: drag;
}
now anything with the draggable class is draggable and prevents the text from being selected
I had the same problem. I realized that you must have property focusable of BrowserWindow to false.
Example:
let auxWindow = new BrowserWindow({
frame: false,
transparent: false,
alwaysOnTop: true,
focusable: false, //THIS IS THE KEY
closable: true,
fullscreenable: false,
maximizable: false,
resizable: false,
webPreferences: {
preload: join(app.getAppPath(), 'build', 'src', 'preload.js'),
},
parent: mainWindow
});
Then, in your aux window, you only need to put a button with class="draggable":
<img src="move-outline.svg" width="15" height="15" alt="move" class="draggable">
And set in your CSS -webkit-app-region: drag;:
.draggable {
-webkit-app-region: drag;
}
I was looking for something similar for my project, even though you should be good with webkit region for your use but It's not the answer you demanded, and If someone facing the issue below they can also use the code.
Im using frameless window, making the whole window element as draggable makes the program to ignore click events.
Worry Not, Im here to you a lot of "mehnat".
Rendering/front end side:
//elem = the element you want to use to drag the whole window.
//In my case, elem was the element covering the whole window. (100vh + 100 vw)
//longmousedown variable tells us if mouse been clicked for a long time, 200ms in my case.
//When longmousedown is true, I use this to ignore click event functions using if/else. (It feels better if click functions doesn't do anything while you trying to drag your window)
let longmousedowntimout;
let longmousedown = false;
let is_mousedownvid = false;
let earlymouseX,earlymouseY;
elem.addEventListener("mousedown", function(event){
longmousedowntimout = setTimeout(function(){longmousedown = true},200)
is_mousedownvid = true;
earlymouseX = event.screenX;
earlymouseY = event.screenY;
});
elem.addEventListener("mouseup", function(event){
clearTimeout(longmousedowntimout)
is_mousedownvid = false;
ipcRenderer.invoke('settlenewpos', {x:(event.screenX - earlymouseX),y:(event.screenY - earlymouseY)})
});
elem.addEventListener("mousemove", dragMouse);
elem.addEventListener("mouseleave", ()=>{
if(is_mousedownvid){
is_mousedownvid = false;
ipcRenderer.send("settlemergency")
}
});
function dragMouse(e){
if(is_mousedownvid){
e = e || window.event;
e.preventDefault();
ipcRenderer.invoke('setnewpos', {x:(e.screenX - earlymouseX),y:(e.screenY - earlymouseY)})
}}
Main.js side (the side where electron runs) :
(don't copy paste the below, read it once)
let earlyX, earlyY;
let newX, newY;
const createWindow = () => {
let display = screen.getPrimaryDisplay();
let widtho = display.bounds.width;
let heighto = display.bounds.height;
let wind_height = 330;
let wind_width = 0;
let minusX = 608;
let minusY = 376;
const mainWindow = new BrowserWindow({
icon: `${__dirname}/resources/icons/yt logo hd 2.png`,
show: false,
height: wind_height,
frame:false,
minimizable: true,
skipTaskbar:true,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration:true,
contextIsolation: false,
},
});
earlyX = widtho - minusX;
earlyY = heighto - minusY;
mainWindow.setBounds({
width: mainWindow.getSize()[0],
height: mainWindow.getSize()[1],
x: earlyX,
y: earlyY
});
mainWindow.setAspectRatio(16/9);
ipcMain.handle('setnewpos', async (event, someArgument) => {
mainWindow.setBounds({
width: wind_width || mainWindow.getSize()[0],
height: wind_height,
x: earlyX+someArgument.x,
y: earlyY+someArgument.y
});
newX = earlyX+someArgument.x;
newY = earlyY+someArgument.y;
if(wind_width == 0) wind_width = Math.ceil(parseInt(wind_height)*16/9)
})
ipcMain.handle('settlenewpos', async (event, someArgument) => {
earlyX=earlyX+someArgument.x;
earlyY=earlyY+someArgument.y;
newX = earlyX;
newY = earlyY;
})
ipcMain.on('settlemergency', () => {
earlyX = newX;
earlyY= newY;
})
mainWindow.on("will-resize",(event, newBounds)=>{
earlyX = newBounds.x;
earlyY = newBounds.y;
newX = earlyX;
newY = earlyY;
wind_height= newBounds.height
wind_width = newBounds.width
})
}

Titanium.Media.showCamera with overlay, pass through events

I am writing an iOS application that utilizes the camera. I want an image (and ultimately a control element or two) overlayed over the camera picture.
This already works. However the overlay prevents the default control elements for Flash, HDR and camera selection from receiving touch events.
Below is my code. Is there a way to make myOverlay pass through or ignore events?
var overlayImage = Titanium.UI.createImageView({
width: 100,
height: 100,
backgroundImage: 'img/picture.png'
});
var myOverlay = Titanium.UI.createView();
myOverlay.add(overlayImage);
Titanium.Media.showCamera({
success: successMethod,
error: errorMethod,
cancel: function(e) {},
overlay: myOverlay,
saveToPhotoGallery: true,
allowEditing: false,
mediaTypes: ['public.image']
});
You can try var myOverlay = Titanium.UI.createView({touchEnabled: false}); and it should pass events according to the Appcelerator docs.

Categories