Find out what application (window) is in focus in Java - java

I'd like to know how I can code a Java program that knows which Windows application is in focus. I can have many windows open but I want to know the one that's being used (like Google Chrome right now as I'm typing this).
I don't need to change anything in the window or application, just need to know its name.

As the others have already pointer out, there is no portable way to get this on all platforms. But to make things worse: There not even a consistent way on MS Windows. I will provide some code that will solve the problem for different platforms and will point out the limitations. Use at your own risk, the code may provide wrong results or not run at all because of security reasons. If it runs on your machine, it will not mean that it will run equally well on other machines.
The code uses JNA. During my experiments I had problems with different versions of JNA and the JNA platform library. It might be best to compile it yourself, so you have a consistent environment.
Windows
The answer provided by kichik was correct at its time but will not work with Windows 8 in all cases. The problem is, that it will not handle Metro apps correctly. Unfortunately there is currently no stable API to get the name of the currently running Metro app. I have inserted some hints in the code, but it's best to wait until Microsoft will provide you with an API.
On Windows you will also have problems with privileged apps and with the UAC dialog. So you will not always get a correct answer.
public interface Psapi extends StdCallLibrary {
Psapi INSTANCE = (Psapi) Native.loadLibrary("Psapi", Psapi.class);
WinDef.DWORD GetModuleBaseNameW(Pointer hProcess, Pointer hModule, byte[] lpBaseName, int nSize);
}
if (Platform.isWindows()) {
final int PROCESS_VM_READ=0x0010;
final int PROCESS_QUERY_INFORMATION=0x0400;
final User32 user32 = User32.INSTANCE;
final Kernel32 kernel32=Kernel32.INSTANCE;
final Psapi psapi = Psapi.INSTANCE;
WinDef.HWND windowHandle=user32.GetForegroundWindow();
IntByReference pid= new IntByReference();
user32.GetWindowThreadProcessId(windowHandle, pid);
WinNT.HANDLE processHandle=kernel32.OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, true, pid.getValue());
byte[] filename = new byte[512];
Psapi.INSTANCE.GetModuleBaseNameW(processHandle.getPointer(), Pointer.NULL, filename, filename.length);
String name=new String(filename);
System.out.println(name);
if (name.endsWith("wwahost.exe")) { // Metro App
// There is no stable API to get the current Metro app
// But you can guestimate the name form the current directory of the process
// To query this, see:
// http://stackoverflow.com/questions/16110936/read-other-process-current-directory-in-c-sharp
}
Linux / Unix / X11
With X11 we have three problems:
Because of network transparency, multiple windows from completely different machines might be mixed in the same X11. So neither name nor PID of the process belonging to a window might be make sense on the machine you are querying.
Most windows managers have mutliple desktops. On each desktop there can be a different application in the foreground
Tiling window managers (like XMonad) don't have the concept of a foreground window. They arrange all windows in a way, so each window is in the foreground at the same time.
On X11 it makes more sense to query for the window that currently has the focus.
public interface XLib extends StdCallLibrary {
XLib INSTANCE = (XLib) Native.loadLibrary("XLib", Psapi.class);
int XGetInputFocus(X11.Display display, X11.Window focus_return, Pointer revert_to_return);
}
if(Platform.isLinux()) { // Possibly most of the Unix systems will work here too, e.g. FreeBSD
final X11 x11 = X11.INSTANCE;
final XLib xlib= XLib.INSTANCE;
X11.Display display = x11.XOpenDisplay(null);
X11.Window window=new X11.Window();
xlib.XGetInputFocus(display, window,Pointer.NULL);
X11.XTextProperty name=new X11.XTextProperty();
x11.XGetWMName(display, window, name);
System.out.println(name.toString());
}
Mac OS X
Mac OS X does not focus on windows but on applications. So it makes sense to ask for the currently active application. Older versions of Mac OS X provide multiple desktops. Newer versions can have multiple fullscreen applications open at the same time. So you might not always get a correct answer.
if(Platform.isMac()) {
final String script="tell application \"System Events\"\n" +
"\tname of application processes whose frontmost is tru\n" +
"end";
ScriptEngine appleScript=new ScriptEngineManager().getEngineByName("AppleScript");
String result=(String)appleScript.eval(script);
System.out.println(result);
}
Conclusion
When I played around with this code, it worked in the most basic cases. But if you want this code to run reliable, you will have to put in a lot of polish. Decide for yourself if it is worth it.
To make the code complete, here is the import section I used:
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
import com.sun.jna.platform.unix.X11;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.StdCallLibrary;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
Of course you will have to rearrange the parts of the code. I used one big class with the interfaces at the beginning a and then the rest in one big main method.

I'm afraid there's no java api for that. JVM does not know anything about the windows it does not manage. You'll probably have to use JNI and call this function
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
MSDN link
PS. THere is a GetWindowText function that you might want to use if you need to grab the title of the window.
This post has JNI examples that might be helpful for you.

As Hovercraft Full Of Eels said, JNA is your best bet here. Unlike JNI, you won't have to compile any C code for it.
To get the process name:
Call GetForegroundWindow() to get the window handle
Call GetWindowThreadProcessId() to figure out which process owns it
Call OpenProcess() to get a handle to the process (with PROCESS_QUERY_INFORMATION | PROCESS_VM_READ)
Call GetModuleFileNameEx() to get the process name from the handle. You can also call GetModuleBaseName() for just the module name without the full path.
A full example is available in Getting active window information in Java.
C code can be found here.

Related

How to let run only one instance of application at a time?

I am working on a GUI application that uses JavaFX(not fxml) and exported as a JAR. For slow machine, impatient user click more than once on JAR, and multiple instances of application started.
I'm looking for a solution to let only one instance can be run at a time on a system and if the user clicks again while the application is running nothing happens. I think it's called singleton but don't know how to implement it.
You could try JUnique. It's an open source library doing exactly what you ask for. Import junique-1.0.4.jar to your project as a library. It's just 10kb file.
It's manual neatly describes how to implement it on a project. For a JavaFX application, implementation would look something like this:
Make sure to import these classes to your main
import it.sauronsoftware.junique.AlreadyLockedException;
import it.sauronsoftware.junique.JUnique;
public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId);
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
launch(args); // <-- This the your default JavaFX start sequence
}else{ //This else is optional. Just to free up memory if you're calling the program from a terminal.
System.exit(1);
}
}
One easy solution that I've used is, when you start the application, it creates a file (I named it .lock but you can call it whatever you want), unless the file already exists, in which case the application terminates its execution instead of creating the file.
You will need to bind your application with a resource. It can be a file, port etc.
You can change the code on startup to check if the file is locked. The below code will give you some idea
FileOutputStream foStream = new FileOutputStream("/tmp/testfile.txt");
FileChannel channel = fileOutputStream.getChannel();
FileLock lock = channel.lock();
If you'd properly package your JavaFX code as a real application instead of just throwing it into a jar, you might get that functionality for free and without all these hacks. If I package my JavaFX code on my Mac with the jpackage tool, the result will be a full featured macOS application. That means that when I double-click its icon somewhere several times, only one instance of the application will be started. This is the default behaviour on Macs and properly packaged JavaFX applications just stick to that rule too. I can't say however what the behaviour on Windows or Linux is because I currently don't have such a box running. Maybe someone who knows can add this as a comment.

Get current remote or game controller

How can I get the current input device in my application in java? I want to know is the remote or the game controller, that is being used.
It is an android application that I want to run on Amazon FireTV. Unlike the Amazon Kindle there is no touchscreen but you can use a remote or a game controller. I would like to know if it is possible to detect what kind of input device the user is currently using.
The code I have until now is a standard Cordova Application code, but when I know how to detect the current input device I would make a plugin to pass the value to the javascript code. That is not the problem.
As mentioned in the comments you should provide steps you have already taken or code you have already written to address this functionality as that will help us tweak the most appropriate answer.
As a general rule, you can look at the official docs to identify controllers on Fire TV.
https://developer.amazon.com/public/solutions/devices/fire-tv/docs/identifying-controllers
Basically, you need to write the identification code in your Cordova plugin as follows:
int hasFlags = InputDevice.SOURCE_GAMEPAD | InputDevice.SOURCE_JOYSTICK;
boolean isGamepad = inputDevice.getSources() & hasFlags == hasFlags;
This will allow you to find out if it's a gamepad. For a Fire TV remote the code you need is:
int hasFlags = InputDevice.SOURCE_DPAD;
bool isRemote = (inputDevice.getSources() & hasFlags == hasFlags)
&& inputDevice.getKeyboardType() == InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC;
The InputDevice class is available on the Android developer site:
http://developer.android.com/reference/android/view/InputDevice.html
So you basically need to import that in your plugin class to ensure the above code works fine.
import android.view.InputDevice;

How can I prevent the Charm bar from showing up in my Java application?

I've got a Java swing program that runs in full screen mode. It's effectively a kiosk program in that I want it to lock out everything else while it's running. This is running on a Windows 8.1 tablet, so of course the tablet is touchscreen, and therefore if you do an "edge swipe" (drag your finger from the right) the charms bar pops up and you can get to the Start screen from there. Is there some way to disable this from happening in Java? (Or is there some third-party solution not involving Java that can work in tandem to achieve the same result?)
You can disable edge gestures while your app is active and full screen by setting the System.EdgeGesture.DisableTouchWhenFullScreen property on the window.
I don't know if Java provides a direct way to set this (probably not), but you should be able to set this from a JNI.
Here's a C++ snippet from the DisableTouchWhenFullScreen docs:
HRESULT SetTouchDisableProperty(HWND hwnd, BOOL fDisableTouch)
{
IPropertyStore* pPropStore;
HRESULT hrReturnValue = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pPropStore));
if (SUCCEEDED(hrReturnValue))
{
PROPVARIANT var;
var.vt = VT_BOOL;
var.boolVal = fDisableTouch ? VARIANT_TRUE : VARIANT_FALSE;
hrReturnValue = pPropStore->SetValue(PKEY_EdgeGesture_DisableTouchWhenFullscreen, var);
pPropStore->Release();
}
return hrReturnValue;
}
What I ended up doing was to write a batch script that kills explorer.exe and then re-spawns it after the app exits, based on this answer on Super User.

Converting JFrame code to JApplet [duplicate]

I have a JFrame application working nicely. However now I'd like to run it on the web as an Applet. This is what I've done:
import MyPackage.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class MyName extends JApplet
{
public void init() {
setSize(600,450);
new MyName()
}
public MyName() {
JShellFrame frame = new JShellFrame(true, null, null);
frame.setVisible(true);
}
}
How can I make an html file to run this applet? Also, I have an external jar file that the applet will need. Does the applet not need a main method?
Check out Getting Started With Applets. It covers relevant methods and life cycle. It mentions main method as well:
Unlike Java applications, applets do not need to implement a main
method.
Deployment section covers HTML file details. For dependency jars you can specify more than one jar in archive attribute of applet tag.
However now I'd like to run it on the web..
Then drop this nonsense and launch the frame from a link using Java Web Start. I say 'nonsense' for two reasons.
JWS has existed since Java 1.2, & has been discussed in these forums several times in the last few days in regard to applets. Seems you are not doing much research.
Of the 'gargantuan' 2 lines of applet code code shown above, one of them is ill-advised and the other is either pointless or would risk creating a stack overflow error (could not be bothered trying it to find out which).
here's some html that will work:
<applet archive = "appName.jar" width = 900 height = 506 code = "main.class"/>
You can change the width and height according to the size your app needs. Also make sure to put the url as a path to the jar.

How to give focus to default program of shell-opened file, from Java?

From within Java, I am opening an Excel file with the default file handler (MS Excel, in this case :-) ) using the method described in this stackoverflow question:
Desktop dt = Desktop.getDesktop();
dt.open(new File(filename));
However, the Excel program doesn't get the focus. Is there any easy way to do so?
Edit: There is a related stackoverflow question for C#, but I didn't find any similar Java method.
Edit 2: I've did some simple tests, and discovered that Excel starts and gets the focus whenever no instance of Excel is running. When Excel is already open en NOT minimized, the application doesn't get the focus. If instead the Excel Windows was minimized, the above code will trigger a maximization of the window and Excel getting the focus (or vice versa :-) ).
If you only care about Windows (implied in the question), you can change the way you invoke Excel: use "cmd start...".
I have been using this piece of code to launch Windows applications for some time now. Works every time. It relies on the file association in Windows to find the application. The launched application becomes the focused window on the desktop.
In your case, Excel should be associated with .xls, .csv and other typical extensions. If it is, Windows will launch Excel, passing your file to it.
Usage:
MyUtilClass.startApplication( "c:\\mydir\\myfile.csv", "my window title" );
file is the full path to the input file for Excel and title is the window title (the application may or may not take it - Excel changes the window title).
public static void startApplication( String file, String title )
{
try
{
Runtime.getRuntime().exec( new String[] { "cmd", "/c", "start", title, file } );
}
catch( Exception e )
{
System.out.println( e.getMessage() );
}
}
From a scala-program, which runs in the JVM too, I can open an application, and that get's the focus by default. (Tested with xUbuntu, which is a kind of Linux).
import java.awt.Desktop
val dt = Desktop.getDesktop ();
dt.open (new java.io.File ("euler166.svg"));
I can't say, whether this is specific for Linux, or maybe something else - however starting Inkscape in my example, excel in yours, may take a few seconds, while the user impatiently clicks in the javaprogram again, thereby claiming the cursor back. Did you check for that?
You could then change to the last application, at least on Linux and Windows with ALT-Tab aka Meta-Tab (again shown in scala code, which you can easily transform to javacode, I'm sure):
import java.awt.Robot
import java.awt.event._
val rob = new Robot ()
rob.keyPress (KeyEvent.VK_META)
rob.keyPress (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_TAB)
rob.keyRelease (KeyEvent.VK_META)
but unfortunately the unknown source off more trouble, also known as user, might do nothing, so switching would be the false thing to do. Maybe with a thread, which checks for a certain amount of time, whether the java-program has the focus, but it keeps a form of roulette, in an interactional environment, because the user may have a fast or slow machine, or change to a third application meanwhile, and so on. Maybe a hint before triggering the new app is the best you can do?

Categories

Resources