Merge pull request #400 from DrChat/winkey_fixes

Winkey fixes
This commit is contained in:
Ben Vanik 2015-08-18 17:15:21 -07:00
commit 76efd13301
5 changed files with 174 additions and 99 deletions

View File

@ -13,5 +13,6 @@ project("xenia-hid-winkey")
defines({
})
includedirs({
project_root.."/third_party/elemental-forms/src",
})
local_platform_files()

View File

@ -10,14 +10,41 @@
#include "xenia/hid/winkey/winkey_input_driver.h"
#include "xenia/base/platform_win.h"
#include "xenia/emulator.h"
#include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_system.h"
#include "xenia/ui/window.h"
namespace xe {
namespace hid {
namespace winkey {
WinKeyInputDriver::WinKeyInputDriver(InputSystem* input_system)
: InputDriver(input_system), packet_number_(1) {}
: InputDriver(input_system), packet_number_(1) {
// Register a key listener.
input_system_->emulator()->display_window()->on_key_down.AddListener(
[this](ui::KeyEvent* evt) {
std::lock_guard<std::mutex> lock(key_event_mutex_);
KeyEvent key;
key.vkey = evt->key_code();
key.transition = true;
key.prev_state = evt->prev_state();
key.repeat_count = evt->repeat_count();
key_events_.push(key);
});
input_system_->emulator()->display_window()->on_key_up.AddListener(
[this](ui::KeyEvent* evt) {
std::lock_guard<std::mutex> lock(key_event_mutex_);
KeyEvent key;
key.vkey = evt->key_code();
key.transition = false;
key.prev_state = evt->prev_state();
key.repeat_count = evt->repeat_count();
key_events_.push(key);
});
}
WinKeyInputDriver::~WinKeyInputDriver() = default;
@ -64,6 +91,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
int16_t thumb_rx = 0;
int16_t thumb_ry = 0;
if (input_system_->emulator()->display_window()->has_focus()) {
if (IS_KEY_TOGGLED(VK_CAPITAL)) {
// dpad toggled
if (IS_KEY_DOWN(0x41)) {
@ -145,6 +173,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
// X
buttons |= 0x0010; // XINPUT_GAMEPAD_START
}
}
out_state->packet_number = packet_number_;
out_state->gamepad.buttons = buttons;
@ -180,84 +209,107 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
uint16_t keystroke_flags = 0;
uint8_t hid_code = 0;
// Pop from the queue.
key_event_mutex_.lock();
if (key_events_.size() == 0) {
key_event_mutex_.unlock();
// No keys!
return X_ERROR_EMPTY;
}
KeyEvent evt = key_events_.front();
key_events_.pop();
key_event_mutex_.unlock();
// TODO: Some other way to toggle this...
if (IS_KEY_TOGGLED(VK_CAPITAL)) {
// dpad toggled
if (IS_KEY_DOWN(0x41)) {
if (evt.vkey == (0x41)) {
// A
virtual_key = 0x5812; // VK_PAD_DPAD_LEFT
} else if (IS_KEY_DOWN(0x44)) {
} else if (evt.vkey == (0x44)) {
// D
virtual_key = 0x5813; // VK_PAD_DPAD_RIGHT
} else if (IS_KEY_DOWN(0x53)) {
} else if (evt.vkey == (0x53)) {
// S
virtual_key = 0x5811; // VK_PAD_DPAD_DOWN
} else if (IS_KEY_DOWN(0x57)) {
} else if (evt.vkey == (0x57)) {
// W
virtual_key = 0x5810; // VK_PAD_DPAD_UP
}
} else {
// left stick
if (IS_KEY_DOWN(0x57)) {
if (evt.vkey == (0x57)) {
// W
virtual_key = 0x5820; // VK_PAD_LTHUMB_UP
}
if (IS_KEY_DOWN(0x53)) {
if (evt.vkey == (0x53)) {
// S
virtual_key = 0x5821; // VK_PAD_LTHUMB_DOWN
}
if (IS_KEY_DOWN(0x44)) {
if (evt.vkey == (0x44)) {
// D
virtual_key = 0x5822; // VK_PAD_LTHUMB_RIGHT
}
if (IS_KEY_DOWN(0x41)) {
if (evt.vkey == (0x41)) {
// A
virtual_key = 0x5823; // VK_PAD_LTHUMB_LEFT
}
}
// Right stick
if (IS_KEY_DOWN(0x26)) {
if (evt.vkey == (0x26)) {
// Up
virtual_key = 0x5830;
}
if (IS_KEY_DOWN(0x28)) {
if (evt.vkey == (0x28)) {
// Down
virtual_key = 0x5831;
}
if (IS_KEY_DOWN(0x27)) {
if (evt.vkey == (0x27)) {
// Right
virtual_key = 0x5832;
}
if (IS_KEY_DOWN(0x25)) {
if (evt.vkey == (0x25)) {
// Left
virtual_key = 0x5833;
}
if (IS_KEY_DOWN(0x4C)) {
if (evt.vkey == (0x4C)) {
// L
virtual_key = 0x5802; // VK_PAD_X
} else if (IS_KEY_DOWN(VK_OEM_7)) {
} else if (evt.vkey == (VK_OEM_7)) {
// '
virtual_key = 0x5801; // VK_PAD_B
} else if (IS_KEY_DOWN(VK_OEM_1)) {
} else if (evt.vkey == (VK_OEM_1)) {
// ;
virtual_key = 0x5800; // VK_PAD_A
} else if (IS_KEY_DOWN(0x50)) {
} else if (evt.vkey == (0x50)) {
// P
virtual_key = 0x5803; // VK_PAD_Y
}
if (IS_KEY_DOWN(0x58)) {
if (evt.vkey == (0x58)) {
// X
virtual_key = 0x5814; // VK_PAD_START
}
if (IS_KEY_DOWN(0x5A)) {
if (evt.vkey == (0x5A)) {
// Z
virtual_key = 0x5815; // VK_PAD_BACK
}
if (virtual_key != 0) {
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_DOWN
if (evt.transition == true) {
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN
} else if (evt.transition == false) {
keystroke_flags |= 0x0002; // XINPUT_KEYSTROKE_KEYUP
}
if (evt.prev_state == evt.transition) {
keystroke_flags |= 0x0004; // XINPUT_KEYSTROKE_REPEAT
}
result = X_ERROR_SUCCESS;
}

View File

@ -10,6 +10,9 @@
#ifndef XENIA_HID_WINKEY_WINKEY_INPUT_DRIVER_H_
#define XENIA_HID_WINKEY_WINKEY_INPUT_DRIVER_H_
#include <mutex>
#include <queue>
#include "xenia/hid/input_driver.h"
namespace xe {
@ -31,6 +34,15 @@ class WinKeyInputDriver : public InputDriver {
X_INPUT_KEYSTROKE* out_keystroke) override;
protected:
struct KeyEvent {
int vkey = 0;
int repeat_count = 0;
bool transition = false; // going up(false) or going down(true)
bool prev_state = false; // down(true) or up(false)
};
std::queue<KeyEvent> key_events_;
std::mutex key_event_mutex_;
uint32_t packet_number_;
};

View File

@ -28,8 +28,11 @@ class UIEvent {
class KeyEvent : public UIEvent {
public:
KeyEvent(Window* target, int key_code)
: UIEvent(target), key_code_(key_code) {}
KeyEvent(Window* target, int key_code, int repeat_count, bool prev_state)
: UIEvent(target),
key_code_(key_code),
repeat_count_(repeat_count),
prev_state_(prev_state) {}
~KeyEvent() override = default;
bool is_handled() const { return handled_; }
@ -37,9 +40,15 @@ class KeyEvent : public UIEvent {
int key_code() const { return key_code_; }
int repeat_count() const { return repeat_count_; }
bool prev_state() const { return prev_state_; }
private:
bool handled_ = false;
int key_code_ = 0;
int repeat_count_ = 0;
bool prev_state_ = false; // Key previously down(true) or up(false)
};
class MouseEvent : public UIEvent {

View File

@ -503,7 +503,8 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) {
}
bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) {
auto e = KeyEvent(this, static_cast<int>(wParam));
auto e = KeyEvent(this, static_cast<int>(wParam), lParam & 0xFFFF0000,
!!(lParam & 0x2));
switch (message) {
case WM_KEYDOWN:
OnKeyDown(&e);