diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index a47edf27b..658303906 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -24,6 +24,7 @@ #include "xenia/ui/file_picker.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/virtual_key.h" // Autogenerated by `xb premake`. #include "build/version.h" @@ -93,49 +94,49 @@ bool EmulatorWindow::Initialize() { window_->on_key_down.AddListener([this](KeyEvent* e) { bool handled = true; - switch (e->key_code()) { - case 0x4F: { // o + switch (e->virtual_key()) { + case ui::VirtualKey::kO: { if (e->is_ctrl_pressed()) { FileOpen(); } } break; - case 0x6A: { // numpad * + case ui::VirtualKey::kMultiply: { CpuTimeScalarReset(); } break; - case 0x6D: { // numpad minus + case ui::VirtualKey::kSubtract: { CpuTimeScalarSetHalf(); } break; - case 0x6B: { // numpad plus + case ui::VirtualKey::kAdd: { CpuTimeScalarSetDouble(); } break; - case 0x72: { // F3 + case ui::VirtualKey::kF3: { Profiler::ToggleDisplay(); } break; - case 0x73: { // VK_F4 + case ui::VirtualKey::kF4: { GpuTraceFrame(); } break; - case 0x74: { // VK_F5 + case ui::VirtualKey::kF5: { GpuClearCaches(); } break; - case 0x76: { // VK_F7 + case ui::VirtualKey::kF7: { // Save to file // TODO: Choose path based on user input, or from options // TODO: Spawn a new thread to do this. emulator()->SaveToFile("test.sav"); } break; - case 0x77: { // VK_F8 + case ui::VirtualKey::kF8: { // Restore from file // TODO: Choose path from user // TODO: Spawn a new thread to do this. emulator()->RestoreFromFile("test.sav"); } break; - case 0x7A: { // VK_F11 + case ui::VirtualKey::kF11: { ToggleFullscreen(); } break; - case 0x1B: { // VK_ESCAPE - // Allow users to escape fullscreen (but not enter it). + case ui::VirtualKey::kEscape: { + // Allow users to escape fullscreen (but not enter it). if (window_->is_fullscreen()) { window_->ToggleFullscreen(false); } else { @@ -143,18 +144,18 @@ bool EmulatorWindow::Initialize() { } } break; - case 0x13: { // VK_PAUSE + case ui::VirtualKey::kPause: { CpuBreakIntoDebugger(); } break; - case 0x03: { // VK_CANCEL + case ui::VirtualKey::kCancel: { CpuBreakIntoHostDebugger(); } break; - case 0x70: { // VK_F1 + case ui::VirtualKey::kF1: { ShowHelpWebsite(); } break; - case 0x71: { // VK_F2 + case ui::VirtualKey::kF2: { ShowCommitID(); } break; diff --git a/src/xenia/base/byte_order.h b/src/xenia/base/byte_order.h index abbf41606..1a3c63b2f 100644 --- a/src/xenia/base/byte_order.h +++ b/src/xenia/base/byte_order.h @@ -81,20 +81,23 @@ inline T byte_swap(T value) { template struct endian_store { endian_store() = default; - endian_store(const T& src) { + endian_store(const T& src) { set(src); } + endian_store(const endian_store& other) { set(other); } + operator T() const { return get(); } + + void set(const T& src) { if constexpr (std::endian::native == E) { value = src; } else { value = xe::byte_swap(src); } } - endian_store(const endian_store& other) { value = other.value; } - operator T() const { + void set(const endian_store& other) { value = other.value; } + T get() const { if constexpr (std::endian::native == E) { return value; - } else { - return xe::byte_swap(value); } + return xe::byte_swap(value); } endian_store& operator+=(int a) { diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index a28f6e26b..bf24d4f7d 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -30,6 +30,7 @@ #include "xenia/base/assert.h" #include "xenia/base/cvar.h" #include "xenia/base/profiling.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #if XE_OPTION_PROFILING @@ -112,31 +113,35 @@ void Profiler::ThreadEnter(const char* name) { void Profiler::ThreadExit() { MicroProfileOnThreadExit(); } -bool Profiler::OnKeyDown(int key_code) { +bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { // https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx - switch (key_code) { - case VK_OEM_3: // ` + switch (virtual_key) { + case ui::VirtualKey::kOem3: // ` MicroProfileTogglePause(); return true; #if XE_OPTION_PROFILING_UI - case VK_TAB: + case ui::VirtualKey::kTab: MicroProfileToggleDisplayMode(); return true; - case 0x31: // 1 + case ui::VirtualKey::k1: MicroProfileModKey(1); return true; #endif // XE_OPTION_PROFILING_UI + default: + break; } return false; } -bool Profiler::OnKeyUp(int key_code) { - switch (key_code) { +bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { + switch (virtual_key) { #if XE_OPTION_PROFILING_UI - case 0x31: // 1 + case ui::VirtualKey::k1: MicroProfileModKey(0); return true; #endif // XE_OPTION_PROFILING_UI + default: + break; } return false; } @@ -219,14 +224,14 @@ void Profiler::set_window(ui::Window* window) { // Watch for toggle/mode keys and such. window_->on_key_down.AddListener([](ui::KeyEvent* e) { if (Profiler::is_visible()) { - Profiler::OnKeyDown(e->key_code()); + Profiler::OnKeyDown(e->virtual_key()); e->set_handled(true); window_->Invalidate(); } }); window_->on_key_up.AddListener([](ui::KeyEvent* e) { if (Profiler::is_visible()) { - Profiler::OnKeyUp(e->key_code()); + Profiler::OnKeyUp(e->virtual_key()); e->set_handled(true); window_->Invalidate(); } @@ -257,8 +262,8 @@ void Profiler::Shutdown() {} uint32_t Profiler::GetColor(const char* str) { return 0; } void Profiler::ThreadEnter(const char* name) {} void Profiler::ThreadExit() {} -bool Profiler::OnKeyDown(int key_code) { return false; } -bool Profiler::OnKeyUp(int key_code) { return false; } +bool Profiler::OnKeyDown(ui::VirtualKey virtual_key) { return false; } +bool Profiler::OnKeyUp(ui::VirtualKey virtual_key) { return false; } void Profiler::OnMouseDown(bool left_button, bool right_button) {} void Profiler::OnMouseUp() {} void Profiler::OnMouseMove(int x, int y) {} diff --git a/src/xenia/base/profiling.h b/src/xenia/base/profiling.h index d6cc42d41..a55600d7e 100644 --- a/src/xenia/base/profiling.h +++ b/src/xenia/base/profiling.h @@ -13,6 +13,7 @@ #include #include "xenia/base/string.h" +#include "xenia/ui/virtual_key.h" #if XE_PLATFORM_WIN32 #define XE_OPTION_PROFILING 1 @@ -171,8 +172,8 @@ class Profiler { // Deactivates the calling thread for profiling. static void ThreadExit(); - static bool OnKeyDown(int key_code); - static bool OnKeyUp(int key_code); + static bool OnKeyDown(ui::VirtualKey virtual_key); + static bool OnKeyUp(ui::VirtualKey virtual_key); static void OnMouseDown(bool left_button, bool right_button); static void OnMouseUp(); static void OnMouseMove(int x, int y); diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index f632267fa..cfc82bf2a 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -28,6 +28,7 @@ #include "xenia/memory.h" #include "xenia/ui/file_picker.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" #include "xenia/xbox.h" @@ -135,7 +136,7 @@ bool TraceViewer::Setup() { window_->set_imgui_input_enabled(true); window_->on_key_char.AddListener([&](xe::ui::KeyEvent* e) { - if (e->key_code() == 0x74 /* VK_F5 */) { + if (e->virtual_key() == xe::ui::VirtualKey::kF5) { graphics_system_->ClearCaches(); e->set_handled(true); } diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index 44d8c780c..c1a81f533 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -10,8 +10,8 @@ #include #include #include -#include #include +#include #include "third_party/fmt/include/fmt/format.h" #include "third_party/imgui/imgui.h" @@ -23,6 +23,7 @@ #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/vulkan/vulkan_provider.h" #include "xenia/ui/window.h" @@ -281,44 +282,42 @@ void DrawInputGetState() { ImGui::EndChild(); } -static const std::map::type, - const std::string> - vk_pretty = { - {X_INPUT_GAMEPAD_VK_A, "A"}, - {X_INPUT_GAMEPAD_VK_B, "B"}, - {X_INPUT_GAMEPAD_VK_X, "X"}, - {X_INPUT_GAMEPAD_VK_Y, "Y"}, - {X_INPUT_GAMEPAD_VK_RSHOULDER, "R Shoulder"}, - {X_INPUT_GAMEPAD_VK_LSHOULDER, "L Shoulder"}, - {X_INPUT_GAMEPAD_VK_LTRIGGER, "L Trigger"}, - {X_INPUT_GAMEPAD_VK_RTRIGGER, "R Trigger"}, +static const std::unordered_map kVkPretty = { + {ui::VirtualKey::kXInputPadA, "A"}, + {ui::VirtualKey::kXInputPadB, "B"}, + {ui::VirtualKey::kXInputPadX, "X"}, + {ui::VirtualKey::kXInputPadY, "Y"}, + {ui::VirtualKey::kXInputPadRShoulder, "R Shoulder"}, + {ui::VirtualKey::kXInputPadLShoulder, "L Shoulder"}, + {ui::VirtualKey::kXInputPadLTrigger, "L Trigger"}, + {ui::VirtualKey::kXInputPadRTrigger, "R Trigger"}, - {X_INPUT_GAMEPAD_VK_DPAD_UP, "DPad up"}, - {X_INPUT_GAMEPAD_VK_DPAD_DOWN, "DPad down"}, - {X_INPUT_GAMEPAD_VK_DPAD_LEFT, "DPad left"}, - {X_INPUT_GAMEPAD_VK_DPAD_RIGHT, "DPad right"}, - {X_INPUT_GAMEPAD_VK_START, "Start"}, - {X_INPUT_GAMEPAD_VK_BACK, "Back"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_PRESS, "L Thumb press"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_PRESS, "R Thumb press"}, + {ui::VirtualKey::kXInputPadDpadUp, "DPad up"}, + {ui::VirtualKey::kXInputPadDpadDown, "DPad down"}, + {ui::VirtualKey::kXInputPadDpadLeft, "DPad left"}, + {ui::VirtualKey::kXInputPadDpadRight, "DPad right"}, + {ui::VirtualKey::kXInputPadStart, "Start"}, + {ui::VirtualKey::kXInputPadBack, "Back"}, + {ui::VirtualKey::kXInputPadLThumbPress, "L Thumb press"}, + {ui::VirtualKey::kXInputPadRThumbPress, "R Thumb press"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_UP, "L Thumb up"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_DOWN, "L Thumb down"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_RIGHT, "L Thumb right"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_LEFT, "L Thumb left"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_UPLEFT, "L Thumb up & left"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_UPRIGHT, "L Thumb up & right"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_DOWNRIGHT, "L Thumb down & right"}, - {X_INPUT_GAMEPAD_VK_LTHUMB_DOWNLEFT, "L Thumb down & left"}, + {ui::VirtualKey::kXInputPadLThumbUp, "L Thumb up"}, + {ui::VirtualKey::kXInputPadLThumbDown, "L Thumb down"}, + {ui::VirtualKey::kXInputPadLThumbRight, "L Thumb right"}, + {ui::VirtualKey::kXInputPadLThumbLeft, "L Thumb left"}, + {ui::VirtualKey::kXInputPadLThumbUpLeft, "L Thumb up & left"}, + {ui::VirtualKey::kXInputPadLThumbUpRight, "L Thumb up & right"}, + {ui::VirtualKey::kXInputPadLThumbDownRight, "L Thumb down & right"}, + {ui::VirtualKey::kXInputPadLThumbDownLeft, "L Thumb down & left"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_UP, "R Thumb up"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_DOWN, "R Thumb down"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_RIGHT, "R Thumb right"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_LEFT, "R Thumb left"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_UPLEFT, "R Thumb up & left"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_UPRIGHT, "R Thumb up & right"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_DOWNRIGHT, "R Thumb down & right"}, - {X_INPUT_GAMEPAD_VK_RTHUMB_DOWNLEFT, "R Thumb down & left"}, + {ui::VirtualKey::kXInputPadRThumbUp, "R Thumb up"}, + {ui::VirtualKey::kXInputPadRThumbDown, "R Thumb down"}, + {ui::VirtualKey::kXInputPadRThumbRight, "R Thumb right"}, + {ui::VirtualKey::kXInputPadRThumbLeft, "R Thumb left"}, + {ui::VirtualKey::kXInputPadRThumbUpLeft, "R Thumb up & left"}, + {ui::VirtualKey::kXInputPadRThumbUpRight, "R Thumb up & right"}, + {ui::VirtualKey::kXInputPadRThumbDownRight, "R Thumb down & right"}, + {ui::VirtualKey::kXInputPadRThumbDownLeft, "R Thumb down & left"}, }; void DrawUserInputGetKeystroke(uint32_t user_index, bool poll, @@ -354,10 +353,12 @@ void DrawUserInputGetKeystroke(uint32_t user_index, bool poll, break; } - const auto key_search = vk_pretty.find(stroke.virtual_key); - const auto key = key_search != vk_pretty.end() - ? key_search->second - : fmt::format("0x{:04x}", stroke.virtual_key); + ui::VirtualKey virtual_key = ui::VirtualKey(stroke.virtual_key.get()); + const auto key_search = kVkPretty.find(virtual_key); + std::string key = + key_search != kVkPretty.cend() + ? key_search->second + : fmt::format("0x{:04x}", uint16_t(virtual_key)); event_log.emplace_front(fmt::format( "{:>6} {:>9}ms {:<20} {} {} {}", ImGui::GetFrameCount(), dur, key, diff --git a/src/xenia/hid/input.h b/src/xenia/hid/input.h index 9ebec0108..82202a391 100644 --- a/src/xenia/hid/input.h +++ b/src/xenia/hid/input.h @@ -46,43 +46,7 @@ enum X_INPUT_GAMEPAD_BUTTON { X_INPUT_GAMEPAD_Y = 0x8000, }; -enum X_INPUT_GAMEPAD_VK { - X_INPUT_GAMEPAD_VK_A = 0x5800, - X_INPUT_GAMEPAD_VK_B = 0x5801, - X_INPUT_GAMEPAD_VK_X = 0x5802, - X_INPUT_GAMEPAD_VK_Y = 0x5803, - X_INPUT_GAMEPAD_VK_RSHOULDER = 0x5804, - X_INPUT_GAMEPAD_VK_LSHOULDER = 0x5805, - X_INPUT_GAMEPAD_VK_LTRIGGER = 0x5806, - X_INPUT_GAMEPAD_VK_RTRIGGER = 0x5807, - - X_INPUT_GAMEPAD_VK_DPAD_UP = 0x5810, - X_INPUT_GAMEPAD_VK_DPAD_DOWN = 0x5811, - X_INPUT_GAMEPAD_VK_DPAD_LEFT = 0x5812, - X_INPUT_GAMEPAD_VK_DPAD_RIGHT = 0x5813, - X_INPUT_GAMEPAD_VK_START = 0x5814, - X_INPUT_GAMEPAD_VK_BACK = 0x5815, - X_INPUT_GAMEPAD_VK_LTHUMB_PRESS = 0x5816, - X_INPUT_GAMEPAD_VK_RTHUMB_PRESS = 0x5817, - - X_INPUT_GAMEPAD_VK_LTHUMB_UP = 0x5820, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWN = 0x5821, - X_INPUT_GAMEPAD_VK_LTHUMB_RIGHT = 0x5822, - X_INPUT_GAMEPAD_VK_LTHUMB_LEFT = 0x5823, - X_INPUT_GAMEPAD_VK_LTHUMB_UPLEFT = 0x5824, - X_INPUT_GAMEPAD_VK_LTHUMB_UPRIGHT = 0x5825, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWNRIGHT = 0x5826, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWNLEFT = 0x5827, - - X_INPUT_GAMEPAD_VK_RTHUMB_UP = 0x5830, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWN = 0x5831, - X_INPUT_GAMEPAD_VK_RTHUMB_RIGHT = 0x5832, - X_INPUT_GAMEPAD_VK_RTHUMB_LEFT = 0x5833, - X_INPUT_GAMEPAD_VK_RTHUMB_UPLEFT = 0x5834, - X_INPUT_GAMEPAD_VK_RTHUMB_UPRIGHT = 0x5835, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWNRIGHT = 0x5836, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWNLEFT = 0x5837, -}; +// For VK_PAD, use ui::VirtualKey. enum X_INPUT_KEYSTROKE_FLAGS { X_INPUT_KEYSTROKE_KEYDOWN = 0x0001, diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index 27a00c80d..914f31bb8 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -20,6 +20,7 @@ #include "xenia/base/logging.h" #include "xenia/helper/sdl/sdl_helper.h" #include "xenia/hid/hid_flags.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" // TODO(joellinn) make this path relative to the config folder. @@ -238,48 +239,46 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags, // The order of this list is also the order in which events are send if // multiple buttons change at once. static_assert(sizeof(X_INPUT_GAMEPAD::buttons) == 2); - static constexpr std::array::type, - 34> - vk_lookup = { - // 00 - True buttons from xinput button field - X_INPUT_GAMEPAD_VK_DPAD_UP, - X_INPUT_GAMEPAD_VK_DPAD_DOWN, - X_INPUT_GAMEPAD_VK_DPAD_LEFT, - X_INPUT_GAMEPAD_VK_DPAD_RIGHT, - X_INPUT_GAMEPAD_VK_START, - X_INPUT_GAMEPAD_VK_BACK, - X_INPUT_GAMEPAD_VK_LTHUMB_PRESS, - X_INPUT_GAMEPAD_VK_RTHUMB_PRESS, - X_INPUT_GAMEPAD_VK_LSHOULDER, - X_INPUT_GAMEPAD_VK_RSHOULDER, - 0, /* Guide has no VK */ - 0, /* Unknown */ - X_INPUT_GAMEPAD_VK_A, - X_INPUT_GAMEPAD_VK_B, - X_INPUT_GAMEPAD_VK_X, - X_INPUT_GAMEPAD_VK_Y, - // 16 - Fake buttons generated from analog inputs - X_INPUT_GAMEPAD_VK_LTRIGGER, - X_INPUT_GAMEPAD_VK_RTRIGGER, - // 18 - X_INPUT_GAMEPAD_VK_LTHUMB_UP, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWN, - X_INPUT_GAMEPAD_VK_LTHUMB_RIGHT, - X_INPUT_GAMEPAD_VK_LTHUMB_LEFT, - X_INPUT_GAMEPAD_VK_LTHUMB_UPLEFT, - X_INPUT_GAMEPAD_VK_LTHUMB_UPRIGHT, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWNRIGHT, - X_INPUT_GAMEPAD_VK_LTHUMB_DOWNLEFT, - // 26 - X_INPUT_GAMEPAD_VK_RTHUMB_UP, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWN, - X_INPUT_GAMEPAD_VK_RTHUMB_RIGHT, - X_INPUT_GAMEPAD_VK_RTHUMB_LEFT, - X_INPUT_GAMEPAD_VK_RTHUMB_UPLEFT, - X_INPUT_GAMEPAD_VK_RTHUMB_UPRIGHT, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWNRIGHT, - X_INPUT_GAMEPAD_VK_RTHUMB_DOWNLEFT, - }; + static constexpr std::array kVkLookup = { + // 00 - True buttons from xinput button field + ui::VirtualKey::kXInputPadDpadUp, + ui::VirtualKey::kXInputPadDpadDown, + ui::VirtualKey::kXInputPadDpadLeft, + ui::VirtualKey::kXInputPadDpadRight, + ui::VirtualKey::kXInputPadStart, + ui::VirtualKey::kXInputPadBack, + ui::VirtualKey::kXInputPadLThumbPress, + ui::VirtualKey::kXInputPadRThumbPress, + ui::VirtualKey::kXInputPadLShoulder, + ui::VirtualKey::kXInputPadRShoulder, + ui::VirtualKey::kNone, /* Guide has no VK */ + ui::VirtualKey::kNone, /* Unknown */ + ui::VirtualKey::kXInputPadA, + ui::VirtualKey::kXInputPadB, + ui::VirtualKey::kXInputPadX, + ui::VirtualKey::kXInputPadY, + // 16 - Fake buttons generated from analog inputs + ui::VirtualKey::kXInputPadLTrigger, + ui::VirtualKey::kXInputPadRTrigger, + // 18 + ui::VirtualKey::kXInputPadLThumbUp, + ui::VirtualKey::kXInputPadLThumbDown, + ui::VirtualKey::kXInputPadLThumbRight, + ui::VirtualKey::kXInputPadLThumbLeft, + ui::VirtualKey::kXInputPadLThumbUpLeft, + ui::VirtualKey::kXInputPadLThumbUpRight, + ui::VirtualKey::kXInputPadLThumbDownRight, + ui::VirtualKey::kXInputPadLThumbDownLeft, + // 26 + ui::VirtualKey::kXInputPadRThumbUp, + ui::VirtualKey::kXInputPadRThumbDown, + ui::VirtualKey::kXInputPadRThumbRight, + ui::VirtualKey::kXInputPadRThumbLeft, + ui::VirtualKey::kXInputPadRThumbUpLeft, + ui::VirtualKey::kXInputPadRThumbUpRight, + ui::VirtualKey::kXInputPadRThumbDownRight, + ui::VirtualKey::kXInputPadRThumbDownLeft, + }; auto is_active = this->is_active(); @@ -319,9 +318,9 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags, if (last.repeat_state == RepeatState::Repeating && (last.repeat_time + HID_SDL_REPEAT_RATE < guest_now)) { last.repeat_time = guest_now; - auto vk = vk_lookup.at(last.repeat_butt_idx); - assert_not_zero(vk); - out_keystroke->virtual_key = vk; + ui::VirtualKey vk = kVkLookup.at(last.repeat_butt_idx); + assert_true(vk != ui::VirtualKey::kNone); + out_keystroke->virtual_key = uint16_t(vk); out_keystroke->unicode = 0; out_keystroke->user_index = user_index; out_keystroke->hid_code = 0; @@ -340,17 +339,17 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags, // up before THUMB_LEFT is down. for (auto [clear_pass, i] = std::tuple{true, 0}; i < 2; clear_pass = false, i++) { - for (uint8_t i = 0; i < std::size(vk_lookup); i++) { + for (uint8_t i = 0; i < uint8_t(std::size(kVkLookup)); i++) { auto fbutton = uint64_t(1) << i; if (!(butts_changed & fbutton)) { continue; } - auto vk = vk_lookup.at(i); - if (!vk) { + ui::VirtualKey vk = kVkLookup.at(last.repeat_butt_idx); + if (vk == ui::VirtualKey::kNone) { continue; } - out_keystroke->virtual_key = vk; + out_keystroke->virtual_key = uint16_t(vk); out_keystroke->unicode = 0; out_keystroke->user_index = user_index; out_keystroke->hid_code = 0; diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index 18e192578..ba0b12cdf 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -12,6 +12,7 @@ #include "xenia/base/platform_win.h" #include "xenia/hid/hid_flags.h" #include "xenia/hid/input_system.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" namespace xe { @@ -29,7 +30,7 @@ WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) auto global_lock = global_critical_region_.Acquire(); KeyEvent key; - key.vkey = evt->key_code(); + key.virtual_key = evt->virtual_key(); key.transition = true; key.prev_state = evt->prev_state(); key.repeat_count = evt->repeat_count(); @@ -43,7 +44,7 @@ WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) auto global_lock = global_critical_region_.Acquire(); KeyEvent key; - key.vkey = evt->key_code(); + key.virtual_key = evt->virtual_key(); key.transition = false; key.prev_state = evt->prev_state(); key.repeat_count = evt->repeat_count(); @@ -241,7 +242,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, X_RESULT result = X_ERROR_EMPTY; - uint16_t virtual_key = 0; + ui::VirtualKey xinput_virtual_key = ui::VirtualKey::kNone; uint16_t unicode = 0; uint16_t keystroke_flags = 0; uint8_t hid_code = 0; @@ -258,100 +259,93 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, key_events_.pop(); } - // TODO(DrChat): Some other way to toggle this... - if (IS_KEY_TOGGLED(VK_CAPITAL)) { - // dpad toggled - if (evt.vkey == (0x41)) { - // A - virtual_key = 0x5812; // VK_PAD_DPAD_LEFT - } else if (evt.vkey == (0x44)) { - // D - virtual_key = 0x5813; // VK_PAD_DPAD_RIGHT - } else if (evt.vkey == (0x53)) { - // S - virtual_key = 0x5811; // VK_PAD_DPAD_DOWN - } else if (evt.vkey == (0x57)) { - // W - virtual_key = 0x5810; // VK_PAD_DPAD_UP - } - } else { - // left stick - if (evt.vkey == (0x57)) { - // W - virtual_key = 0x5820; // VK_PAD_LTHUMB_UP - } - if (evt.vkey == (0x53)) { - // S - virtual_key = 0x5821; // VK_PAD_LTHUMB_DOWN - } - if (evt.vkey == (0x44)) { - // D - virtual_key = 0x5822; // VK_PAD_LTHUMB_RIGHT - } - if (evt.vkey == (0x41)) { - // A - virtual_key = 0x5823; // VK_PAD_LTHUMB_LEFT - } + switch (evt.virtual_key) { + case ui::VirtualKey::kOem1: // ; + xinput_virtual_key = ui::VirtualKey::kXInputPadA; + break; + case ui::VirtualKey::kOem7: // ' + xinput_virtual_key = ui::VirtualKey::kXInputPadB; + break; + case ui::VirtualKey::kL: + xinput_virtual_key = ui::VirtualKey::kXInputPadX; + break; + case ui::VirtualKey::kP: + xinput_virtual_key = ui::VirtualKey::kXInputPadY; + break; + case ui::VirtualKey::k3: + xinput_virtual_key = ui::VirtualKey::kXInputPadRShoulder; + break; + case ui::VirtualKey::k1: + xinput_virtual_key = ui::VirtualKey::kXInputPadLShoulder; + break; + case ui::VirtualKey::kQ: + case ui::VirtualKey::kI: + xinput_virtual_key = ui::VirtualKey::kXInputPadLTrigger; + break; + case ui::VirtualKey::kE: + case ui::VirtualKey::kO: + xinput_virtual_key = ui::VirtualKey::kXInputPadRTrigger; + break; + case ui::VirtualKey::kX: + xinput_virtual_key = ui::VirtualKey::kXInputPadStart; + break; + case ui::VirtualKey::kZ: + xinput_virtual_key = ui::VirtualKey::kXInputPadBack; + break; + case ui::VirtualKey::kUp: + xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbUp; + break; + case ui::VirtualKey::kDown: + xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbDown; + break; + case ui::VirtualKey::kRight: + xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbRight; + break; + case ui::VirtualKey::kLeft: + xinput_virtual_key = ui::VirtualKey::kXInputPadRThumbLeft; + break; + default: + // TODO(DrChat): Some other way to toggle this... + if (IS_KEY_TOGGLED(VK_CAPITAL) || IS_KEY_DOWN(VK_SHIFT)) { + // D-pad toggled. + switch (evt.virtual_key) { + case ui::VirtualKey::kW: + xinput_virtual_key = ui::VirtualKey::kXInputPadDpadUp; + break; + case ui::VirtualKey::kS: + xinput_virtual_key = ui::VirtualKey::kXInputPadDpadDown; + break; + case ui::VirtualKey::kA: + xinput_virtual_key = ui::VirtualKey::kXInputPadDpadLeft; + break; + case ui::VirtualKey::kD: + xinput_virtual_key = ui::VirtualKey::kXInputPadDpadRight; + break; + default: + break; + } + } else { + // Left thumbstick. + switch (evt.virtual_key) { + case ui::VirtualKey::kW: + xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbUp; + break; + case ui::VirtualKey::kS: + xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbDown; + break; + case ui::VirtualKey::kA: + xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbLeft; + break; + case ui::VirtualKey::kD: + xinput_virtual_key = ui::VirtualKey::kXInputPadLThumbRight; + break; + default: + break; + } + } } - // Right stick - if (evt.vkey == (0x26)) { - // Up - virtual_key = 0x5830; - } - if (evt.vkey == (0x28)) { - // Down - virtual_key = 0x5831; - } - if (evt.vkey == (0x27)) { - // Right - virtual_key = 0x5832; - } - if (evt.vkey == (0x25)) { - // Left - virtual_key = 0x5833; - } - - if (evt.vkey == (0x4C)) { - // L - virtual_key = 0x5802; // VK_PAD_X - } else if (evt.vkey == (VK_OEM_7)) { - // ' - virtual_key = 0x5801; // VK_PAD_B - } else if (evt.vkey == (VK_OEM_1)) { - // ; - virtual_key = 0x5800; // VK_PAD_A - } else if (evt.vkey == (0x50)) { - // P - virtual_key = 0x5803; // VK_PAD_Y - } - - if (evt.vkey == (0x58)) { - // X - virtual_key = 0x5814; // VK_PAD_START - } - if (evt.vkey == (0x5A)) { - // Z - virtual_key = 0x5815; // VK_PAD_BACK - } - if (evt.vkey == (0x51) || evt.vkey == (0x49)) { - // Q / I - virtual_key = 0x5806; // VK_PAD_LTRIGGER - } - if (evt.vkey == (0x45) || evt.vkey == (0x4F)) { - // E / O - virtual_key = 0x5807; // VK_PAD_RTRIGGER - } - if (evt.vkey == (0x31)) { - // 1 - virtual_key = 0x5805; // VK_PAD_LSHOULDER - } - if (evt.vkey == (0x33)) { - // 3 - virtual_key = 0x5804; // VK_PAD_RSHOULDER - } - - if (virtual_key != 0) { + if (xinput_virtual_key != ui::VirtualKey::kNone) { if (evt.transition == true) { keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_KEYDOWN } else if (evt.transition == false) { @@ -365,7 +359,7 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags, result = X_ERROR_SUCCESS; } - out_keystroke->virtual_key = virtual_key; + out_keystroke->virtual_key = uint16_t(xinput_virtual_key); out_keystroke->unicode = unicode; out_keystroke->flags = keystroke_flags; out_keystroke->user_index = 0; diff --git a/src/xenia/hid/winkey/winkey_input_driver.h b/src/xenia/hid/winkey/winkey_input_driver.h index 2bc923f39..f015b7416 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.h +++ b/src/xenia/hid/winkey/winkey_input_driver.h @@ -14,6 +14,7 @@ #include "xenia/base/mutex.h" #include "xenia/hid/input_driver.h" +#include "xenia/ui/virtual_key.h" namespace xe { namespace hid { @@ -35,7 +36,7 @@ class WinKeyInputDriver : public InputDriver { protected: struct KeyEvent { - int vkey = 0; + ui::VirtualKey virtual_key = ui::VirtualKey::kNone; int repeat_count = 0; bool transition = false; // going up(false) or going down(true) bool prev_state = false; // down(true) or up(false) diff --git a/src/xenia/ui/imgui_drawer.cc b/src/xenia/ui/imgui_drawer.cc index 158c9248a..276cea114 100644 --- a/src/xenia/ui/imgui_drawer.cc +++ b/src/xenia/ui/imgui_drawer.cc @@ -12,6 +12,7 @@ #include "third_party/imgui/imgui.h" #include "xenia/base/assert.h" #include "xenia/base/logging.h" +#include "xenia/base/math.h" #include "xenia/ui/window.h" namespace xe { @@ -107,23 +108,23 @@ void ImGuiDrawer::Initialize() { style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 1.00f, 0.00f, 0.21f); style.Colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); - io.KeyMap[ImGuiKey_Tab] = 0x09; // VK_TAB; - io.KeyMap[ImGuiKey_LeftArrow] = 0x25; - io.KeyMap[ImGuiKey_RightArrow] = 0x27; - io.KeyMap[ImGuiKey_UpArrow] = 0x26; - io.KeyMap[ImGuiKey_DownArrow] = 0x28; - io.KeyMap[ImGuiKey_Home] = 0x24; - io.KeyMap[ImGuiKey_End] = 0x23; - io.KeyMap[ImGuiKey_Delete] = 0x2E; - io.KeyMap[ImGuiKey_Backspace] = 0x08; - io.KeyMap[ImGuiKey_Enter] = 0x0D; - io.KeyMap[ImGuiKey_Escape] = 0x1B; - io.KeyMap[ImGuiKey_A] = 'A'; - io.KeyMap[ImGuiKey_C] = 'C'; - io.KeyMap[ImGuiKey_V] = 'V'; - io.KeyMap[ImGuiKey_X] = 'X'; - io.KeyMap[ImGuiKey_Y] = 'Y'; - io.KeyMap[ImGuiKey_Z] = 'Z'; + io.KeyMap[ImGuiKey_Tab] = int(ui::VirtualKey::kTab); + io.KeyMap[ImGuiKey_LeftArrow] = int(ui::VirtualKey::kLeft); + io.KeyMap[ImGuiKey_RightArrow] = int(ui::VirtualKey::kRight); + io.KeyMap[ImGuiKey_UpArrow] = int(ui::VirtualKey::kUp); + io.KeyMap[ImGuiKey_DownArrow] = int(ui::VirtualKey::kDown); + io.KeyMap[ImGuiKey_Home] = int(ui::VirtualKey::kHome); + io.KeyMap[ImGuiKey_End] = int(ui::VirtualKey::kEnd); + io.KeyMap[ImGuiKey_Delete] = int(ui::VirtualKey::kDelete); + io.KeyMap[ImGuiKey_Backspace] = int(ui::VirtualKey::kBack); + io.KeyMap[ImGuiKey_Enter] = int(ui::VirtualKey::kReturn); + io.KeyMap[ImGuiKey_Escape] = int(ui::VirtualKey::kEscape); + io.KeyMap[ImGuiKey_A] = int(ui::VirtualKey::kA); + io.KeyMap[ImGuiKey_C] = int(ui::VirtualKey::kC); + io.KeyMap[ImGuiKey_V] = int(ui::VirtualKey::kV); + io.KeyMap[ImGuiKey_X] = int(ui::VirtualKey::kX); + io.KeyMap[ImGuiKey_Y] = int(ui::VirtualKey::kY); + io.KeyMap[ImGuiKey_Z] = int(ui::VirtualKey::kZ); } void ImGuiDrawer::SetupFont() { @@ -228,36 +229,16 @@ void ImGuiDrawer::RenderDrawLists() { } } -void ImGuiDrawer::OnKeyDown(KeyEvent* e) { - auto& io = GetIO(); - io.KeysDown[e->key_code()] = true; - switch (e->key_code()) { - case 16: { - io.KeyShift = true; - } break; - case 17: { - io.KeyCtrl = true; - } break; - } -} +void ImGuiDrawer::OnKeyDown(KeyEvent* e) { OnKey(e, true); } -void ImGuiDrawer::OnKeyUp(KeyEvent* e) { - auto& io = GetIO(); - io.KeysDown[e->key_code()] = false; - switch (e->key_code()) { - case 16: { - io.KeyShift = false; - } break; - case 17: { - io.KeyCtrl = false; - } break; - } -} +void ImGuiDrawer::OnKeyUp(KeyEvent* e) { OnKey(e, false); } void ImGuiDrawer::OnKeyChar(KeyEvent* e) { auto& io = GetIO(); - if (e->key_code() > 0 && e->key_code() < 0x10000) { - io.AddInputCharacter(e->key_code()); + // TODO(Triang3l): Accept the Unicode character. + unsigned int character = static_cast(e->virtual_key()); + if (character > 0 && character < 0x10000) { + io.AddInputCharacter(character); e->set_handled(true); } } @@ -327,5 +308,30 @@ void ImGuiDrawer::OnMouseWheel(MouseEvent* e) { io.MouseWheel += float(e->dy() / 120.0f); } +void ImGuiDrawer::OnKey(KeyEvent* e, bool is_down) { + auto& io = GetIO(); + VirtualKey virtual_key = e->virtual_key(); + if (size_t(virtual_key) < xe::countof(io.KeysDown)) { + io.KeysDown[size_t(virtual_key)] = is_down; + } + switch (virtual_key) { + case VirtualKey::kShift: + io.KeyShift = is_down; + break; + case VirtualKey::kControl: + io.KeyCtrl = is_down; + break; + case VirtualKey::kMenu: + // FIXME(Triang3l): Doesn't work in xenia-ui-window-demo. + io.KeyAlt = is_down; + break; + case VirtualKey::kLWin: + io.KeySuper = is_down; + break; + default: + break; + } +} + } // namespace ui } // namespace xe diff --git a/src/xenia/ui/imgui_drawer.h b/src/xenia/ui/imgui_drawer.h index 7163e7a1a..2c370b2aa 100644 --- a/src/xenia/ui/imgui_drawer.h +++ b/src/xenia/ui/imgui_drawer.h @@ -57,6 +57,9 @@ class ImGuiDrawer : public WindowListener { ImGuiContext* internal_state_ = nullptr; std::unique_ptr font_texture_; + + private: + void OnKey(KeyEvent* e, bool is_down); }; } // namespace ui diff --git a/src/xenia/ui/ui_event.h b/src/xenia/ui/ui_event.h index 9fd4734ba..993eda672 100644 --- a/src/xenia/ui/ui_event.h +++ b/src/xenia/ui/ui_event.h @@ -12,6 +12,8 @@ #include +#include "xenia/ui/virtual_key.h" + namespace xe { namespace ui { @@ -42,11 +44,12 @@ class FileDropEvent : public UIEvent { class KeyEvent : public UIEvent { public: - KeyEvent(Window* target, int key_code, int repeat_count, bool prev_state, - bool modifier_shift_pressed, bool modifier_ctrl_pressed, - bool modifier_alt_pressed, bool modifier_super_pressed) + KeyEvent(Window* target, VirtualKey virtual_key, int repeat_count, + bool prev_state, bool modifier_shift_pressed, + bool modifier_ctrl_pressed, bool modifier_alt_pressed, + bool modifier_super_pressed) : UIEvent(target), - key_code_(key_code), + virtual_key_(virtual_key), repeat_count_(repeat_count), prev_state_(prev_state), modifier_shift_pressed_(modifier_shift_pressed), @@ -58,7 +61,7 @@ class KeyEvent : public UIEvent { bool is_handled() const { return handled_; } void set_handled(bool value) { handled_ = value; } - int key_code() const { return key_code_; } + VirtualKey virtual_key() const { return virtual_key_; } int repeat_count() const { return repeat_count_; } bool prev_state() const { return prev_state_; } @@ -70,7 +73,7 @@ class KeyEvent : public UIEvent { private: bool handled_ = false; - int key_code_ = 0; + VirtualKey virtual_key_ = VirtualKey::kNone; int repeat_count_ = 0; bool prev_state_ = false; // Key previously down(true) or up(false) diff --git a/src/xenia/ui/virtual_key.h b/src/xenia/ui/virtual_key.h new file mode 100644 index 000000000..8bda0667a --- /dev/null +++ b/src/xenia/ui/virtual_key.h @@ -0,0 +1,362 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2021 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_VIRTUAL_KEY_H_ +#define XENIA_UI_VIRTUAL_KEY_H_ + +#include + +namespace xe { +namespace ui { + +// Windows and Xbox 360 / XInput virtual key enumeration. +// This is what platform-specific keys should be translated to, for both HID +// keystroke emulation and Xenia-internal UI events. On Windows, the translation +// is a simple cast. +// This is uint16_t as it's WPARAM (which was 16-bit back in Win16 days, where +// virtual key codes were added), and XINPUT_KEYSTROKE stores the virtual key as +// a WORD. In some cases (see kPacket), bits above 16 may be used as well, but +// VK_ on Windows are defined up to 0xFF (0xFE not counting the reserved 0xFF) +// as of Windows SDK 10.0.19041.0, and XInput virtual key codes are 16-bit. +// Base virtual key codes as of _WIN32_WINNT 0x0500 (Windows 2000, which the +// Xbox 360's kernel is based on), virtual key codes added later are marked +// explicitly as such. +enum class VirtualKey : uint16_t { + // Not a valid key - MapVirtualKey returns zero when there is no translation. + kNone, + + kLButton = 0x01, + kRButton = 0x02, + kCancel = 0x03, // Control-break. + kMButton = 0x04, // Not contiguous with kLButton and kRButton. + + kXButton1 = 0x05, // Not contiguous with kLButton and kRButton. + kXButton2 = 0x06, // Not contiguous with kLButton and kRButton. + + kBack = 0x08, // Backspace. + kTab = 0x09, + + kClear = 0x0C, + kReturn = 0x0D, // Enter. + + kShift = 0x10, + kControl = 0x11, // Ctrl. + kMenu = 0x12, // Alt. + kPause = 0x13, + kCapital = 0x14, // Caps Lock. + + kKana = 0x15, + kHangeul = 0x15, // Old name. + kHangul = 0x15, + kImeOn = 0x16, + kJunja = 0x17, + kFinal = 0x18, + kHanja = 0x19, + kKanji = 0x19, + kImeOff = 0x1A, + + kEscape = 0x1B, + + kConvert = 0x1C, + kNonConvert = 0x1D, + kAccept = 0x1E, + kModeChange = 0x1F, + + kSpace = 0x20, + kPrior = 0x21, // Page Up. + kNext = 0x22, // Page Down. + kEnd = 0x23, + kHome = 0x24, + kLeft = 0x25, + kUp = 0x26, + kRight = 0x27, + kDown = 0x28, + kSelect = 0x29, + kPrint = 0x2A, + kExecute = 0x2B, + kSnapshot = 0x2C, + kInsert = 0x2D, + kDelete = 0x2E, + kHelp = 0x2F, + + // Same as ASCII '0' - '9'. + k0 = 0x30, + k1 = 0x31, + k2 = 0x32, + k3 = 0x33, + k4 = 0x34, + k5 = 0x35, + k6 = 0x36, + k7 = 0x37, + k8 = 0x38, + k9 = 0x39, + + // Same as ASCII 'A' - 'Z'. + kA = 0x41, + kB = 0x42, + kC = 0x43, + kD = 0x44, + kE = 0x45, + kF = 0x46, + kG = 0x47, + kH = 0x48, + kI = 0x49, + kJ = 0x4A, + kK = 0x4B, + kL = 0x4C, + kM = 0x4D, + kN = 0x4E, + kO = 0x4F, + kP = 0x50, + kQ = 0x51, + kR = 0x52, + kS = 0x53, + kT = 0x54, + kU = 0x55, + kV = 0x56, + kW = 0x57, + kX = 0x58, + kY = 0x59, + kZ = 0x5A, + + kLWin = 0x5B, + kRWin = 0x5C, + kApps = 0x5D, + + kSleep = 0x5F, + + kNumpad0 = 0x60, + kNumpad1 = 0x61, + kNumpad2 = 0x62, + kNumpad3 = 0x63, + kNumpad4 = 0x64, + kNumpad5 = 0x65, + kNumpad6 = 0x66, + kNumpad7 = 0x67, + kNumpad8 = 0x68, + kNumpad9 = 0x69, + kMultiply = 0x6A, + kAdd = 0x6B, + kSeparator = 0x6C, + kSubtract = 0x6D, + kDecimal = 0x6E, + kDivide = 0x6F, + kF1 = 0x70, + kF2 = 0x71, + kF3 = 0x72, + kF4 = 0x73, + kF5 = 0x74, + kF6 = 0x75, + kF7 = 0x76, + kF8 = 0x77, + kF9 = 0x78, + kF10 = 0x79, + kF11 = 0x7A, + kF12 = 0x7B, + kF13 = 0x7C, + kF14 = 0x7D, + kF15 = 0x7E, + kF16 = 0x7F, + kF17 = 0x80, + kF18 = 0x81, + kF19 = 0x82, + kF20 = 0x83, + kF21 = 0x84, + kF22 = 0x85, + kF23 = 0x86, + kF24 = 0x87, + + // VK_NAVIGATION_* added in _WIN32_WINNT 0x0604, but marked as reserved in + // WinUser.h and not documented on MSDN. + kNavigationView = 0x88, + kNavigationMenu = 0x89, + kNavigationUp = 0x8A, + kNavigationDown = 0x8B, + kNavigationLeft = 0x8C, + kNavigationRight = 0x8D, + kNavigationAccept = 0x8E, + kNavigationCancel = 0x8F, + + kNumLock = 0x90, + kScroll = 0x91, + + // NEC PC-9800 keyboard. + kOemNecEqual = 0x92, // '=' key on the numpad. + + // Fujitsu/OASYS keyboard. + kOemFjJisho = 0x92, // 'Dictionary' key. + kOemFjMasshou = 0x93, // 'Unregister word' key. + kOemFjTouroku = 0x94, // 'Register word' key. + kOemFjLOya = 0x95, // 'Left OYAYUBI' key. + kOemFjROya = 0x96, // 'Right OYAYUBI' key. + + // Left and right Alt, Ctrl and Shift virtual keys. + // On Windows (from WinUser.h): + // "Used only as parameters to GetAsyncKeyState() and GetKeyState(). + // No other API or message will distinguish left and right keys in this way." + kLShift = 0xA0, + kRShift = 0xA1, + kLControl = 0xA2, + kRControl = 0xA3, + kLMenu = 0xA4, + kRMenu = 0xA5, + + kBrowserBack = 0xA6, + kBrowserForward = 0xA7, + kBrowserRefresh = 0xA8, + kBrowserStop = 0xA9, + kBrowserSearch = 0xAA, + kBrowserFavorites = 0xAB, + kBrowserHome = 0xAC, + + kVolumeMute = 0xAD, + kVolumeDown = 0xAE, + kVolumeUp = 0xAF, + kMediaNextTrack = 0xB0, + kMediaPrevTrack = 0xB1, + kMediaStop = 0xB2, + kMediaPlayPause = 0xB3, + kLaunchMail = 0xB4, + kLaunchMediaSelect = 0xB5, + kLaunchApp1 = 0xB6, + kLaunchApp2 = 0xB7, + + kOem1 = 0xBA, // ';:' for the US. + kOemPlus = 0xBB, // '+' for any country. + kOemComma = 0xBC, // ',' for any country. + kOemMinus = 0xBD, // '-' for any country. + kOemPeriod = 0xBE, // '.' for any country. + kOem2 = 0xBF, // '/?' for the US. + kOem3 = 0xC0, // '`~' for the US. + + // VK_GAMEPAD_* (since _WIN32_WINNT 0x0604) virtual key codes are marked as + // reserved in WinUser.h and are mostly not documented on MSDN (with the + // exception of the Xbox Device Portal Remote Input REST API in the "UWP on + // Xbox One" section). + // Xenia uses VK_PAD_* (kXInputPad*) for HID emulation internally instead + // because XInput is the API used for the Xbox 360 controller. + // To avoid confusion between VK_GAMEPAD_* and VK_PAD_*, here they are + // prefixed with kXboxOne and kXInput respectively. + kXboxOneGamepadA = 0xC3, + kXboxOneGamepadB = 0xC4, + kXboxOneGamepadX = 0xC5, + kXboxOneGamepadY = 0xC6, + kXboxOneGamepadRightShoulder = 0xC7, + kXboxOneGamepadLeftShoulder = 0xC8, + kXboxOneGamepadLeftTrigger = 0xC9, + kXboxOneGamepadRightTrigger = 0xCA, + kXboxOneGamepadDpadUp = 0xCB, + kXboxOneGamepadDpadDown = 0xCC, + kXboxOneGamepadDpadLeft = 0xCD, + kXboxOneGamepadDpadRight = 0xCE, + kXboxOneGamepadMenu = 0xCF, + kXboxOneGamepadView = 0xD0, + kXboxOneGamepadLeftThumbstickButton = 0xD1, + kXboxOneGamepadRightThumbstickButton = 0xD2, + kXboxOneGamepadLeftThumbstickUp = 0xD3, + kXboxOneGamepadLeftThumbstickDown = 0xD4, + kXboxOneGamepadLeftThumbstickRight = 0xD5, + kXboxOneGamepadLeftThumbstickLeft = 0xD6, + kXboxOneGamepadRightThumbstickUp = 0xD7, + kXboxOneGamepadRightThumbstickDown = 0xD8, + kXboxOneGamepadRightThumbstickRight = 0xD9, + kXboxOneGamepadRightThumbstickLeft = 0xDA, + + kOem4 = 0xDB, // '[{' for the US. + kOem5 = 0xDC, // '\|' for the US. + kOem6 = 0xDD, // ']}' for the US. + kOem7 = 0xDE, // ''"' for the US. + kOem8 = 0xDF, + + kOemAx = 0xE1, // 'AX' key on the Japanese AX keyboard. + kOem102 = 0xE2, // "<>" or "\|" on the RT 102-key keyboard. + kIcoHelp = 0xE3, // Help key on the Olivetti keyboard (ICO). + kIco00 = 0xE4, // 00 key on the ICO. + + kProcessKey = 0xE5, + + kIcoClear = 0xE6, + + // From MSDN: + // "Used to pass Unicode characters as if they were keystrokes. The VK_PACKET + // key is the low word of a 32-bit Virtual Key value used for non-keyboard + // input methods." + kPacket = 0xE7, + + // Nokia/Ericsson. + kOemReset = 0xE9, + kOemJump = 0xEA, + kOemPa1 = 0xEB, + kOemPa2 = 0xEC, + kOemPa3 = 0xED, + kOemWsCtrl = 0xEE, + kOemCuSel = 0xEF, + kOemAttn = 0xF0, + kOemFinish = 0xF1, + kOemCopy = 0xF2, + kOemAuto = 0xF3, + kOemEnlW = 0xF4, + kOemBackTab = 0xF5, + + kAttn = 0xF6, + kCrSel = 0xF7, + kExSel = 0xF8, + kErEof = 0xF9, + kPlay = 0xFA, + kZoom = 0xFB, + kNoName = 0xFC, + kPa1 = 0xFD, + kOemClear = 0xFE, + + // VK_PAD_* from XInput.h for XInputGetKeystroke. kXInput prefix added to + // distinguish from VK_GAMEPAD_*, added much later for the Xbox One + // controller. + + kXInputPadA = 0x5800, + kXInputPadB = 0x5801, + kXInputPadX = 0x5802, + kXInputPadY = 0x5803, + // RShoulder before LShoulder, not a typo. + kXInputPadRShoulder = 0x5804, + kXInputPadLShoulder = 0x5805, + kXInputPadLTrigger = 0x5806, + kXInputPadRTrigger = 0x5807, + + kXInputPadDpadUp = 0x5810, + kXInputPadDpadDown = 0x5811, + kXInputPadDpadLeft = 0x5812, + kXInputPadDpadRight = 0x5813, + kXInputPadStart = 0x5814, + kXInputPadBack = 0x5815, + kXInputPadLThumbPress = 0x5816, + kXInputPadRThumbPress = 0x5817, + + kXInputPadLThumbUp = 0x5820, + kXInputPadLThumbDown = 0x5821, + kXInputPadLThumbRight = 0x5822, + kXInputPadLThumbLeft = 0x5823, + kXInputPadLThumbUpLeft = 0x5824, + kXInputPadLThumbUpRight = 0x5825, + kXInputPadLThumbDownRight = 0x5826, + kXInputPadLThumbDownLeft = 0x5827, + + kXInputPadRThumbUp = 0x5830, + kXInputPadRThumbDown = 0x5831, + kXInputPadRThumbRight = 0x5832, + kXInputPadRThumbLeft = 0x5833, + kXInputPadRThumbUpLeft = 0x5834, + kXInputPadRThumbUpRight = 0x5835, + kXInputPadRThumbDownRight = 0x5836, + kXInputPadRThumbDownLeft = 0x5837, +}; + +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_VIRTUAL_KEY_H_ diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index 1273b61f0..47a2b874c 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -259,20 +259,21 @@ void Window::OnLostFocus(UIEvent* e) { void Window::OnKeyPress(KeyEvent* e, bool is_down, bool is_char) { if (!is_char) { - switch (e->key_code()) { - case 16: + switch (e->virtual_key()) { + case VirtualKey::kShift: modifier_shift_pressed_ = is_down; break; - case 17: + case VirtualKey::kControl: modifier_cntrl_pressed_ = is_down; break; - // case xx: - // // alt ?? - // modifier_alt_pressed_ = is_down; - // break; - case 91: + case VirtualKey::kMenu: + modifier_alt_pressed_ = is_down; + break; + case VirtualKey::kLWin: modifier_super_pressed_ = is_down; break; + default: + break; } } } diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index a6a05140a..dd191fa7f 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -18,6 +18,7 @@ #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window.h" namespace xe { @@ -92,10 +93,12 @@ int window_demo_main(const std::vector& args) { loop->on_quit.AddListener([&window](xe::ui::UIEvent* e) { window.reset(); }); window->on_key_down.AddListener([](xe::ui::KeyEvent* e) { - switch (e->key_code()) { - case 0x72: { // F3 + switch (e->virtual_key()) { + case VirtualKey::kF3: Profiler::ToggleDisplay(); - } break; + break; + default: + break; } }); diff --git a/src/xenia/ui/window_gtk.cc b/src/xenia/ui/window_gtk.cc index 56248bd2d..9dbeccad5 100644 --- a/src/xenia/ui/window_gtk.cc +++ b/src/xenia/ui/window_gtk.cc @@ -12,6 +12,7 @@ #include "xenia/base/assert.h" #include "xenia/base/logging.h" #include "xenia/base/platform_linux.h" +#include "xenia/ui/virtual_key.h" #include "xenia/ui/window_gtk.h" namespace xe { @@ -350,9 +351,10 @@ bool GTKWindow::HandleKeyboard(GdkEventKey* event) { bool ctrl_pressed = modifiers & GDK_CONTROL_MASK; bool alt_pressed = modifiers & GDK_META_MASK; bool super_pressed = modifiers & GDK_SUPER_MASK; - auto e = - KeyEvent(this, event->hardware_keycode, 1, event->type == GDK_KEY_RELEASE, - shift_pressed, ctrl_pressed, alt_pressed, super_pressed); + // TODO(Triang3l): event->hardware_keycode to VirtualKey translation. + auto e = KeyEvent(this, VirtualKey(event->hardware_keycode), 1, + event->type == GDK_KEY_RELEASE, shift_pressed, ctrl_pressed, + alt_pressed, super_pressed); switch (event->type) { case GDK_KEY_PRESS: OnKeyDown(&e); diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index 954502364..c5bfc780a 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -17,6 +17,7 @@ #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/platform_win.h" +#include "xenia/ui/virtual_key.h" namespace xe { namespace ui { @@ -706,7 +707,7 @@ bool Win32Window::HandleMouse(UINT message, WPARAM wParam, LPARAM lParam) { bool Win32Window::HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam) { auto e = KeyEvent( - this, static_cast(wParam), lParam & 0xFFFF0000, !!(lParam & 0x2), + this, VirtualKey(wParam), lParam & 0xFFFF0000, !!(lParam & 0x2), !!(GetKeyState(VK_SHIFT) & 0x80), !!(GetKeyState(VK_CONTROL) & 0x80), !!(GetKeyState(VK_MENU) & 0x80), !!(GetKeyState(VK_LWIN) & 0x80)); switch (message) {