Node Webkit Detect Program Focus Event - focus

Is it possible to detect when a user focuses on the program, like doing an alt-tab to the program?
I do get the window.onfocus when the window is being selected, but when I have the window minimized, then I don't receive anything.

You can try with the NW.js Window API
// Load library
var gui = require('nw.gui');
// Reference to window and tray
var win = gui.Window.get();
win.on('focus', function() {
console.log('Window is focused');
});

Related

How to find if electron app is in foreground?

I have a requirement where I want to perform an action inside the electron app only when it is in foreground.
It is an electron-react application. On mounting of a component, I want to schedule a periodic task which only runs when the app is in focus or is being used by the user. And pause the task when the app goes in background.
How can we detect the Electron app being in foreground?
You can use the isFocused method from BrowserWindow. To get your own BrowserWindow, you can do this :
remote.BrowserWindow.getAllWindows();
This will return all your app's windows. So to get the first / primary window, you could deconstruct the array like this :
const [yourBrowserWindow] = remote.BrowserWindow.getAllWindows();
console.log(yourBrowserWindow.isFocused());
You can use the focus / blur events on your BrowserWindow to be notified when the app is focused / unfocused.
mainWindow = new BrowserWindow({})
mainWindow.on('focus', () => {
console.log('window got focus')
})
mainWindow.on('blur', () => {
console.log('window blur')
})
You may want to update the component's state within these event handlers or use any other method to keep track of the current focus status.
This assumes that you have a single application window. If you have multiple, you'll need to extend the check to cover all of your windows.

Adobe Air Application - Not in background and not in Foreground - iPhone

I have an adobe air application - AS3 for iOs and Android.
Whenever the user clicks the home button, and thus the application is now in the background, the application automatically stops, which is the expected behavior. Now, if the user is in the application, and he double clicks his home button, showing all the multiple windows, the application continues running, which is not what i want. How can i access that state ( Not Background, not foreground )? If i can access it, i would then put my pausing code into that state, but how can i access that particular state?
When the user clicks the home button the app is moved to the background and suspended. The app isn't closed. The OS can close the app to free memory. If your app is a memory hog you'll see this happening.
You use events dispatched by the NativeApplication object. Below is example code to listen and handle these events.
import flash.events.Event;
import flash.desktop.NativeApplication;
import flash.desktop.SystemIdleMode;
// create listeners to NativeApplication
private var naApplication: NativeApplication;
naApplication = NativeApplication.nativeApplication;
naApplication.addEventListener(Event.ACTIVATE, eActivate);
naApplication.addEventListener(Event.DEACTIVATE, eDeactivate);
naApplication.addEventListener(Event.EXITING, eExiting);
private function eActivate(e: Event): void {
// app has opened or resumed
application.systemIdleMode = SystemIdleMode.KEEP_AWAKE;
}
private function eDeactivate(e: Event): void {
// app is going to be moved to background
application.systemIdleMode = SystemIdleMode.NORMAL;
}
private function eExiting(e: Event): void {
// app is going to be closed by user or by the OS (usually to free up memory)
// do whatever exit code here then remove all listeners (to be clean don't rely on OS to close them)
application.removeEventListener(Event.ACTIVATE, eActivate);
application.removeEventListener(Event.DEACTIVATE, eDeactivate);
application.removeEventListener(Event.EXITING, eExiting);
application.systemIdleMode = SystemIdleMode.NORMAL;
removeEventListener(Event.ENTER_FRAME, eMainTimer);
}
The systemIdleMode and ENTER_FRAME are just examples of typical code. Let me know of any questions.

jQuery UI Focus Issue

I am getting Issue
unable to get property'_focusTabbable'of undefined or null reference
I am using Jquery-ui-1.10.2.custom.js
Here I am getting issue in
if ( !$.ui.dialog.overlayInstances ) {
// Prevent use of anchors and inputs.
// We use a delay in case the overlay is created from an
// event that we're going to be cancelling. (#2804)
this._delay(function() {
// Handle .dialog().dialog("close") (#4065)
if ( $.ui.dialog.overlayInstances ) {
this.document.bind( "focusin.dialog", function( event ) {
if ( !that._allowInteraction( event ) ) {
event.preventDefault();
**$(".ui-dialog:visible:last .ui-dialog-content")
.data( widgetFullName )._focusTabbable();**
}
});
}
});
}
This bug arises when you open a dialog and then, in an action button of this dialog, call a method that opens a second dialog. When you attempt to close the second dialog, the bug appears.
To prevent this from happening, close the first dialog immediately, and then call the second dialog.
$('#dialog1').dialog({
buttons: {
'No': function () {
$(this).dialog('close')
},
'Yes': function () {
// This works
$(this).dialog('close');
// Open second dialog
OpenSecondDialog()
// This doesn't work. A bug will arise when attempting to close the second dialog
$(this).dialog('close');
}
}
});
I'm opening one dialog and then another to confirm changes which were done in the first dialog. When confirming it doesn't close the first dialog which was opened. So I'm just destroying everything to get rid of the focus issue.
$(".ui-dialog-content").dialog('destroy');
I just put this one in the confirm function of the last dialog so it destroys all my dialogs (since they have the same class).
Just for future reference (and in case anyone else experiences this problem), I got the same error in jQuery UI 1.10.3 when re-opening a dialog after partial postbacks in asp.net. I found out that this was due to a variable $.ui.dialog.overlayInstances that is supposed to evaluate to 1 before the dialog is closed. Since every time the dialog is opened the variable is increased by 1, when the user pressed the close button my value often evaluated to 2 or more. My solution was to reset $.ui.dialog.overlayInstances to 1 every time I opened the dialog. So:
$("#myDiv").dialog("open");
$.ui.dialog.overlayInstances = 1;
I was working jquery-ui-1.12.1 and encountered the same error and as Emyr pointed out this bug has been fixed.
My first workaround used George Beiers approach. Close dialog1 before creating dialog2, then I would restore dialog1 after closing dialog2. The result didn't look so well but it cleared the error in every browser except Internet Explorer.
Turns out there was a function that was attempting to closed my dialog1(already closed) before closing dialog2. Once I reordered the code I was able to keep dialog1 open while I displayed dialog2.
My suggestion if you are having trouble fixing this issue is to add a console log message on the beforeClose and open events to keep an eye for odd behavior.
I remember that error.
For me was
I tried to open a modal by code, then I opened other modal also by code...
They opened well... but if tried again, I received that error.
I had to close the first modal before open a new one.

Closing application and notifying renderer process

I have an Electron application that needs to save some data when it's closed by the user (e.g. just after the user clicked on the "Close" button).
The data is available at the renderer process, so it should be notified before the application dies.
The Electron API for Browser Window mentions a close method, but it seems this is done by the main process, not the renderer one (if I'm not mistaken).
I tried using WebContents.send from the main process to notify the renderer process, but it seems that, because the message is asynchronous, the application is closed before the renderer process has the time to actually perform the operations.
You can just use the normal unload or beforeunload events in the renderer process:
window.addEventListener('unload', function(event) {
// store data etc.
})
So far, the simplest solution that worked for me consists in doing the following:
On the main process, the BrowserWindow listens on the close event, and when it happens, it sends a message via webContents to the renderer process. It also prevents the application from being immediately closed by calling event.preventDefault();
The renderer process is always listening on IPC messages from the main process, then when it receives the close event notification, it saves its data, then sends the main process an IPC message (e.g. closed);
The main process has previously set a hook to listen to the renderer IPC messages (ipcMain.on), so when the closed message arrives, it finally closes the program (e.g. via app.quit()).
Note that, if I understood it correctly, calling app.quit() sends another close event to the BrowserWindow, so it will loop unless you prevent it somehow. I used a dirty hack (quit the second time the close event is called, without calling event.preventDefault()), but a better solution must exist.
On the Main process:
const ipc = require('electron').ipcMain;
let status = 0;
mainWindow.on('close', function (e) {
if (status == 0) {
if (mainWindow) {
e.preventDefault();
mainWindow.webContents.send('app-close');
}
}
})
ipc.on('closed', _ => {
status = 1;
mainWindow = null;
if (process.platform !== 'darwin') {
app.quit();
}
})
On the renderer process:
const electron = require('electron');
const ipc = electron.ipcRenderer;
ipc.on('app-close', _ => {
//do something here...
ipc.send('closed');
});

Dart TouchEvent.supported during emulation

TouchEvent.supported attempts to create a TouchEvent to determine touch support. This works for actual touch devices, however, it does not help when using Chromium DevTools: “Emulate Touch Screen“. Chromium does expose functions Touch() and TouchList() on the window object. I added a check for context['Touch'] that now shows supportsTouchEvent: true. It is still not an indicator of whether “Emulate Touch Screen” is active. Any suggestions appreciated!
//bool get supportsTouchEvents =>TouchEvent.supported;
bool get supportsTouchEvents {
bool bIsTouchSupported = TouchEvent.supported;
if (bIsTouchSupported == false) {
//Get the browser's native window and check for Touch function
JsObject nativeTouch = context['Touch'];
bIsTouchSupported = (nativeTouch is JsObject);
//Check Chromium DevTools "Emulate Touch Screen"
}
return bIsTouchSupported;
}
Update-1: The additional check for context['Touch'] function does provide more insight that touch handling is possible. But it's a false-positive due to "Emulation" is not active until the DevTools window is opened. As a bloated alternative: If nativeTouch install both mouse and touch streamcontrollers/handlers.
This is a know bug ...............................
https://code.google.com/p/dart/issues/detail?id=16669

Resources