Linux获取有关重点GUI窗口更改的通知 [英] Linux get notification on focused gui window change

查看:110
本文介绍了Linux获取有关重点GUI窗口更改的通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在linux中,当当前关注的GUI应用程序更改时,是否可以获得通知?我正在编写一个应用程序,该应用程序可以跟踪用户在每个GUI应用程序上停留的时间(每个进程,而不是一个进程),并且需要某种方式来访问此信息.我正在用c ++做到这一点.


到目前为止,这是我发现的东西:

In linux, is it possible to get notifications when the currently focused GUI app changes? I'm writing an app that tracks how long a user stays on each GUI app(per process, not within one process), and need some way to access this information. I'm doing this in c++.


Here is what I have found so far:

xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}'

这会打印出当前关注的应用程序的pid,但需要我经常拉.我宁愿不拉,但如果需要的话,我会拉.它还假定所有GUI都通过x11,这可能不是不合理的假设,但并非完全可移植.

This prints out the pid of the currently focused app, but would require me to pull every so often. I would rather not pull, but I will if I have to. It also assumes that all GUI's are going through x11, which may not be an unreasonable assumption, but is not entirely portable.

另一种方法是编写一个挂接到各种gui函数的共享库,然后修改主机系统的ld.so.preload文件以在每个进程中加载​​该共享库.假定所有gui应用程序都在使用动态链接的图形库.我还必须为每个图形库编写钩子,以确保总覆盖率.在研究GTK(我正在运行Gnome的系统上进行测试)中,我没有发现任何在窗口开关上调用的功能.我看起来还不是很辛苦.


有没有办法通过x11接收此类通知?还是其他图形库呢?

Another approach would be to write a shared object that hooks into various gui functions, and then modify the host system's ld.so.preload file to load this shared object with every process. This assumes that all gui apps are using dynamically linked graphics libraries. I would also have to write hooks for every graphics library to ensure total coverage. And in researching GTK (I'm doing my testing on a system running Gnome), I haven't found any functions that are called on window switches. I haven't looked very hard though.


Is there a way to get notifications through x11 for this sort of thing? Or other graphics libraries for that matter?

好吧,这是我到目前为止基于@Andrey的代码得出的:

Okay, this is what I have so far, based off @Andrey 's code:

#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.我在做什么错了?

But get_window_pid always returns -1, even though using xprop -id $(xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}') | awk '/_NET_WM_PID\(CARDINAL\)/{print $NF}' correctly returns the pid of the active window. What am I doing wrong?

推荐答案

使用 node-x11 :

var x11 = require('x11');
x11.createClient(function(err, display) {
  var X = display.client;
  X.ChangeWindowAttributes(display.screen[0].root, { eventMask: x11.eventMask.PropertyChange });
  X.on('event', function(ev) {
    if(ev.name == 'PropertyNotify') {
      X.GetAtomName(ev.atom, function(err, name) {
        if (name == '_NET_ACTIVE_WINDOW') {
          X.GetProperty(0, ev.window, ev.atom, X.atoms.WINDOW, 0, 4, function(err, prop) {
            console.log('New active window:' + prop.data.readUInt32LE(0));
          });
        }
      });
    }
  });
});

这篇关于Linux获取有关重点GUI窗口更改的通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆