簡體   English   中英

使用XCB檢測窗口焦點變化

[英]Detect window focus changes with XCB

我正在用XCB編寫一個程序,該程序需要檢測窗口何時獲得焦點或失去焦點。 到目前為止,我已經知道了,但它只是掛在xcb_wait_for_event調用上,從未進入循環。 我在這里缺少舉辦根事件的想法嗎? 還是我只是要解決這個完全錯誤的問題,還有比聽根源更好的方法嗎?

#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>

int main (int argc, char **argv)
{
    xcb_connection_t* conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(conn)) {
        printf("Cannot open daemon connection.");
        return 0;
    }

    xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

    uint32_t values[] = { XCB_EVENT_MASK_FOCUS_CHANGE };
    xcb_change_window_attributes(
        conn,
        screen->root,
        XCB_CW_EVENT_MASK,
        values);

    xcb_generic_event_t *ev;
    while ((ev = xcb_wait_for_event(conn))) {
        printf("IN LOOP\n");
        switch (ev->response_type & 0x7F) {
        case XCB_FOCUS_IN:
        case XCB_FOCUS_OUT:
            printf("IN CASE\n");
            break;
        default:
            printf("IN DEFAULT\n");
            break;
        }
        free(ev);
    }

    return 0;
}

僅在您選擇了這些事件的窗口接收焦點或失去焦點時才發送焦點事件,請參閱https://www.x.org/releases/X11R7.5/doc/x11proto/proto.html

FocusIn FocusOut

[...]

這些事件在輸入焦點更改時生成,並報告給選擇該窗口上的FocusChange的客戶端。

要使用此功能,您將必須在所有窗口上選擇此事件掩碼,並還要注意新窗口的創建。


我建議使用另一種方法:在根窗口上監視PropertyChangeNotify事件,以查看_NET_ACTIVE_WINDOW屬性何時更改。 根據EWMH,此屬性應由WM保持最新狀態。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xcb/xcb.h>

static xcb_atom_t intern_atom(xcb_connection_t *conn, const char *atom)
{
    xcb_atom_t result = XCB_NONE;
    xcb_intern_atom_reply_t *r = xcb_intern_atom_reply(conn,
            xcb_intern_atom(conn, 0, strlen(atom), atom), NULL);
    if (r)
        result = r->atom;
    free(r);
    return result;
}

int main (int argc, char **argv)
{
    xcb_connection_t* conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(conn)) {
        printf("Cannot open daemon connection.");
        return 0;
    }

    xcb_atom_t active_window = intern_atom(conn, "_NET_ACTIVE_WINDOW");
    xcb_screen_t* screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

    uint32_t values[] = { XCB_EVENT_MASK_PROPERTY_CHANGE };
    xcb_change_window_attributes(
        conn,
        screen->root,
        XCB_CW_EVENT_MASK,
        values);

    xcb_flush(conn);

    xcb_generic_event_t *ev;
    while ((ev = xcb_wait_for_event(conn))) {
        printf("IN LOOP\n");
        switch (ev->response_type & 0x7F) {
        case XCB_PROPERTY_NOTIFY: {
            xcb_property_notify_event_t *e = (void *) ev;
            if (e->atom == active_window)
                puts("active window changed");
            break;
        }
        default:
            printf("IN DEFAULT\n");
            break;
        }
        free(ev);
    }

    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM