How can you get information about other apps running or in focus? - electron

My motivation: I'm writing an app to help with some quantified self / time tracking type things. I'd like to use electron to record information about which app I am currently using.
Is there a way to get information about other apps in Electron? Can you at least pull information about another app that currently has focus? For instance, if the user is browsing a webpage in Chrome, it would be great to know that A) they're using chrome and B) the title of the webpage they're viewing.
During my research I found this question:
Which app has the focus when a global shortcut is triggered
It looks like the author there is using the nodObjc library to get this information on OSX. In addition to any approaches others are using to solve this problem, I'm particularly curious if electron itself has any way of exposing this information without resorting to outside libraries.

In a limited way, yes, you can get some of this information using the electron's desktopCapturer.getSources() method.
This will not get every program running on the machine. This will only get whatever chromium deems to be a video capturable source. This generally equates to anything that is an active program that has a GUI window (e.g., on the task bar on windows).
desktopCapturer.getSources({
types: ['window', 'screen']
}, (error, sources) => {
if (error) throw error
for (let i = 0; i < sources.length; ++i) {
log(sources[i]);
}
});

No, Electron doesn't provide an API to obtain information about other apps. You'll need to access the native platform APIs directly to obtain that information. For example Tockler seems to do so via shell scripts, though personally I prefer accessing native APIs directly via native Node addons/modules or node-ffi-napi.

2022 answer
Andy Baird's answer is definitely the better native Electron approach though that syntax is outdated or incomplete. Here's a complete working code snippet, assumes running from the renderer using the remote module in a recent Electron version (13+):
require('#electron/remote').desktopCapturer.getSources({
types: ['window', 'screen']
}).then(sources => {
for (const thisSource of sources) {
console.log(thisSource.name);
}
});

The other answers here are for the rendering side - it might be helpful to do this in the main process:
const { desktopCapturer } = require('electron')
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
for (const source of sources) {
console.log("Window: ", source.id, source.name);
}
})

Related

Use ShareArrayBuffer from an electron app

We have an electron app which uses ShareArrayBuffer. It was written with a very old version of electron. When we updated the electron version in order to use SIMD instructions in WASM, it started showing an error saying ShareArrayBuffer is not defined. It seems it is due to the security update in Chromeum and ShareArrayBuffer is available iff Cross Origin Isolation is set.
Google shows some articiles explaining how to enable Cross Origin Isolation on web-pages, but I have not found any article that explains how to do that on an electron app. Does anyone have a pointer to the info or an idea to try?
Thank you,
It can be enabled by adding the following line in background.js
app.commandLine.appendSwitch('enable-features','SharedArrayBuffer')
Reference
As of December 2022, this is the only thing that worked for me:
browserWindow = new BrowserWindow({...});
// Enable SharedArrayBuffer
browserWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
details.responseHeaders['Cross-Origin-Opener-Policy'] = ['same-origin'];
details.responseHeaders['Cross-Origin-Embedder-Policy'] = ['require-corp'];
callback({ responseHeaders: details.responseHeaders });
});

obtain List of dart versions via http request (or similar)

I'm trying to build a cli app to show a list of dart versions and allow the user to select the one to install and then switch between them.
Note: there is a flutter tool (fvm) that can switch between flutter versions (and the embedded dart tools) but this tool is specifically for dart and needs versions as well as channels.
The fvm tool uses the following endpoint:
https://storage.googleapis.com/flutter_infra/releases/releases_linux.json
But I can't find an equivalent.
Is there any method of obtaining a list of versions for each of the dart channels.
I've found:
https://storage.googleapis.com/dart-archive/channels
but you need to know the full url as I can't find any endpoints that provide a list.
I'm hoping to avoid screen scraping.
You can see how the Dart Archive Page retrieves all the information and use their endpoints:
The endpoints returns in a format such as:
{
"kind": "storage#objects",
"prefixes": [
"channels/<stable|beta|dev>/release/1.11.0/",
...,
"channels/<stable|beta|dev>/release/2.9.3/",
"channels/<stable|beta|dev>/release/29803/", // You might need to filter out results such as this
...,
"channels/<stable|beta|dev>/release/latest/"
]
}
Note: The results are not ordered in any way
Url:
https://www.googleapis.com/storage/v1/b/dart-archive/o?delimiter=%2F&prefix=channels%2F<stable|beta|dev>%2Frelease%2F&alt=json
Replace <stable|beta|dev> with which version do you want the info of.
If you need to collect info about a version you can use:
https://storage.googleapis.com/dart-archive/channels/<stable|beta|dev>/release/< VERSION NUMBER | latest>/VERSION
which will return a json object like :
{
"date": "2020-11-11",
"version": "2.10.4",
"revision": "7c148d029de32590a8d0d332bf807d25929f080e"
}
The tags for the github archive for the SDK (https://github.com/dart-lang/sdk/tags) appear to have the releases tagged reasonably usefully. The downside is that it is weighing in at 1.3GB, and there's no easy way to get a workable shallow clone of that.

How to check if a key is pressed in Electron?

Is it possible to check if a key is pressed in Electron? I'm not asking to detect when a key is pressed.
When my app starts, I want to be able to hold shift while it starts, before the window loads, to open a special menu. An example of what I'm looking for is:
app.whenReady().then(() => {
const win = new BrowserWindow({ show: false })
win.loadFile("whatever.html")
// ***
const openSpecialMenu = keyboard.shiftKeyHeld
// ***
// do other stuff
window.show()
})
I don't know if there's an easy way to do this, but I believe you can do this using native APIs.
On Windows you can use GetKeyState.
On macOS you can use the function described in this answer.
You can then build a native node addon that allows you to use these native APIs in your Electron JavaScript code.
In fact, I found a node module for Windows that does what you need: https://github.com/Zysen/node-asynckeystate
You need to do additional work to support other operating systems.

Open file with default application from Vala?

What's the best way to open a file in the default application from Vala?
A bit like how xdg-open works.
I found some existing code in another application, but later on I also found this
GLib.AppInfo.launch_default_for_uri method.
A simple example:
var file = File.new_for_path (file_path);
if (file.query_exists ()) {
try {
AppInfo.launch_default_for_uri (file.get_uri (), null);
} catch (Error e) {
warning ("Unable to launch %s", file_path);
}
}
If you're using GTK, then you've also got Gtk.gtk_show_uri_on_window(), which uses the GLib stuff under the hood.
As far as I know there is only one implementation of the relevant freedesktop.org standards.
That is the reference implementation in xdg-utils:
https://www.freedesktop.org/wiki/Software/xdg-utils/
The tools are written in shell script, for example here is the source code for xdg-open:
https://cgit.freedesktop.org/xdg/xdg-utils/tree/scripts/xdg-open.in
So by far the easiest way is to just call the xdg-open script via Process.spawn_async and friends.
If you insist on using a library function you would have to implement a standard conforming library yourself.
Update:
There are quite a few libraries in various languages that implement some of the freedesktop.org standards, for example here is a list on GitHub:
https://github.com/topics/xdg
For example here is a similar tool to xdg-open written in D:
https://github.com/FreeSlave/mimeapps/blob/master/source/mimeapps.d
What I didn't find so far is a Vala / GLib or plain C library that could easily be used from a Vala application.
Update 2:
Actually it turns out there is something for that purpose in GLib (or more precisely in Gio):
https://valadoc.org/gio-2.0/GLib.AppInfo.launch_default_for_uri_async.html
https://developer.gnome.org/gio/stable/GAppInfo.html
So you should be able to use the GLib.AppInfo.launch_default_for_uri_async method.

Electron: how to close a portable app on pulling out the pendrive

I made a portable app with electron. It works fine. I have it saved in a pendrive, so I don't need to install it and copy into my hard disk to run it. Just executing the app from the pendrive I have it running in my desktop. But what I need, is implement a system that makes that if you pull out the pendrive the app automatically closes. I've been googling something similar and found many ways for using a pendrive as a master key. But that isn't exactly what I need. I don't want to shutdown the PC, I only need to close the app and remove it from memory. There is any way or nodejs library that can help me with that?
You can use node_usbspy module to watch the usb insertion/removal. This module supports only Windows.
If you receive an event with device_status as 0 then you could quit the app with app.quit()
Hope it helps you!
Note: I'm the author of node-usbspy.
I found a practical solution that could work on all platforms:
const basePath = app.getAppPath()
setInterval(() => {
const path = basePath.split('/')
const baseDir = path.slice(0, -1).join('/')
fs.writeFile(baseDir + '/portable.txt', '1', err => {
if(err) {
app.quit()
}
})
}, 1000)
The script above try to save a TXT file every second. If fs.writeFile returns an error, app.quit() is called closing the application.

Resources