首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

XCB 程式設計教學(三):事件捕獲與響應完整實作

     編輯:關於C++

X 視窗事件驅動模型

GUI 程式皆為事件驅動。XCB 透過 xcb_wait_for_event() 從 X Server 取得事件,在迴圈中依類型分派處理。

完整事件處理範例


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

void print_modifiers(uint32_t mask) {
    const char *MODS[] = {"Shift","Lock","Ctrl","Alt","Mod2","Mod3","Mod4","Mod5",
                          "Button1","Button2","Button3","Button4","Button5"};
    printf("Modifier mask: ");
    for (const char **m = MODS; mask; mask >>= 1, ++m)
        if (mask & 1) printf("%s ", *m);
    printf("\n");
}

int main() {
    xcb_connection_t *conn = xcb_connect(NULL, NULL);
    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data;

    xcb_window_t win = xcb_generate_id(conn);
    uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
    uint32_t vals[2] = {screen->white_pixel,
        XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
        XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
        XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
        XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE};
    xcb_create_window(conn, 0, win, screen->root, 0, 0, 600, 400, 10,
                      XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, vals);
    xcb_map_window(conn, win); xcb_flush(conn);

    xcb_generic_event_t *ev;
    while ((ev = xcb_wait_for_event(conn))) {
        switch (ev->response_type & ~0x80) {
            case XCB_EXPOSE: {
                xcb_expose_event_t *ex = (xcb_expose_event_t*)ev;
                printf("Window %u exposed. Redraw at (%u,%u) size (%u,%u)\n",
                       ex->window, ex->x, ex->y, ex->width, ex->height);
                break;
            }
            case XCB_BUTTON_PRESS: {
                xcb_button_press_event_t *bp = (xcb_button_press_event_t*)ev;
                print_modifiers(bp->state);
                switch (bp->detail) {
                    case 4: printf("Wheel Up in win %u at (%d,%d)\n", bp->event, bp->event_x, bp->event_y); break;
                    case 5: printf("Wheel Down in win %u at (%d,%d)\n", bp->event, bp->event_x, bp->event_y); break;
                    default: printf("Button %u pressed in win %u at (%d,%d)\n", bp->detail, bp->event, bp->event_x, bp->event_y);
                }
                break;
            }
            case XCB_BUTTON_RELEASE: {
                xcb_button_release_event_t *br = (xcb_button_release_event_t*)ev;
                print_modifiers(br->state);
                printf("Button %u released in win %u at (%d,%d)\n", br->detail, br->event, br->event_x, br->event_y);
                break;
            }
            case XCB_MOTION_NOTIFY: {
                xcb_motion_notify_event_t *mv = (xcb_motion_notify_event_t*)ev;
                printf("Mouse moved in win %u at (%d,%d)\n", mv->event, mv->event_x, mv->event_y);
                break;
            }
            case XCB_ENTER_NOTIFY: {
                xcb_enter_notify_event_t *en = (xcb_enter_notify_event_t*)ev;
                printf("Mouse entered win %u at (%d,%d)\n", en->event, en->event_x, en->event_y);
                break;
            }
            case XCB_LEAVE_NOTIFY: {
                xcb_leave_notify_event_t *lv = (xcb_leave_notify_event_t*)ev;
                printf("Mouse left win %u at (%d,%d)\n", lv->event, lv->event_x, lv->event_y);
                break;
            }
            case XCB_KEY_PRESS: {
                xcb_key_press_event_t *kp = (xcb_key_press_event_t*)ev;
                print_modifiers(kp->state);
                printf("Key pressed in win %u\n", kp->event); break;
            }
            case XCB_KEY_RELEASE: {
                xcb_key_release_event_t *kr = (xcb_key_release_event_t*)ev;
                print_modifiers(kr->state);
                printf("Key released in win %u\n", kr->event);
                if (kr->detail == 9) { free(ev); xcb_disconnect(conn); return 0; } // ESC
                break;
            }
            default: printf("Unknown event: %u\n", ev->response_type);
        }
        free(ev);
    }
    return 0;
}

執行畫面

關鍵機制解析

1. 事件註冊(建立視窗時)

mask = XCB_CW_EVENT_MASK,values 填入關心的事件位元組合(XCB_EVENT_MASK_*)。

2. 事件結構統一性

所有事件固定 32 bytes,第一 byte 為 response_type。用 xcb_generic_event_t* 接收,再依類型強轉具體結構(如 xcb_button_press_event_t*)。

3. response_type & ~0x80 目的

  • 最高位 (bit 7) = 1 表示 SendEvent 發送的合成事件。
  • 最高位 = 0 表示 X Server 產生的原生事件。
  • 應用層通常不關心來源,只關心類型,故屏蔽最高位。

4. 常見事件類型枚舉

核心協定定義 33 種事件,Vim Ctrl+] 可跳轉查看各結構定義。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved