简体   繁体   English

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

[英]Receive focused widget changing events with X11/Xlib

I am currently searching for a way to receive widgets focus change events from X server on Linux OS.我目前正在寻找一种从 Linux OS 上的 X 服务器接收小部件焦点更改事件的方法。

I have tried using XSelectInput(dpy, focuswin, FocusChangeMask);我试过使用XSelectInput(dpy, focuswin, FocusChangeMask); , but the server notifies me only when the focused window changes, not the focused widget (eg a text input) inside a specific window. ,但服务器仅在焦点窗口更改时通知我,而不是特定窗口内的焦点小部件(例如文本输入)。

I want to accomplish this in order to show a virtual keyboard whenever an editable text area gains focus.我想完成此操作,以便在可编辑文本区域获得焦点时显示虚拟键盘。

The code written until now is:到现在写的代码是:

#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();
    }
}

The X server has no concept of widgets. X 服务器没有小部件的概念。 It only knows windows.它只知道窗户。

If an application has a text input, a radio group, and a push button implemented all in a single window, then nothing outside of the application has any idea about which widget it currently considers active or focused or whatever.如果一个应用程序在一个窗口中实现了一个文本输入、一个单选组和一个按钮,那么应用程序之外的任何人都不知道它当前认为哪个小部件是活动的或聚焦的或其他任何东西。

If the text widget is actually implemented as a window, you can get focus change events on it.如果文本小部件实际上是作为窗口实现的,则可以在其上获取焦点更改事件。 You need to call XSelectInput on that window .您需要在该窗口上调用 XSelectInput。

In addition, it's not clear how you can differentiate between text input windows and other kinds of windows in other applications.此外,尚不清楚如何区分文本输入窗口和其他应用程序中的其他类型的窗口。 The X server has no idea which windows are text-input ones. X 服务器不知道哪些窗口是文本输入窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM