diff options
Diffstat (limited to 'dinput')
| -rw-r--r-- | dinput/keybinding-worker.cpp | 166 | ||||
| -rw-r--r-- | dinput/keybinding-worker.hpp | 3 | 
2 files changed, 92 insertions, 77 deletions
| diff --git a/dinput/keybinding-worker.cpp b/dinput/keybinding-worker.cpp index 9c2b06d4..8ef99921 100644 --- a/dinput/keybinding-worker.cpp +++ b/dinput/keybinding-worker.cpp @@ -114,83 +114,13 @@ void KeybindingWorker::run()              if (!receivers.empty())              { -                /* There are some problems reported on various forums -                 * with regard to key-up events. But that's what I dug up: -                 * -                 * https://www.gamedev.net/forums/topic/633011-keyboard-getdevicedata-buffered-never-releases-keys/ -                 * -                 * "Over in the xna forums (http://xboxforums.create.msdn.com/forums/p/108722/642144.aspx#642144) -                 *  we discovered this behavior is caused by calling Unacquire in your event processing loop. -                 *  Funnily enough only the keyboard seems to be affected." -                 * -                 * Key-up events work on my end. -                 */ - -                { -                    DWORD sz = num_keyboard_states; -                    const HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0); - -                    if (hr != DI_OK) -                    { -                        qDebug() << "Tracker::run GetDeviceData function failed!" << hr; -                        Sleep(25); -                        continue; -                    } -                    else -                    { -                        for (unsigned k = 0; k < sz; k++) -                        { -                            const unsigned idx = keyboard_states[k].dwOfs & 0xff; // defensive programming -                            const bool held = !!(keyboard_states[k].dwData & 0x80); - -                            switch (idx) -                            { -                            case DIK_LCONTROL: -                            case DIK_LSHIFT: -                            case DIK_LALT: -                            case DIK_RCONTROL: -                            case DIK_RSHIFT: -                            case DIK_RALT: -                            case DIK_LWIN: -                            case DIK_RWIN: -                                break; -                            default: -                            { -                                Key k; -                                k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; -                                k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; -                                k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; -                                k.keycode = idx; -                                k.held = held; - -                                for (auto& r : receivers) -                                    (*r)(k); -                                break; -                            } -                            } -                            keystate[idx] = held; -                        } -                    } -                } - -                { -                    using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; - -                    joy_fn f = [&](const QString& guid, int idx, bool held) { -                        Key k; -                        k.keycode = idx; -                        k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; -                        k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; -                        k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; -                        k.guid = guid; -                        k.held = held; - -                        for (auto& r : receivers) -                            (*r)(k); -                    }; - -                    joy_ctx.poll(f); -                } +                bool ok = true; + +                ok &= run_keyboard_nolock(); +                ok &= run_joystick_nolock(); + +                if (!ok) +                    Sleep(500);              }          } @@ -198,6 +128,88 @@ void KeybindingWorker::run()      }  } +bool KeybindingWorker::run_keyboard_nolock() +{ +    /* There are some problems reported on various forums +     * with regard to key-up events. But that's what I dug up: +     * +     * https://www.gamedev.net/forums/topic/633011-keyboard-getdevicedata-buffered-never-releases-keys/ +     * +     * "Over in the xna forums (http://xboxforums.create.msdn.com/forums/p/108722/642144.aspx#642144) +     *  we discovered this behavior is caused by calling Unacquire in your event processing loop. +     *  Funnily enough only the keyboard seems to be affected." +     * +     * Key-up events work on my end. +     */ + +    DWORD sz = num_keyboard_states; +    const HRESULT hr = dinkeyboard->GetDeviceData(sizeof(*keyboard_states), keyboard_states, &sz, 0); + +    if (hr != DI_OK) +    { +        eval_once(qDebug() << "dinput: keyboard GetDeviceData failed" << hr); +        return false; +    } + +    for (unsigned k = 0; k < sz; k++) +    { +        const unsigned idx = keyboard_states[k].dwOfs & 0xff; // defensive programming +        const bool held = !!(keyboard_states[k].dwData & 0x80); + +        switch (idx) +        { +        case DIK_LCONTROL: +        case DIK_LSHIFT: +        case DIK_LALT: +        case DIK_RCONTROL: +        case DIK_RSHIFT: +        case DIK_RALT: +        case DIK_LWIN: +        case DIK_RWIN: +            break; +        default: +        { +            Key k; +            k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; +            k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; +            k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; +            k.keycode = idx; +            k.held = held; + +            for (auto& r : receivers) +                (*r)(k); +        } +            break; +        } + +        keystate[idx] = held; +    } + +    return true; +} + +bool KeybindingWorker::run_joystick_nolock() +{ +    using joy_fn = std::function<void(const QString& guid, int idx, bool held)>; + +    joy_fn f = [&](const QString& guid, int idx, bool held) { +        Key k; +        k.keycode = idx; +        k.shift = keystate[DIK_LSHIFT] | keystate[DIK_RSHIFT]; +        k.alt = keystate[DIK_LALT] | keystate[DIK_RALT]; +        k.ctrl = keystate[DIK_LCONTROL] | keystate[DIK_RCONTROL]; +        k.guid = guid; +        k.held = held; + +        for (auto& r : receivers) +            (*r)(k); +    }; + +    joy_ctx.poll(f); + +    return true; +} +  KeybindingWorker::fun* KeybindingWorker::_add_receiver(fun& receiver)  {      QMutexLocker l(&mtx); diff --git a/dinput/keybinding-worker.hpp b/dinput/keybinding-worker.hpp index 6b7d6882..9d067c10 100644 --- a/dinput/keybinding-worker.hpp +++ b/dinput/keybinding-worker.hpp @@ -53,6 +53,9 @@ private:      bool old_keystate[256] {};      void run() override; +    bool run_keyboard_nolock(); +    bool run_joystick_nolock(); +      bool init();      KeybindingWorker(); | 
