4

次のように、を使用して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;

VLCからのコピペGetModifierですが、Altキーは正しくマッチしているのでこの部分は関係ないと思います)

私が抱えている問題はshow()、ホットキーが押されたときにメインウィンドウを表示した後、ほとんどの場合、キーボードが適切にフォーカスされていないことです。入力できますが、カーソルが表示されず、入力の境界線が強調表示されず、Ctrl+Qdesn を終了するためのショートカットが機能しません。ウィンドウを移動するか、スペースを押すことで回避できます-その後、フォーカスが復元されます-カーソル+境界線が再び表示され、Ctrl+Q機能します。この動作の原因は何ですか?

Qt 5.0.0 と xcb 1.8.1 を使用しています。完全なアプリケーションは、コンパイル用に github からダウンロードできます。

1は、問題が再現できない場合があることを意味します。ウィンドウの非表示/表示を繰り返してもフォーカスが正しく設定されますが、非表示/表示の連続で複数回発生する場合もあります。全体的に頻繁に発生します。

(編集:(非常に醜い...)回避策を実装したため、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
4

0 に答える 0