【问题标题】:Obtain keyboard layout and keysyms with XCB使用 XCB 获取键盘布局和键符
【发布时间】:2013-09-12 10:45:09
【问题描述】:

我正在创建一个集成在简单窗口管理器中的 Linux 屏幕键盘。我目前正在使用 XCB,现在我想做假击键。使用 xtest 扩展程序一切正常,除了我无法从我想要输入的键符中获取真正的键码的细节。

目前我正在使用 xcb_key_symbols_get_keycode,然后我使用 xcb_key_symbols_get_keysym 来了解获取该符号所需的修饰符。当配置的键盘是美国键盘时,这可以正常工作。但我有一个西班牙语键盘,这个调用只返回美国配置。在西班牙语键盘中,使用正确的 alt (altgr) 可以获得几个符号,但前面的调用似乎不支持它。

那么,我怎样才能获得获得任何键符所需的键码?我认为我需要 XKB 扩展,但我一直无法为 XCB 找到它们,我不想为 XLib 重写整个窗口管理器。

谢谢。

【问题讨论】:

    标签: keyboard xcb


    【解决方案1】:

    这可能是一个过时的问题,但我发现它仍然有效。

    您可以通过 xcb 启用 xkb 扩展,然后通过 xcb API(或者更具体地从 xkb 键盘映射的状态)获取键盘映射、布局以及该布局的适当键符。

    链接:

    我必须承认,我实际上并没有完全做到这一点(仅取决于键映射/布局/状态)。但这应该足以让您入门。 :)

    【讨论】:

      【解决方案2】:

      以下代码将打印整个 keycode-to-keysym 映射。它相当于xmodmap -pkxmodmap -pke。也就是说,给定任何键码,它都会为您提供与该键码关联的键符。

      (除了它只显示keysym values,不显示keysym names,你可以在/usr/include/X11/keysymdef.h或使用Xlib的XKeysymToString()找到,我没有认为存在该功能的 XCB 端口,但您可以根据 keysymdef.h 编写自己的端口。)(在我的 X 服务器上,每个键码有 7 个键符,我想知道 X 服务器是否可以支持超过那……)

      /*
      gcc keymap.c -o keymap -lxcb && ./keymap
      */
      #include <stdlib.h>
      #include <stdio.h>
      #include <xcb/xcb.h>
      
      void xcb_show_keyboard_mapping(xcb_connection_t* connection, const xcb_setup_t* setup){
        xcb_get_keyboard_mapping_reply_t* keyboard_mapping =
          xcb_get_keyboard_mapping_reply(
            connection,
            xcb_get_keyboard_mapping(
              connection,
              setup->min_keycode,
              setup->max_keycode - setup->min_keycode + 1),
            NULL);
      
        int          nkeycodes = keyboard_mapping->length / keyboard_mapping->keysyms_per_keycode;
        int          nkeysyms  = keyboard_mapping->length;
        xcb_keysym_t* keysyms  = (xcb_keysym_t*)(keyboard_mapping + 1);  // `xcb_keycode_t` is just a `typedef u8`, and `xcb_keysym_t` is just a `typedef u32`
        printf("nkeycodes %u  nkeysyms %u  keysyms_per_keycode %u\n\n", nkeycodes, nkeysyms, keyboard_mapping->keysyms_per_keycode);
      
        for(int keycode_idx=0; keycode_idx < nkeycodes; ++keycode_idx){
          printf("keycode %3u ", setup->min_keycode + keycode_idx);
          for(int keysym_idx=0; keysym_idx < keyboard_mapping->keysyms_per_keycode; ++keysym_idx){
            printf(" %8x", keysyms[keysym_idx + keycode_idx * keyboard_mapping->keysyms_per_keycode]);
          }
          putchar('\n');
        }
      
        free(keyboard_mapping);
      }
      
      int main(){
        xcb_connection_t*  connection = xcb_connect(NULL, NULL);
        const xcb_setup_t* setup      = xcb_get_setup(connection);
        xcb_show_keyboard_mapping(connection, setup);
        xcb_disconnect(connection);
      }
      

      如果你想要相反的映射(keysyms-to-keycodes),你可能想要xcb_key_symbols_get_keycode(),我不知道。


      不,你不需要 XKB 来处理键盘的东西。您可能想要的大部分内容都可以使用核心 X 协议完成,包括但不限于修改上述键码到键符号的映射、抓取键盘、抓取鼠标、发送键盘/鼠标输入,使用所有 8 个修饰符,并写入“伪 Unicode”(即您在 keysymdef.h 中找到的所有符号,我认为这不是官方的 Unicode,但确实包含很多东西)。

      【讨论】:

      • 问题是我需要相反的:从keysym获取keycode。无论如何,我找到了一个解决方案:将每个键码生成的键符与所有可能的修饰符一起存储在一个列表中,然后搜索我需要的键符。
      猜你喜欢
      • 2013-07-19
      • 2019-12-09
      • 2016-05-24
      • 1970-01-01
      • 2013-07-25
      • 2015-01-10
      • 2019-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多