简体   繁体   中英

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.

I have tried using 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. 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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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