2009-08-30 28 views
11

Sto provando a scrivere un programma Java che registra quale applicazione sto usando ogni 5 secondi (questa è un'app di registrazione del tempo). Ho bisogno di un modo per scoprire cos'è la finestra attiva corrente. Ho trovato KeyboardFocusManager.getGlobalActiveWindow() ma non riesco a farlo funzionare correttamente. È preferibile una soluzione multipiattaforma, ma se uno non esiste, allora sto sviluppando per linux con X.Org. Grazie.Ottieni il titolo corrente della finestra attiva in Java

+0

Si sta utilizzando un sistema a finestre, come KDE o Gnome? Potrebbe essere necessario sapere che, poiché questo tipo di attività di solito deve essere fatto con codice specifico del sistema. –

+0

Gnome è la mia prima priorità. –

risposta

2

Per trovare la finestra attiva (sia esso una cornice o una finestra) in un'applicazione Java Swing è possibile utilizzare il seguente metodo ricorsivo:

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

questo è da here Altri indizi sullo stato Finestra here.

+2

Tuttavia, solo le finestre Java sono prese in considerazione, mentre io penso che Steven voglia ottenere la finestra globalmente attiva, che si tratti di un programma Java o meno. –

+0

Oops!Ho frainteso la domanda! –

+2

David ha ragione, voglio sapere il nome della finestra attiva a livello globale. In questo modo posso automaticamente tenere traccia di quando uso, ad esempio, firefox e quando uso, ad esempio, Eclipse. –

7

Sono certo che non troverete alcun modo per enumerare le finestre attive in Java puro (mi sono sembrato piuttosto difficili prima), quindi dovrete codificare per le piattaforme che volete targetizzare.

  • In Mac OS X, è possibile avviare un AppleScript utilizzando "osascript".

  • Su X11, è possibile utilizzare xwininfo.

  • Su Windows, probabilmente è possibile avviare alcuni VBScript (ad esempio, this link sembra promettente).

Se stai usando SWT, si può essere in grado di trovare alcuni metodi non pubblici privi di documenti nelle librerie SWT, dal momento che SWT fornisce wrapper per un sacco di API OS (ad esempio SWT sul cacao ha la org.eclipse.swt.internal.cocoa.OS#objc_msgSend() metodi che possono essere utilizzati per accedere al sistema operativo). Le classi equivalenti di "OS" su Windows e X11 possono avere API che puoi usare.

2

Ho scritto uno script bash che registra l'attuale finestra attiva: http://www.whitelamp.com/public/active-window-logger.html Esso utilizza una versione modificata di wmctrl ma fornisce dettagli di un metodo alternativo (più lento) utilizzando xprop e xwininfo.

I collegamenti al codice sorgente & della patch wmctrl e lo script possono essere trovati in .

+0

Grazie mille per questo script. – vaibhav

+1

non funziona ora (2014-06-16). – VasyaNovikov

3

Ho scritto un programma java utilizzando lo script di user361601. Spero che questo aiuti gli altri.

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

} 
} 

// il Thread.sleep è là in modo che si ottiene il tempo per passare alla altra finestra :) Inoltre, è possibile utilizzare quarzo dalla primavera pianificarlo.

0

Ho creato questo AppleScript mentre guardando in soggetti simili - questo si ha la dimensione specifica della finestra

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

Fornisci anche una spiegazione per il tuo codice invece di incollarlo qui. –

+0

C'è una spiegazione. Se non ti piace quello che ho postato o non voglio spendere un paio di minuti per vedere ciò che lo script fa poi maledettamente eliminare il post. – Henri

Problemi correlati