Exemplo n.º 1
0
Arquivo: xcb.c Projeto: FLYKingdom/vlc
static void Mapping( intf_thread_t *p_intf )
{
    static const xcb_keysym_t p_x11_modifier_ignored[] = {
        0,
        XK_Num_Lock,
        XK_Scroll_Lock,
        XK_Caps_Lock,
    };

    intf_sys_t *p_sys = p_intf->p_sys;

    p_sys->i_map = 0;
    p_sys->p_map = NULL;

    /* Registering of Hotkeys */
    for( struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
            p_hotkey->psz_action != NULL;
            p_hotkey++ )
    {
        char *psz_hotkey;
        if( asprintf( &psz_hotkey, "global-%s", p_hotkey->psz_action ) < 0 )
            break;

        const int i_vlc_action = p_hotkey->i_action;
        const int i_vlc_key = config_GetInt( p_intf, psz_hotkey );

        free( psz_hotkey );

        if( !i_vlc_key )
            continue;

        const xcb_keycode_t key = xcb_key_symbols_get_keycode( p_sys->p_symbols, GetX11Key( i_vlc_key & ~KEY_MODIFIER ) );
        const unsigned i_modifier = GetX11Modifier( p_sys->p_connection, p_sys->p_symbols, i_vlc_key & KEY_MODIFIER );

        for( int j = 0; j < sizeof(p_x11_modifier_ignored)/sizeof(*p_x11_modifier_ignored); j++ )
        {
            const unsigned i_ignored = GetModifier( p_sys->p_connection, p_sys->p_symbols, p_x11_modifier_ignored[j] );
            if( j != 0 && i_ignored == 0x00)
                continue;

            hotkey_mapping_t *p_map_old = p_sys->p_map;
            p_sys->p_map = realloc( p_sys->p_map, sizeof(*p_sys->p_map) * (p_sys->i_map+1) );
            if( !p_sys->p_map )
            {
                p_sys->p_map = p_map_old;
                break;
            }
            hotkey_mapping_t *p_map = &p_sys->p_map[p_sys->i_map++];

            p_map->i_x11 = key;
            p_map->i_modifier = i_modifier|i_ignored;
            p_map->i_action = i_vlc_action;
        }
    }
}
Exemplo n.º 2
0
void MainWindow::setHotKey(const QKeySequence& hotKey_) {
    // platform-specific code for global key grabbing
#ifdef WIN32
    UINT i_vk, i_mod = 0;
    if(!hotKey.isEmpty()) {
        // disable previous hotkey
        UnregisterHotKey(NULL, 10);
    }
    hotKey = hotKey_;
    nativeFilter.setHotKey(hotKey);
    settings.setValue("hotkey", hotKey);
    if(hotKey.isEmpty()) return;
    int key = hotKey[0];
    if(key & Qt::ALT) i_mod |= MOD_ALT;
    if(key & Qt::CTRL) i_mod |= MOD_CONTROL;
    if(key & Qt::SHIFT) i_mod |= MOD_SHIFT;
    key = key & ~(Qt::ALT | Qt::CTRL | Qt::SHIFT | Qt::META);
#ifndef VK_VOLUME_DOWN
#define VK_VOLUME_DOWN          0xAE
#define VK_VOLUME_UP            0xAF
#endif

#ifndef VK_MEDIA_NEXT_TRACK
#define VK_MEDIA_NEXT_TRACK     0xB0
#define VK_MEDIA_PREV_TRACK     0xB1
#define VK_MEDIA_STOP           0xB2
#define VK_MEDIA_PLAY_PAUSE     0xB3
#endif

#ifndef VK_PAGEUP
#define VK_PAGEUP               0x21
#define VK_PAGEDOWN             0x22
#endif
    switch(key) {
        case Qt::Key_Left: i_vk = VK_LEFT; break;
        case Qt::Key_Right: i_vk = VK_RIGHT; break;
        case Qt::Key_Up: i_vk = VK_UP; break;
        case Qt::Key_Down: i_vk = VK_DOWN; break;
        case Qt::Key_Space: i_vk = VK_SPACE; break;
        case Qt::Key_Escape: i_vk = VK_ESCAPE; break;
        case Qt::Key_Enter: i_vk = VK_RETURN; break;
        case Qt::Key_Return: i_vk = VK_RETURN; break;
        case Qt::Key_F1: i_vk = VK_F1; break;
        case Qt::Key_F2: i_vk = VK_F2; break;
        case Qt::Key_F3: i_vk = VK_F3; break;
        case Qt::Key_F4: i_vk = VK_F4; break;
        case Qt::Key_F5: i_vk = VK_F5; break;
        case Qt::Key_F6: i_vk = VK_F6; break;
        case Qt::Key_F7: i_vk = VK_F7; break;
        case Qt::Key_F8: i_vk = VK_F8; break;
        case Qt::Key_F9: i_vk = VK_F9; break;
        case Qt::Key_F10: i_vk = VK_F10; break;
        case Qt::Key_F11: i_vk = VK_F11; break;
        case Qt::Key_F12: i_vk = VK_F12; break;
        case Qt::Key_PageUp: i_vk = VK_PAGEUP; break;
        case Qt::Key_PageDown: i_vk = VK_PAGEDOWN; break;
        case Qt::Key_Home: i_vk = VK_HOME; break;
        case Qt::Key_End: i_vk = VK_END; break;
        case Qt::Key_Insert: i_vk = VK_INSERT; break;
        case Qt::Key_Delete: i_vk = VK_DELETE; break;
        case Qt::Key_VolumeDown: i_vk = VK_VOLUME_DOWN; break;
        case Qt::Key_VolumeUp: i_vk = VK_VOLUME_UP; break;
        case Qt::Key_MediaTogglePlayPause: i_vk = VK_MEDIA_PLAY_PAUSE; break;
        case Qt::Key_MediaStop: i_vk = VK_MEDIA_STOP; break;
        case Qt::Key_MediaPrevious: i_vk = VK_MEDIA_PREV_TRACK; break;
        case Qt::Key_MediaNext: i_vk = VK_MEDIA_NEXT_TRACK; break;
        default:
            i_vk = toupper( key );
            break;
    }

    if(!RegisterHotKey(NULL, 10, i_mod, i_vk)) {
        hotKey = QKeySequence();
        nativeFilter.setHotKey(hotKey);
        settings.setValue("hotkey", hotKey);
        QMessageBox::warning(this, "Key binding failed", "Binding global hotkey failed.");
    }
#elif LINUX
    auto platform = qApp->platformNativeInterface();

    xcb_connection_t *c = static_cast<xcb_connection_t*>(platform->nativeResourceForWindow("connection", 0));
    xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(c);

    if(!hotKey.isEmpty()) {
        // remove previous bindings from all screens
        xcb_screen_iterator_t iter;
        iter = xcb_setup_roots_iterator (xcb_get_setup (c));
        for (; iter.rem; xcb_screen_next (&iter)) {
            xcb_ungrab_key(c, XCB_GRAB_ANY, iter.data->root, XCB_MOD_MASK_ANY);
        }
    }
    hotKey = hotKey_;
    nativeFilter.setHotKey(hotKey);
    settings.setValue("hotkey", hotKey);

    if(hotKey.isEmpty()) return;

    xcb_keysym_t keysym = GetX11Key(hotKey[0]);
    xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, keysym), keycode;

    if(!keycodes) {
        hotKey = QKeySequence();
        nativeFilter.setHotKey(hotKey);
        settings.setValue("hotkey", hotKey);
        QMessageBox::warning(this, "Key binding failed", "Binding global hotkey failed.");
        free(keysyms);
        return;
    }

    // add bindings for all screens
    xcb_screen_iterator_t iter;
    iter = xcb_setup_roots_iterator (xcb_get_setup (c));
    bool any_failed = false;
    for (; iter.rem; xcb_screen_next (&iter)) {
        int i = 0;
        while(keycodes[i] != XCB_NO_SYMBOL) {
            keycode = keycodes[i];
            for(auto modifier : GetX11Modifier(c, keysyms, hotKey[0])) {
                auto cookie = xcb_grab_key_checked(c, true, iter.data->root,
                    modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC);
                if(xcb_request_check(c, cookie)) {
                    any_failed = true;
                }
            }
            i += 1;
        }
    }
    if(any_failed) {
        QMessageBox::warning(this, "Key binding warning",
            "Warning: Global hotkey binding problem detected. Some other program might have a conflicting "
            "key binding. If the hotkey doesn't work, try closing some programs or using a different hotkey.");
    }
    free(keysyms);
    free(keycodes);
#endif // WIN32 or LINUX
}
Exemplo n.º 3
0
static bool Mapping( intf_thread_t *p_intf )
{
    static const xcb_keysym_t p_x11_modifier_ignored[] = {
        0,
        XK_Num_Lock,
        XK_Scroll_Lock,
        XK_Caps_Lock,
    };

    intf_sys_t *p_sys = p_intf->p_sys;
    bool active = false;

    p_sys->i_map = 0;
    p_sys->p_map = NULL;

    /* Registering of Hotkeys */
    for( const struct hotkey *p_hotkey = p_intf->p_libvlc->p_hotkeys;
            p_hotkey->psz_action != NULL;
            p_hotkey++ )
    {
        char varname[12 + strlen( p_hotkey->psz_action )];
        sprintf( varname, "global-key-%s", p_hotkey->psz_action );

        char *key = var_InheritString( p_intf, varname );
        if( key == NULL )
            continue;

        uint_fast32_t i_vlc_key = vlc_str2keycode( key );
        free( key );
        if( i_vlc_key == KEY_UNSET )
            continue;

        xcb_keycode_t *p_keys = xcb_key_symbols_get_keycode(
                p_sys->p_symbols, GetX11Key( i_vlc_key & ~KEY_MODIFIER ) );
        if( !p_keys )
            continue;

        const unsigned i_modifier = GetX11Modifier( p_sys->p_connection,
                p_sys->p_symbols, i_vlc_key & KEY_MODIFIER );

        const size_t max = sizeof(p_x11_modifier_ignored) /
                sizeof(*p_x11_modifier_ignored);
        for( unsigned int i = 0; i < max; i++ )
        {
            const unsigned i_ignored = GetModifier( p_sys->p_connection,
                    p_sys->p_symbols, p_x11_modifier_ignored[i] );
            if( i != 0 && i_ignored == 0)
                continue;

            hotkey_mapping_t *p_map_old = p_sys->p_map;
            p_sys->p_map = realloc( p_sys->p_map,
                    sizeof(*p_sys->p_map) * (p_sys->i_map+1) );
            if( !p_sys->p_map )
            {
                p_sys->p_map = p_map_old;
                break;
            }
            hotkey_mapping_t *p_map = &p_sys->p_map[p_sys->i_map++];

            p_map->p_keys = p_keys;
            p_map->i_modifier = i_modifier|i_ignored;
            p_map->i_vlc = i_vlc_key;
            active = true;
        }
    }
    return active;
}
bool ZealNativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
    enabled = true;
#ifdef WIN32
    MSG* msg = static_cast<MSG*>(message);

    if(WM_HOTKEY == msg->message && msg->wParam == 10) {
        emit gotHotKey();
        return true;
    }
#elsif LINUX // WIN32 or LINUX
    xcb_generic_event_t* ev = static_cast<xcb_generic_event_t*>(message);
    if(((ev->response_type&127) == XCB_KEY_PRESS || (ev->response_type&127) == XCB_KEY_RELEASE) && !hotKey.isEmpty()) {
        // XCB_KEY_RELEASE must be ignored by Qt because otherwise it causes SIGSEGV in QXcbKeyboard::handleKeyReleaseEvent
        xcb_connection_t  *c = static_cast<xcb_connection_t*>(
              ((QGuiApplication*)QGuiApplication::instance())->
                    platformNativeInterface()->nativeResourceForWindow("connection", 0));
        xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev;

        xcb_key_symbols_t *keysyms = xcb_key_symbols_alloc(c);
        xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, GetX11Key(hotKey[0]));

        bool found = false;
        // found=true means either (a) complete hotkey was pressed, or (b) any of its separate
        // keys was released. We return true in both cases, because key releases while window
        // is not present cause SIGSEGV in QXcbKeyboard::handleKeyReleaseEvent
        if((ev->response_type&127) == XCB_KEY_RELEASE) {
            QList<QPair<int, Qt::Modifier> > modifiers;
            modifiers.append(qMakePair(XK_Alt_L, Qt::ALT));
            modifiers.append(qMakePair(XK_Alt_R, Qt::ALT));
            modifiers.append(qMakePair(XK_Control_L, Qt::CTRL));
            modifiers.append(qMakePair(XK_Control_R, Qt::CTRL));
            modifiers.append(qMakePair(XK_Meta_L, Qt::META));
            modifiers.append(qMakePair(XK_Meta_R, Qt::META));
            for(auto modifier : modifiers) {
                if(!(hotKey[0] & modifier.second)) {
                    continue;
                }
                xcb_keycode_t *mod_keycodes = xcb_key_symbols_get_keycode(keysyms, modifier.first);
                if(mod_keycodes == nullptr) continue;
                int i = 0;
                while(mod_keycodes[i] != XCB_NO_SYMBOL) {
                    if(event->detail == mod_keycodes[i]) {
                        found = true;
                    }
                    i += 1;
                }
                free(mod_keycodes);
            }
        }
        int i = 0;
        while(keycodes[i] != XCB_NO_SYMBOL) {
            if(event->detail == keycodes[i]) {
                bool modifiers_present = true;
                if(hotKey[0] & Qt::ALT) {
                    if(!(event->state & GetModifier(c, keysyms, XK_Alt_L) || event->state & GetModifier(c, keysyms,  XK_Alt_R))) {
                        modifiers_present = false;
                    }
                }
                if(hotKey[0] & Qt::CTRL) {
                    if(!(event->state & GetModifier(c, keysyms, XK_Control_L) || event->state & GetModifier(c, keysyms,  XK_Control_R))) {
                        modifiers_present = false;
                    }
                }
                if(hotKey[0] & Qt::META) {
                    if(!(event->state & GetModifier(c, keysyms, XK_Meta_L) || event->state & GetModifier(c, keysyms,  XK_Meta_R))) {
                        modifiers_present = false;
                    }
                }
                if(hotKey[0] & Qt::SHIFT) {
                    if(!(event->state & GetModifier(c, keysyms, XK_Shift_L) || event->state & GetModifier(c, keysyms,  XK_Shift_R))) {
                        modifiers_present = false;
                    }
                }
                if(enabled && modifiers_present) {
                    xcb_allow_events(c, XCB_ALLOW_ASYNC_KEYBOARD, event->time);
                    if((ev->response_type&127) == XCB_KEY_PRESS) {
                        emit gotHotKey();
                    }
                    found = true;
                } else {
                    if((ev->response_type&127) == XCB_KEY_RELEASE) {
                        found = true;
                    }
                    xcb_allow_events(c, XCB_ALLOW_REPLAY_KEYBOARD, event->time);
                }
                break;
            }
            i += 1;
        }
        free(keysyms);
        free(keycodes);
        if(found) return true;
    }
#endif // WIN32 or LINUX
    return false;
}