2009-08-30 25 views
11

Próbuję napisać program w języku Java, który rejestruje aplikację, z której korzystam co 5 sekund (jest to aplikacja do śledzenia czasu). Potrzebuję sposobu, aby dowiedzieć się, jakie jest bieżące aktywne okno. Znalazłem KeyboardFocusManager.getGlobalActiveWindow(), ale nie mogę go uruchomić poprawnie. Preferowane jest rozwiązanie wieloplatformowe, ale jeśli nie istnieje, to rozwijam dla systemu Linux z X.Org. Dzięki.Pobierz bieżący tytuł aktywnego okna w Javie

+0

Czy używasz systemu okienkowego jak KDE czy GNOME? Może być konieczne, aby wiedzieć, że ten typ zadania zwykle musi być wykonywany za pomocą kodu specyficznego dla systemu. –

+0

Gnome to mój pierwszy priorytet. –

Odpowiedz

2

Aby znaleźć aktywnego okna (może to być ramka lub okno dialogowe) w aplikacji Java Swing można wykorzystać następujące metody rekurencyjnej:

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; 
} 

to z here Więcej wskazówek na temat stanu Okno here.

+2

To jednak bierze pod uwagę tylko okna Java, podczas gdy myślę, że Steven chce uzyskać globalnie aktywne okno, niezależnie od tego, czy jest to program Java, czy nie. –

+0

Ups!Źle zrozumiałem pytanie! –

+2

David ma rację, chcę znać nazwę globalnie aktywnego okna. W ten sposób mogę automatycznie śledzić, kiedy używam, powiedzmy, firefox i kiedy używam, powiedzmy, Eclipse. –

7

Jestem przekonany, że nie da się wyliczyć aktywnych okien w czystej Javie (wcześniej wyglądałem dosyć ciężko), więc musisz kodować platformy, na które chcesz kierować reklamy.

  • na Mac OS X, można uruchomić AppleScript użyciu "osascript".

  • Na X11 można użyć xwininfo.

  • W systemie Windows prawdopodobnie można uruchomić niektóre skrypty VBScript (np. this link wygląda obiecująco).

Jeśli używasz SWT, być może uda się znaleźć jakieś nieudokumentowane, metody niepublicznych w libs SWT, ponieważ SWT zapewnia obwoluty dla wielu OS API (np SWT na kakao ma org.eclipse.swt.internal.cocoa.OS#objc_msgSend() metody, które można wykorzystać do uzyskania dostępu do systemu operacyjnego). Odpowiednie klasy "OS" w Windows i X11 mogą mieć interfejsy API, z których możesz korzystać.

2

pisałem skrypt bash, który rejestruje bieżące aktywne okno: http://www.whitelamp.com/public/active-window-logger.html wykorzystuje poprawioną wersję wmctrl ale zapewnia szczegóły metoda alternatywna (wolniej) używając xprop i xwininfo.

Linki do kodu źródłowego wmctrl & kodu źródłowego i skryptu mogą być znalezione powyżej.

+0

Wielkie dzięki za ten skrypt. – vaibhav

+1

nie działa teraz (2014-06-16). – VasyaNovikov

3

Napisałem program java za pomocą skryptu user361601. Mam nadzieję, że to pomoże innym.

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); 

} 
} 

// Thread.Sleep jest tak, że masz czas, aby przełączyć się do innego okna :) również można użyć kwarc od wiosny do tego zaplanować.

0

Stworzyłem ten AppleScript patrząc w podobnym temacie - ten dostaje konkretny rozmiar okna

global theSBounds 
 

 
tell application "System Events" 
 
\t set this_info to {} 
 
\t set theSBounds to {} 
 
\t repeat with theProcess in processes 
 
\t \t if not background only of theProcess then 
 
\t \t \t tell theProcess 
 
\t \t \t \t set processName to name 
 
\t \t \t \t set theWindows to windows 
 
\t \t \t end tell 
 
\t \t \t set windowsCount to count of theWindows 
 
\t \t \t 
 
\t \t \t if processName contains "xxxxxxxx" then 
 
\t \t \t \t set this_info to this_info & processName 
 
\t \t \t \t 
 
\t \t \t else if processName is not "Finder" then 
 
\t \t \t \t if windowsCount is greater than 0 then 
 
\t \t \t \t \t repeat with theWindow in theWindows 
 
\t \t \t \t \t \t tell theProcess 
 
\t \t \t \t \t \t \t tell theWindow 
 
\t \t \t \t \t \t \t \t if (value of attribute "AXTitle") contains "Genymotion for personal use -" then 
 
\t \t \t \t \t \t \t \t \t -- set this_info to this_info & (value of attribute "AXTitle") 
 
\t \t \t \t \t \t \t \t \t set the props to get the properties of the theWindow 
 
\t \t \t \t \t \t \t \t \t set theSBounds to {size, position} of props 
 
\t \t \t \t \t \t \t \t \t set this_info to this_info & theSBounds 
 
\t \t \t \t \t \t \t \t end if 
 
\t \t \t \t \t \t \t end tell 
 
\t \t \t \t \t \t end tell 
 
\t \t \t \t \t end repeat 
 
\t \t \t \t end if 
 
\t \t \t end if 
 
\t \t end if 
 
\t end repeat 
 
end tell 
 
return theSBounds

+0

Proszę również podać wyjaśnienie kodu, zamiast tylko wklejać go tutaj. –

+0

Istnieje wyjaśnienie. Jeśli nie podoba ci się to, co napisałem lub nie chcę spędzić kilku minut, aby zobaczyć, co robi skrypt, a następnie krwawy usunąć post. – Henri