在Linux中,是否可能在当前关注的GUI应用程序更改时收到通知?我正在编写一个跟踪用户停留在每个GUI应用程序上的时间的应用程序(每个进程而不是在一个进程内),并需要一种访问此信息的方法。我正在使用C ++进行此操作。
到目前为止,我找到了以下内容:
这段代码会打印出当前焦点应用程序的pid,但需要定时拉取。如果可以的话,我宁愿不拉取。此外,它假设所有GUI都通过x11进行,这可能不是一个不合理的假设,但并不完全可移植。
另一种方法是编写一个共享对象,钩入各种GUI函数,然后修改主机系统的ld.so.preload文件,以便在每个进程中加载此共享对象。这假设所有GUI应用程序都使用动态链接的图形库。我还必须为每个图形库编写钩子,以确保完全覆盖。在研究GTK(我正在运行Gnome的系统上进行测试)时,我没有找到任何在窗口切换时调用的函数。虽然我没有仔细查找。
有没有办法通过x11或其他图形库获得此类通知?
编辑:
好的,根据@Andrey的代码,这是我目前的进展:
到目前为止,我找到了以下内容:
xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
这段代码会打印出当前焦点应用程序的pid,但需要定时拉取。如果可以的话,我宁愿不拉取。此外,它假设所有GUI都通过x11进行,这可能不是一个不合理的假设,但并不完全可移植。
另一种方法是编写一个共享对象,钩入各种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];
}
但是get_window_pid
总是返回-1,即使使用xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'
正确返回活动窗口的pid。我做错了什么?
get_window_pid(e.xproperty.display, e.xproperty.window, e.xproperty.atom);
并像这样调用:pid_t get_window_pid(Display *d, Window w, Atom atom)
- tburette