簡體   English   中英

如何使用鍵盤布局獲取XLib鍵的字符?

[英]How to get the character for an XLib key wrt the keyboard layout?

使用XKeycodeToKeysym (在C ++中)我可以獲得按鍵事件的KeySym。 從我的理解,這已經應該尊重鍵盤布局。 但是,當我切換鍵盤布局(英語和希伯來語之間)時,我得到了相同的KeySym。 我懷疑Xlib Keysym只尊重X11級別中定義的鍵盤布局? 在我的系統中,鍵盤布局僅在桌面環境級別(Mate)中定義。 如果是這樣,有沒有辦法在不使用像Qt / GTK這樣的工具包的情況下獲得正確的角色? 我必須單獨處理每個桌面環境嗎?

[編輯]

我嘗試了以下(根據安德烈的建議),這不起作用:

#include <X11/XKBlib.h>

#include <cstring>
#include <cassert>
#include <iostream>

int main() {
    Display *display = XOpenDisplay(nullptr);
    Window root, window;
    XSetWindowAttributes swa;
    root = DefaultRootWindow( display );
    XSelectInput( display, root, MappingNotify );
    std::memset(&swa, 0, sizeof swa );
    swa.event_mask = MappingNotify | KeyPressMask;
    window = XCreateWindow( display, root, 50, 200, 1024, 768, 0, CopyFromParent, InputOutput, CopyFromParent,
                             CWEventMask, &swa );
    XMapRaised( display, window );
    int xkbEventCode=0, n0=0, n1=0, n2=0, n3=0;
    bool isOk = XkbQueryExtension(  display, &n0, &xkbEventCode, &n1, &n2, &n3 ) ==True;
    assert( isOk );
    isOk = XkbSelectEvents( display, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask ) ==True;
    assert( isOk );
    while (true) {
        XEvent event;
        std::memset( &event, 0, sizeof event );
        XNextEvent( display, &event );
        if (event.type == xkbEventCode)
            switch (reinterpret_cast<XkbEvent*>(&event)->any.xkb_type) {
              case XkbNewKeyboardNotify:
              case XkbMapNotify: {
                std::cout << "Keyboard mapping has changed." << std::endl;
                break;
                }
            default:  break;
            }
        else
            switch (event.type) {
              case KeyPress: {
                KeyCode keyCode = event.xkey.keycode;
                int keySymsPerkeyCode=0;
                KeySym *keySyms( XGetKeyboardMapping(display, keyCode, 1, &keySymsPerkeyCode)),
                       *keySym = keySyms;
                while (keySymsPerkeyCode--  &&  *keySym != NoSymbol) {
                    std::cout << *keySym << std::endl;
                    ++keySym;
                    }
                XFree( keySyms );
                break;
                }
              case MappingNotify: {
                std::cout << "Keyboard mapping has changed." << std::endl;
                break;
                }
              default:  break;
              }
        }
    return 0;
    }

我只能在較低的級別回答,不知道XKeycodeToKeysym作用。

您需要偵聽MappingNotify事件,並且每次收到它時都會使用XGetKeyboardMapping重新讀取新映射(通常這意味着鍵盤布局/語言已更改)

這是核心X協議,桌面環境/ WM獨立的一部分

更新:

看起來xlib默認啟用XKeyboard擴展。 啟用后,您需要明確表達對映射更改事件的興趣(與核心協議不同,其中MappingNotify始終發送給所有客戶端) - 請參閱http://www.x.org/archive/X11R7.5/doc/man/man3 /XkbSelectEvents.3.html

 XkbSelectEvents (display, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask);

之后,您響應XkbMapNotify事件並執行XkbGetMap()以獲取新布局

暫無
暫無

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

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