使用X11 / Xlib接收聚焦小部件更改事件

时间:2014-02-20 10:11:22

标签: linux x11 xlib xorg

我目前正在寻找一种方法来从Linux OS上的X服务器接收小部件焦点更改事件。

我尝试过使用XSelectInput(dpy, focuswin, FocusChangeMask);,但服务器只在焦点窗口发生变化时通知我,而不是特定窗口内的焦点小部件(例如文本输入)。

我想完成此操作,以便在可编辑文本区域获得焦点时显示虚拟键盘。

到目前为止编写的代码是:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>

static Display *dpy;
static Window focuswin = None;

static void attach_to_focuswin(void) {
    int revert_to = 0;

    XGetInputFocus(dpy, &focuswin, &revert_to);
    XSetWindowAttributes attr;
    attr.event_mask = FocusChangeMask;
    XChangeWindowAttributes(dpy, focuswin, CWEventMask, &attr);

    if (focuswin != None)
            XSelectInput(dpy, focuswin, FocusChangeMask);
    else
        sleep(1);
}

static void handle_event(void) {
    XEvent ev;
    char buf[100];
    int len;

    XNextEvent(dpy, &ev);
    if (ev.xany.type == FocusOut) {
        focuswin = None;
        fprintf(stdout, "func: handle_event -> focusing out of window\n\n\n");
    } else if (ev.xany.type == FocusIn) {
        fprintf(stdout, "func: handle_event -> focusing out of window\n\n\n");
    } else if (ev.xany.type == KeyPress) {
        len = XLookupString(&ev.xkey, buf, 99, 0, 0);
        buf[len] = 0;
        printf("%s", buf);
        fflush(stdout);
    } else {
        fprintf(stdout, "func: handle_event -> something else %d\n\n\n", ev.type);
    }
}

int main(void) {

    dpy = XOpenDisplay(getenv("DISPLAY"));

    if (dpy == NULL) {
        fprintf(stdout, "cannot init display\n");
        exit(1);
    }

    while (1) {
        if (focuswin == None)
            attach_to_focuswin();
        else
            handle_event();
    }
}

1 个答案:

答案 0 :(得分:1)

X服务器没有小部件的概念。它只知道窗口。

如果一个应用程序在一个窗口中都有一个文本输入,一个无线电组和一个按钮,那么应用程序之外的任何内容都不知道它当前认为哪个小部件是活动的还是关注的或者其他什么。

如果文本小部件实际上是作为窗口实现的,您可以在其上获得焦点更改事件。您需要在该窗口上调用XSelectInput

此外,还不清楚如何区分文本输入窗口和其他应用程序中的其他类型的窗口。 X服务器不知道哪些窗口是文本输入的。