一番上のアクティブなウィンドウの PID を取得する方法と、PID を使用してウィンドウのプロパティを取得する方法を知っている人はいますか? プロセス名、プログラム名などのプロパティを意味します。
Linux (Ubuntu 9.10) で Qt を使用しています。
Xサーバーでウィンドウのプロパティを表示するためのユーティリティであるlinux call xpropのコマンドがあります。Linuxではxprop -root
、ルートウィンドウのプロパティとその他のアクティブなプログラムが提供されます。次に、次のコマンドを使用してアクティブなウィンドウの ID を取得できます。
xprop -root | grep _NET_ACTIVE_WINDOW\(WINDOW\)
アクティブなウィンドウ ID (行頭の "_NET_ACTIVE_WINDOW(WINDOW): window id # " なし)だけを取得するには、次のコマンドを使用します。
xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'
このコマンド出力をユーザー定義変数に保存できるようになりました。
myid=xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'
xprop には属性 call -id があります。この引数により、ユーザーはコマンド ラインでウィンドウ ID を選択できます。出力で _NET_WM_PID(CARDINAL) を探す必要があるため、次のコマンドを使用します。
xprop -id $myid | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
これにより、最上位のアクティブなウィンドウ プロセス ID が得られます。
よりトリッキーになり、すべてのことを1つのコマンドで行う...:
xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
これで、popen 関数を使用して C++ プログラム (Linux 内) からこれらのコマンドを実行し、stdout を取得して印刷または保存できます。popen はパイプを作成して、呼び出しているプログラムの出力を読み取ることができるようにします。
(「/proc」ファイル システムを使用して、PID の詳細を取得することもできます (「/proc/ YOUR_PID /status」) )
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
inline std::string exec(char* cmd) {
FILE* pipe = popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
pclose(pipe);
return result;
}
int main()
{
//we uses \\ instead of \ ( \ is a escape character ) in this string
cout << exec("xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\\(WINDOW\\)/{print $NF}') | awk '/_NET_WM_PID\\(CARDINAL\\)/{print $NF}'").c_str();
return 0;
}
X の特徴の 1 つは、ネットワークが透過的であることです。上部に表示されている実際のウィンドウ (フォーカスがある) が自分以外のマシンで実行されている可能性は十分にあります。その場合、ウィンドウ内で実行されているプロセスのプロセス ID はマシンでは意味がありません。
やりたいことを少し詳しく説明していただけますか?ここにはいくつかの詳細が欠けていると思います。理想的には、マシン固有のレベルではなく、X レベルで作業する必要があります。
パーティーにとても遅れていますが、私も同様の問題を抱えていました。これは同じ問題を抱えている他の誰かを助けることができると思います。これを行うにはコマンドラインのトリックがあります。実行するか、実行して出力をコードにリダイレクトしてみてください。
xprop -id $(xprop -root _NET_ACTIVE_WINDOW | cut -d ' ' -f 5) _NET_WM_NAME WM_CLASS
ウィンドウ名とプログラム名を指定します。たとえば、このタブの場合、それは私に与えます
_NET_WM_NAME(UTF8_STRING) = "linux - Getting pid and details for topmost window - Stack Overflow - Mozilla Firefox"
WM_CLASS(STRING) = "Navigator", "Firefox"
ウィンドウ所有者の PID は、X プロパティ _NET_WM_PID に格納されます。これは事実上の標準にすぎないことに注意してください。
最初にウィンドウの ID を見つける必要があります。次に、プロパティを照会できます。QT がこれに対して提供する抽象化については知らないので、おそらく xlib または xcb を使用する必要があります。
xprop
初心者向けのツールで遊んでください。
xlibXGetInputFocus
は、どのウィンドウがフォーカスされているかを教えてくれます。これはおそらく、一番上にあるウィンドウよりも興味深いものです。参照。Xfree86 のXGetInputFocus マンページ。
それが本当に一番上のウィンドウであり、あなたが求めているフォーカスのあるウィンドウではない場合、それを行うための単純な呼び出しはないと思います.xlibはグローバルを照会する方法を提供していないようです.重なり順。これは、どのウィンドウが他のどのウィンドウの前にあるかを示すデータ構造です。
適切なウィンドウ IDxprop
を取得したら、_NET_WM_PID_ の下に pid を一覧表示しますが、すべてのウィンドウにそのようなプロパティがあるわけではありません...
あとがきさらなる考察; 長い間考えていたxlib
...
要約すると:
X は、ウィンドウ ID と pid の間の信頼できる関連付けを提供しません。Noufal が観察しているように、X デスクトップで提供されるウィンドウは、多くの異なるマシンからのものである可能性があり、2 つのリモート クライアントがたまたま同じ PID を使用する可能性があります。機械。参照。プロセス ID から X11 ウィンドウを取得するには?
X は、一番上のウィンドウがどれか、または 1 つのウィンドウが別のウィンドウを遮っているかどうかを尋ねるインターフェースを提供していないようです。同様に、特権アクセスで... Cf. xlibを使用してトップレベルのX11ウィンドウを識別する方法は?
一般的に利用可能なウィンドウ マネージャーと Qt では、X への特権アクセスは許可されません。
最上位のウィンドウを見つける方法と、ウィンドウ ID を一致する pid に確実に関連付ける方法の両方がなければ、問題を解決することはできません。
どのウィンドウにフォーカスがあるかを見つけることができます。これはおそらく私たちが望んでいるものです。しかし、やはり、wid から pid へのマップがなければ ...
申し訳ありませんが、それはできないようです。
私はMichel Kogan's answerに投票し、次の簡潔な要約を追加します。
ps -o pid,comm,args $(xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID | awk "{print \$2}")
上記は、現在アクティブなウィンドウの次を示します: PID、コマンド名 (実行可能ファイル名のみ)、すべての引数を含むコマンド。
端末で次のコマンドを実行します。
sleep 5s; ps -Flwwp $(xdotool getwindowpid $(xdotool getwindowfocus))
それを実行し、フォーカスを関連するウィンドウに変更し、5 秒待ってからターミナルに戻ります。ほら!
wmctrlを(リポジトリから)インストールします。wmctrl -lp
あなたが望むものかもしれません。プログラムから必要な場合は、いつでもソースを確認できます。
xprop の要点をhttps://github.com/mondalaci/current-window-linuxに抽出しました
機能しますが、セグメンテーション違反が発生することがあります - 修正してクリーンアップする必要があります。