Linux で、現在フォーカスされている GUI アプリが変更されたときに通知を受け取ることは可能ですか? ユーザーが各 GUI アプリ (1 つのプロセス内ではなくプロセスごと) に滞在している時間を追跡するアプリを作成しており、この情報にアクセスする方法が必要です。私はこれをc ++でやっています。
これが私がこれまでに見つけたものです:
xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
これにより、現在フォーカスされているアプリの pid が出力されますが、頻繁にプルする必要があります。引っ張らない方がいいですが、必要に応じて引っ張ります。また、すべての GUI が x11 を使用していることも前提としています。これは不合理な前提ではないかもしれませんが、完全に移植できるわけではありません。
もう 1 つの方法は、さまざまな GUI 関数にフックする共有オブジェクトを作成し、ホスト システムの ld.so.preload ファイルを変更して、この共有オブジェクトをすべてのプロセスでロードすることです。これは、すべての GUI アプリが動的にリンクされたグラフィック ライブラリを使用していることを前提としています。また、全体を確実にカバーするために、すべてのグラフィックス ライブラリのフックを作成する必要があります。また、GTK の調査 (Gnome を実行しているシステムでテストを行っています) では、ウィンドウ スイッチで呼び出される関数は見つかりませんでした。あまり真剣に見ていませんが。
この種のことについて x11 を介して通知を受け取る方法はありますか? それとも他のグラフィックライブラリですか?
編集:
さて、これは @Andrey のコードに基づいて、これまでのところ私が持っているものです:
#include <X11/Xlib.h>
#include <cstring>
#include <iostream>
using namespace std;
pid_t get_window_pid( Display * d, Window& w );
int main()
{
Display * d;
Window w;
XEvent e;
d = XOpenDisplay( 0 );
if ( !d ) {
cerr << "Could not open display" << endl;
return 1;
}
w = DefaultRootWindow( d );
XSelectInput( d, w, PropertyChangeMask );
pid_t window_pid;
for ( ;; ) {
XNextEvent( d, &e );
if ( e.type == PropertyNotify ) {
if ( !strcmp( XGetAtomName( d, e.xproperty.atom ), "_NET_ACTIVE_WINDOW" ) ) {
window_pid = get_window_pid( d, w );
cout << window_pid << endl;
}
}
}
return 0;
}
pid_t get_window_pid( Display * d, Window& w )
{
Atom atom = XInternAtom( d, "_NET_WM_PID", true );
Atom actual_type;
int actual_format;
unsigned long nitems;
unsigned long bytes_after;
unsigned char *prop;
int status;
status = XGetWindowProperty(
d, w, atom, 0, 1024,
false, AnyPropertyType,
&actual_type,
&actual_format, &nitems,
&bytes_after,
&prop
);
if ( status || !prop )
return -1;
return prop[1] * 256 + prop[0];
}
ただし、使用するとアクティブなウィンドウの pid が正しく返されますがget_window_pid
、常に -1 が返されます。xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
私は何を間違っていますか?