我正在抓Alt+Space
全局热键使用xcb_grab_key
, 如下:
xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(c);
xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, XK_space), keycode;
// add bindings for all screens
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator (xcb_get_setup (c));
for (; iter.rem; xcb_screen_next (&iter)) {
int i = 0;
while(keycodes[i] != XCB_NO_SYMBOL) {
keycode = keycodes[i];
xcb_grab_key(c, true, iter.data->root, XCB_MOD_MASK_ANY, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC);
i += 1;
}
}
然后在 Qt 的 QAbstractNativeEventFilter 子类中处理它并在键匹配时发出 Qt 信号Alt+Space
:
xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, XK_space);
int i = 0;
bool found = false;
while(keycodes[i] != XCB_NO_SYMBOL) {
if(event->detail == keycodes[i]) {
if(event->state & GetModifier(c, keysyms, XK_Alt_L) || event->state & GetModifier(c, keysyms, XK_Alt_R)) {
xcb_allow_events(c, XCB_ALLOW_ASYNC_KEYBOARD, event->time);
emit gotHotKey();
found = true;
} else {
xcb_allow_events(c, XCB_ALLOW_REPLAY_KEYBOARD, event->time);
}
break;
}
i += 1;
}
if(found) return true;
(GetModifier
is 从 VLC 复制 http://svn.tribler.org/vlc/trunk/modules/control/globalhotkeys/xcb.c但我认为这部分并不重要,因为 Alt 键匹配正确)
The problem I'm having is that after show()
ing main window when the hotkey is pressed, keyboard is most of the times1 not focused properly. I can type, but the cursor is not visible, input's border is not highlighted, and the shortcut Ctrl+Q
for quitting desn't work. It can be worked around by moving the window, or pressing space - then focus is restored - cursor+border reappears and Ctrl+Q
works. What might be causing this behaviour?
我正在使用 Qt 5.0.0 和 xcb 1.8.1。完整的应用程序可以下载进行编译来自 github https://github.com/jkozera/zeal.
1 it means sometimes the issue is not reproducible - focus is set correctly even for repeated window hide/shows, but then other times it happens multiple times in a row of hide/shows. It occurs more often than not overall.
(编辑:我已经实现了一个(非常丑陋......)解决方法,因此要重现 github 项目的问题,需要删除以下代码)
#ifndef WIN32
// Very ugly workaround for the problem described at http://stackoverflow.com/questions/14553810/
// (just show and hide a modal dialog box, which for some reason restores proper keyboard focus)
hackDialog.setGeometry(0, 0, 0, 0);
hackDialog.setModal(true);
hackDialog.show();
QTimer::singleShot(100, &hackDialog, SLOT(reject()));
#endif