Get current active window's title in Java
Asked Answered
O

6

13

I am trying to write a Java program that logs what application I'm using every 5 seconds (this is a time tracker app). I need some way to find out what the current active window is. I found KeyboardFocusManager.getGlobalActiveWindow() but I can't get it to work right. A cross platform solution is preferable, but if one doesn't exist, then I'm developing for linux with X.Org. Thanks.

Oreopithecus answered 30/8, 2009 at 16:36 Comment(1)
Are you using a windowing system like KDE or Gnome? It may be necessary to know that since this kind of task usually needs to be done with system-specific code.Heavyweight
L
7

I'm quite certain that you'll find there's no way to enumerate the active windows in pure Java (I've looked pretty hard before), so you'll need to code for the platforms you want to target.

  • On Mac OS X, you can launch an AppleScript using "osascript".

  • On X11, you can use xwininfo.

  • On Windows, you can probably launch some VBScript (e.g. this link looks promising).

If you're using SWT, you may be able to find some undocumented, non-public methods in the SWT libs, since SWT provides wrappers for a lot of the OS API's (e.g. SWT on Cocoa has the org.eclipse.swt.internal.cocoa.OS#objc_msgSend() methods that can be used to access the OS). The equivalent "OS" classes on Windows and X11 may have API's you can use.

Leptospirosis answered 1/4, 2010 at 5:21 Comment(1)
how to do that in Ubuntu when session is in wayland ?Philoprogenitive
P
4

I have written a java program using user361601's script. I hope this will help others.

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class WindowAndProcessInfo4Linux {

public static final String WIN_ID_CMD = "xprop -root | grep " + "\"_NET_ACTIVE_WINDOW(WINDOW)\"" + "|cut -d ' ' -f 5";
public static final String WIN_INFO_CMD_PREFIX = "xwininfo -id ";
public static final String WIN_INFO_CMD_MID = " |awk \'BEGIN {FS=\"\\\"\"}/xwininfo: Window id/{print $2}\' | sed \'s/-[^-]*$//g\'";

public String execShellCmd(String cmd){
    try {  

        Runtime runtime = Runtime.getRuntime();  
        Process process = runtime.exec(new String[] { "/bin/bash", "-c", cmd });  
        int exitValue = process.waitFor();  
        System.out.println("exit value: " + exitValue);  
        BufferedReader buf = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line = "";  
        String output = "";
        while ((line = buf.readLine()) != null) {
            output = line;
        }
        return output;
    } catch (Exception e) {  
        System.out.println(e);
        return null;
    }  
}

public String windowInfoCmd(String winId){
    if(null!=winId && !"".equalsIgnoreCase(winId)){
        return WIN_INFO_CMD_PREFIX+winId +WIN_INFO_CMD_MID;
    }
    return null;
}

public static void main (String [] args){
    WindowAndProcessInfo4Linux windowAndProcessInfo4Linux = new WindowAndProcessInfo4Linux();
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    String winId = windowAndProcessInfo4Linux.execShellCmd(WIN_ID_CMD);
    String winInfoMcd = windowAndProcessInfo4Linux.windowInfoCmd(winId);
    String windowTitle = windowAndProcessInfo4Linux.execShellCmd(winInfoMcd);
    System.out.println("window title is: "+ windowTitle);

}
}

// the thread.sleep is there so that you get time to switch to other window :) also, you may use quartz from spring to schedule it.

Piecemeal answered 5/6, 2012 at 6:57 Comment(0)
M
3

Using SWT internals, I was able to put this together, and it seems to work nicely:

    /** @return The currently active window's title */
    public static final String getActiveWindowText() {
        long /*int*/ handle = OS.GetForegroundWindow();
        int length = OS.GetWindowTextLength(handle);
        if(length == 0) return "";
        /* Use the character encoding for the default locale */
        TCHAR buffer = new TCHAR(0, length + 1);
        OS.GetWindowText(handle, buffer, length + 1);
        return buffer.toString(0, length);
    }
public static final void main(String[] args) {
    try {
        Thread.sleep(1000L);
    } catch(InterruptedException e) {
        Thread.currentThread().interrupt();
    }
    System.out.println(getActiveWindowText());
}

Prints: user interface - Get current active window's title in Java - Stack Overflow - Google Chrome

Morty answered 14/10, 2018 at 17:3 Comment(1)
One thing I should note, this is using the Windows-specific SWT librariy, and so it won't work on other platforms. You might be able to do what I did and open up the other SWT platform libraries and construct a version of this function for your desired platform.Morty
A
2

To find the active Window(be it a frame or a dialog) in a java swing application you can use the following recursive method:

Window getSelectedWindow(Window[] windows) {
    Window result = null;
    for (int i = 0; i < windows.length; i++) {
        Window window = windows[i];
        if (window.isActive()) {
            result = window;
        } else {
            Window[] ownedWindows = window.getOwnedWindows();
            if (ownedWindows != null) {
                result = getSelectedWindow(ownedWindows);
            }
        }
    }
    return result;
}

this is from here More clues on Window state here.

Actuality answered 30/8, 2009 at 16:46 Comment(3)
That only takes Java windows into account, though, whereas I think Steven wants to get the globally active window, whether it's a Java program or not.Heavyweight
Oops! I misunderstood the question!Actuality
David is right, I want to know the name of the globally active window. That way I can automatically keep track of when I use, say, firefox, and when I use, say, Eclipse.Oreopithecus
R
2

I've written a bash script that logs the current active window: http://www.whitelamp.com/public/active-window-logger.html It uses a patched version of wmctrl but provides details of an alternative (slower) method using xprop and xwininfo.

The links to the wmctrl patch & source code and the script can be found above.

Room answered 8/6, 2010 at 16:56 Comment(0)
T
-1

I created this applescript while looking into similar topic - this one gets the specific window size

global theSBounds

tell application "System Events"
	set this_info to {}
	set theSBounds to {}
	repeat with theProcess in processes
		if not background only of theProcess then
			tell theProcess
				set processName to name
				set theWindows to windows
			end tell
			set windowsCount to count of theWindows
			
			if processName contains "xxxxxxxx" then
				set this_info to this_info & processName
				
			else if processName is not "Finder" then
				if windowsCount is greater than 0 then
					repeat with theWindow in theWindows
						tell theProcess
							tell theWindow
								if (value of attribute "AXTitle") contains "Genymotion for personal use -" then
									-- set this_info to this_info & (value of attribute "AXTitle")
									set the props to get the properties of the theWindow
									set theSBounds to {size, position} of props
									set this_info to this_info & theSBounds
								end if
							end tell
						end tell
					end repeat
				end if
			end if
		end if
	end repeat
end tell
return theSBounds
Tomikotomkiel answered 30/12, 2014 at 8:9 Comment(1)
Please also provide explanation for your code instead of just pasting it here.Psychognosis

© 2022 - 2024 — McMap. All rights reserved.