[UI] Image post-processing and full presentation/window rework

[GPU] Add FXAA post-processing
[UI] Add FidelityFX FSR and CAS post-processing
[UI] Add blue noise dithering from 10bpc to 8bpc
[GPU] Apply the DC PWL gamma ramp closer to the spec, supporting fully white color
[UI] Allow the GPU CP thread to present on the host directly, bypassing the UI thread OS paint event
[UI] Allow variable refresh rate (or tearing)
[UI] Present the newest frame (restart) on DXGI
[UI] Replace GraphicsContext with a far more advanced Presenter with more coherent surface connection and UI overlay state management
[UI] Connect presentation to windows via the Surface class, not native window handles
[Vulkan] Switch to simpler Vulkan setup with no instance/device separation due to interdependencies and to pass fewer objects around
[Vulkan] Lower the minimum required Vulkan version to 1.0
[UI/GPU] Various cleanup, mainly ComPtr usage
[UI] Support per-monitor DPI awareness v2 on Windows
[UI] DPI-scale Dear ImGui
[UI] Replace the remaining non-detachable window delegates with unified window event and input listeners
[UI] Allow listeners to safely destroy or close the window, and to register/unregister listeners without use-after-free and the ABA problem
[UI] Explicit Z ordering of input listeners and UI overlays, top-down for input, bottom-up for drawing
[UI] Add explicit window lifecycle phases
[UI] Replace Window virtual functions with explicit desired state, its application, actual state, its feedback
[UI] GTK: Apply the initial size to the drawing area
[UI] Limit internal UI frame rate to that of the monitor
[UI] Hide the cursor using a timer instead of polling due to no repeated UI thread paints with GPU CP thread presentation, and only within the window
This commit is contained in:
Triang3l
2022-01-29 13:22:03 +03:00
parent 372bdd3ec9
commit fe3f0f26e4
428 changed files with 75942 additions and 18360 deletions

View File

@@ -2,7 +2,7 @@
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
@@ -24,10 +24,14 @@
#include "xenia/base/threading.h"
#include "xenia/hid/hid_flags.h"
#include "xenia/hid/input_system.h"
#include "xenia/ui/imgui_dialog.h"
#include "xenia/ui/imgui_drawer.h"
#include "xenia/ui/immediate_drawer.h"
#include "xenia/ui/presenter.h"
#include "xenia/ui/virtual_key.h"
#include "xenia/ui/vulkan/vulkan_provider.h"
#include "xenia/ui/window.h"
#include "xenia/ui/window_listener.h"
#include "xenia/ui/windowed_app.h"
// Available input drivers:
@@ -59,12 +63,41 @@ class HidDemoApp final : public ui::WindowedApp {
bool OnInitialize() override;
private:
enum : size_t {
kZOrderHidInput,
kZOrderImGui,
};
class HidDemoWindowListener final : public ui::WindowListener {
public:
explicit HidDemoWindowListener(ui::WindowedAppContext& app_context)
: app_context_(app_context) {}
void OnClosing(ui::UIEvent& e) override { app_context_.QuitFromUIThread(); }
private:
ui::WindowedAppContext& app_context_;
};
class HidDemoDialog final : public ui::ImGuiDialog {
public:
explicit HidDemoDialog(ui::ImGuiDrawer* imgui_drawer, HidDemoApp& app)
: ui::ImGuiDialog(imgui_drawer), app_(app) {}
protected:
void OnDraw(ImGuiIO& io) override;
private:
HidDemoApp& app_;
};
explicit HidDemoApp(ui::WindowedAppContext& app_context)
: ui::WindowedApp(app_context, "xenia-hid-demo") {}
: ui::WindowedApp(app_context, "xenia-hid-demo"),
window_listener_(app_context) {}
static std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
ui::Window* window);
void Draw(ImGuiIO& io);
void DrawUserInputGetState(uint32_t user_index) const;
void DrawInputGetState() const;
void DrawUserInputGetKeystroke(uint32_t user_index, bool poll,
@@ -72,9 +105,15 @@ class HidDemoApp final : public ui::WindowedApp {
void DrawInputGetKeystroke(bool poll, bool hide_repeats,
bool clear_log) const;
HidDemoWindowListener window_listener_;
std::unique_ptr<ui::GraphicsProvider> graphics_provider_;
std::unique_ptr<ui::Window> window_;
std::unique_ptr<InputSystem> input_system_;
std::unique_ptr<ui::Presenter> presenter_;
std::unique_ptr<ui::ImmediateDrawer> immediate_drawer_;
std::unique_ptr<ui::ImGuiDrawer> imgui_drawer_;
std::unique_ptr<HidDemoDialog> demo_dialog_;
bool is_active_ = true;
};
@@ -82,71 +121,64 @@ std::vector<std::unique_ptr<hid::InputDriver>> HidDemoApp::CreateInputDrivers(
ui::Window* window) {
std::vector<std::unique_ptr<hid::InputDriver>> drivers;
if (cvars::hid.compare("nop") == 0) {
drivers.emplace_back(xe::hid::nop::Create(window));
drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput));
} else if (cvars::hid.compare("sdl") == 0) {
auto driver = xe::hid::sdl::Create(window);
auto driver = xe::hid::sdl::Create(window, kZOrderHidInput);
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
#if XE_PLATFORM_WIN32
} else if (cvars::hid.compare("winkey") == 0) {
auto driver = xe::hid::winkey::Create(window);
auto driver = xe::hid::winkey::Create(window, kZOrderHidInput);
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
} else if (cvars::hid.compare("xinput") == 0) {
auto driver = xe::hid::xinput::Create(window);
auto driver = xe::hid::xinput::Create(window, kZOrderHidInput);
if (XSUCCEEDED(driver->Setup())) {
drivers.emplace_back(std::move(driver));
}
#endif // XE_PLATFORM_WIN32
} else {
auto sdl_driver = xe::hid::sdl::Create(window);
auto sdl_driver = xe::hid::sdl::Create(window, kZOrderHidInput);
if (sdl_driver && XSUCCEEDED(sdl_driver->Setup())) {
drivers.emplace_back(std::move(sdl_driver));
}
#if XE_PLATFORM_WIN32
auto xinput_driver = xe::hid::xinput::Create(window);
auto xinput_driver = xe::hid::xinput::Create(window, kZOrderHidInput);
if (xinput_driver && XSUCCEEDED(xinput_driver->Setup())) {
drivers.emplace_back(std::move(xinput_driver));
}
auto winkey_driver = xe::hid::winkey::Create(window);
auto winkey_driver = xe::hid::winkey::Create(window, kZOrderHidInput);
if (winkey_driver && XSUCCEEDED(winkey_driver->Setup())) {
drivers.emplace_back(std::move(winkey_driver));
}
#endif // XE_PLATFORM_WIN32
if (drivers.empty()) {
// Fallback to nop if none created.
drivers.emplace_back(xe::hid::nop::Create(window));
drivers.emplace_back(xe::hid::nop::Create(window, kZOrderHidInput));
}
}
return drivers;
}
bool HidDemoApp::OnInitialize() {
// Create graphics provider that provides the context for the window.
graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create();
// Create the graphics provider that provides the presenter for the window.
graphics_provider_ = xe::ui::vulkan::VulkanProvider::Create(true);
if (!graphics_provider_) {
XELOGE("Failed to initialize the graphics provider");
return false;
}
// Create the window.
window_ = xe::ui::Window::Create(app_context(), GetName());
if (!window_->Initialize()) {
XELOGE("Failed to initialize main window");
// Create and configure the window.
window_ = xe::ui::Window::Create(app_context(), GetName(),
COL_WIDTH_STATE + COL_WIDTH_STROKE,
ROW_HEIGHT_GENERAL + 500);
window_->AddListener(&window_listener_);
if (!window_->Open()) {
XELOGE("Failed to open the main window");
return false;
}
window_->on_closed.AddListener([this](xe::ui::UIEvent* e) {
XELOGI("User-initiated death!");
app_context().QuitFromUIThread();
});
// Initial size setting, done here so that it knows the menu exists.
window_->Resize(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL + 500);
// Create the graphics context for the window. The window will finish
// initialization with the context (loading resources, etc).
window_->set_context(graphics_provider_->CreateContext(window_.get()));
// Initialize input system and all drivers.
input_system_ = std::make_unique<xe::hid::InputSystem>(window_.get());
@@ -157,71 +189,83 @@ bool HidDemoApp::OnInitialize() {
input_system_->AddDriver(std::move(driver));
}
window_->Invalidate();
window_->set_imgui_input_enabled(true);
window_->on_painting.AddListener([this](xe::ui::UIEvent* e) {
auto& io = window_->imgui_drawer()->GetIO();
const ImGuiWindowFlags wflags =
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoScrollbar;
ImGui::Begin("General", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(0, 0));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL));
ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str());
ImGui::Checkbox("is_active", &is_active_);
}
ImGui::End();
ImGui::Begin("GetState()", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL));
static bool enable_GetState = false;
ImGui::Checkbox("Active", &enable_GetState);
ImGui::SameLine();
ImGui::Checkbox("Guide Button", &cvars::guide_button);
if (enable_GetState) {
ImGui::Spacing();
DrawInputGetState();
}
}
ImGui::End();
ImGui::Begin("GetKeystroke()", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL));
static bool enable_GetKeystroke = false;
static bool hide_repeats = false;
ImGui::Checkbox("Active", &enable_GetKeystroke);
ImGui::SameLine();
ImGui::Checkbox("Hide repeats", &hide_repeats);
ImGui::SameLine();
const bool clear_log = ImGui::Button("Clear");
ImGui::Spacing();
DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log);
}
ImGui::End();
// Continuous paint.
window_->Invalidate();
});
// Setup drawing to the window.
presenter_ = graphics_provider_->CreatePresenter();
if (!presenter_) {
XELOGE("Failed to initialize the presenter");
return false;
}
immediate_drawer_ = graphics_provider_->CreateImmediateDrawer();
if (!immediate_drawer_) {
XELOGE("Failed to initialize the immediate drawer");
return false;
}
immediate_drawer_->SetPresenter(presenter_.get());
imgui_drawer_ =
std::make_unique<ui::ImGuiDrawer>(window_.get(), kZOrderImGui);
imgui_drawer_->SetPresenterAndImmediateDrawer(presenter_.get(),
immediate_drawer_.get());
demo_dialog_ = std::make_unique<HidDemoDialog>(imgui_drawer_.get(), *this);
window_->SetPresenter(presenter_.get());
return true;
}
void HidDemoApp::HidDemoDialog::OnDraw(ImGuiIO& io) { app_.Draw(io); }
void HidDemoApp::Draw(ImGuiIO& io) {
const ImGuiWindowFlags wflags =
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoScrollbar;
ImGui::Begin("General", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(0, 0));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STATE + COL_WIDTH_STROKE, ROW_HEIGHT_GENERAL));
ImGui::Text("Input System (hid) = \"%s\"", cvars::hid.c_str());
ImGui::Checkbox("is_active", &is_active_);
}
ImGui::End();
ImGui::Begin("GetState()", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(0, ROW_HEIGHT_GENERAL));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STATE, io.DisplaySize.y - ROW_HEIGHT_GENERAL));
static bool enable_GetState = false;
ImGui::Checkbox("Active", &enable_GetState);
ImGui::SameLine();
ImGui::Checkbox("Guide Button", &cvars::guide_button);
if (enable_GetState) {
ImGui::Spacing();
DrawInputGetState();
}
}
ImGui::End();
ImGui::Begin("GetKeystroke()", nullptr, wflags);
{
ImGui::SetWindowPos(ImVec2(COL_WIDTH_STATE, ROW_HEIGHT_GENERAL));
ImGui::SetWindowSize(
ImVec2(COL_WIDTH_STROKE, io.DisplaySize.y - ROW_HEIGHT_GENERAL));
static bool enable_GetKeystroke = false;
static bool hide_repeats = false;
ImGui::Checkbox("Active", &enable_GetKeystroke);
ImGui::SameLine();
ImGui::Checkbox("Hide repeats", &hide_repeats);
ImGui::SameLine();
const bool clear_log = ImGui::Button("Clear");
ImGui::Spacing();
DrawInputGetKeystroke(enable_GetKeystroke, hide_repeats, clear_log);
}
ImGui::End();
}
void HidDemoApp::DrawUserInputGetState(uint32_t user_index) const {
ImGui::Text("User %u:", user_index);

View File

@@ -1,20 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/hid/input_driver.h"
namespace xe {
namespace hid {
InputDriver::InputDriver(xe::ui::Window* window) : window_(window) {}
InputDriver::~InputDriver() = default;
} // namespace hid
} // namespace xe

View File

@@ -10,6 +10,7 @@
#ifndef XENIA_HID_INPUT_DRIVER_H_
#define XENIA_HID_INPUT_DRIVER_H_
#include <cstddef>
#include <functional>
#include "xenia/hid/input.h"
@@ -29,7 +30,7 @@ class InputSystem;
class InputDriver {
public:
virtual ~InputDriver();
virtual ~InputDriver() = default;
virtual X_STATUS Setup() = 0;
@@ -45,18 +46,21 @@ class InputDriver {
is_active_callback_ = is_active_callback;
}
private:
xe::ui::Window* window_ = nullptr;
std::function<bool()> is_active_callback_ = nullptr;
protected:
explicit InputDriver(xe::ui::Window* window);
explicit InputDriver(xe::ui::Window* window, size_t window_z_order)
: window_(window), window_z_order_(window_z_order) {}
xe::ui::Window* window() const { return window_; }
size_t window_z_order() const { return window_z_order_; }
bool is_active() const {
return !is_active_callback_ || is_active_callback_();
}
private:
xe::ui::Window* window_;
size_t window_z_order_;
std::function<bool()> is_active_callback_ = nullptr;
};
} // namespace hid

View File

@@ -15,8 +15,9 @@ namespace xe {
namespace hid {
namespace nop {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window) {
return std::make_unique<NopInputDriver>(window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order) {
return std::make_unique<NopInputDriver>(window, window_z_order);
}
} // namespace nop

View File

@@ -18,7 +18,8 @@ namespace xe {
namespace hid {
namespace nop {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order);
} // namespace nop
} // namespace hid

View File

@@ -15,7 +15,8 @@ namespace xe {
namespace hid {
namespace nop {
NopInputDriver::NopInputDriver(xe::ui::Window* window) : InputDriver(window) {}
NopInputDriver::NopInputDriver(xe::ui::Window* window, size_t window_z_order)
: InputDriver(window, window_z_order) {}
NopInputDriver::~NopInputDriver() = default;

View File

@@ -16,9 +16,9 @@ namespace xe {
namespace hid {
namespace nop {
class NopInputDriver : public InputDriver {
class NopInputDriver final : public InputDriver {
public:
explicit NopInputDriver(xe::ui::Window* window);
explicit NopInputDriver(xe::ui::Window* window, size_t window_z_order);
~NopInputDriver() override;
X_STATUS Setup() override;

View File

@@ -41,7 +41,6 @@ project("xenia-hid-demo")
filter("platforms:Linux")
links({
"SDL2",
"vulkan",
"X11",
"xcb",
"X11-xcb",

View File

@@ -15,8 +15,9 @@ namespace xe {
namespace hid {
namespace sdl {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window) {
return std::make_unique<SDLInputDriver>(window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order) {
return std::make_unique<SDLInputDriver>(window, window_z_order);
}
} // namespace sdl

View File

@@ -18,7 +18,8 @@ namespace xe {
namespace hid {
namespace sdl {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order);
} // namespace sdl
} // namespace hid

View File

@@ -33,8 +33,8 @@ namespace xe {
namespace hid {
namespace sdl {
SDLInputDriver::SDLInputDriver(xe::ui::Window* window)
: InputDriver(window),
SDLInputDriver::SDLInputDriver(xe::ui::Window* window, size_t window_z_order)
: InputDriver(window, window_z_order),
sdl_events_initialized_(false),
sdl_gamecontroller_initialized_(false),
sdl_events_unflushed_(0),

View File

@@ -28,9 +28,9 @@ namespace xe {
namespace hid {
namespace sdl {
class SDLInputDriver : public InputDriver {
class SDLInputDriver final : public InputDriver {
public:
explicit SDLInputDriver(xe::ui::Window* window);
explicit SDLInputDriver(xe::ui::Window* window, size_t window_z_order);
~SDLInputDriver() override;
X_STATUS Setup() override;
@@ -42,7 +42,7 @@ class SDLInputDriver : public InputDriver {
X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) override;
protected:
private:
struct ControllerState {
SDL_GameController* sdl;
X_INPUT_CAPABILITIES caps;
@@ -65,7 +65,6 @@ class SDLInputDriver : public InputDriver {
uint32_t repeat_time;
};
protected:
void HandleEvent(const SDL_Event& event);
void OnControllerDeviceAdded(const SDL_Event& event);
void OnControllerDeviceRemoved(const SDL_Event& event);
@@ -80,7 +79,6 @@ class SDLInputDriver : public InputDriver {
void UpdateXCapabilities(ControllerState& state);
void QueueControllerUpdate();
protected:
bool sdl_events_initialized_;
bool sdl_gamecontroller_initialized_;
int sdl_events_unflushed_;

View File

@@ -15,8 +15,9 @@ namespace xe {
namespace hid {
namespace winkey {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window) {
return std::make_unique<WinKeyInputDriver>(window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order) {
return std::make_unique<WinKeyInputDriver>(window, window_z_order);
}
} // namespace winkey

View File

@@ -18,7 +18,8 @@ namespace xe {
namespace hid {
namespace winkey {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order);
} // namespace winkey
} // namespace hid

View File

@@ -80,47 +80,22 @@ void WinKeyInputDriver::ParseKeyBinding(ui::VirtualKey output_key,
}
}
WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window)
: InputDriver(window), packet_number_(1) {
// Register a key listener.
window->on_key_down.AddListener([this](ui::KeyEvent* evt) {
if (!is_active()) {
return;
}
auto global_lock = global_critical_region_.Acquire();
KeyEvent key;
key.virtual_key = evt->virtual_key();
key.transition = true;
key.prev_state = evt->prev_state();
key.repeat_count = evt->repeat_count();
key_events_.push(key);
});
window->on_key_up.AddListener([this](ui::KeyEvent* evt) {
if (!is_active()) {
return;
}
auto global_lock = global_critical_region_.Acquire();
KeyEvent key;
key.virtual_key = evt->virtual_key();
key.transition = false;
key.prev_state = evt->prev_state();
key.repeat_count = evt->repeat_count();
key_events_.push(key);
});
WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window,
size_t window_z_order)
: InputDriver(window, window_z_order), window_input_listener_(*this) {
#define XE_HID_WINKEY_BINDING(button, description, cvar_name, \
cvar_default_value) \
ParseKeyBinding(xe::ui::VirtualKey::kXInputPad##button, description, \
cvars::cvar_name);
#include "winkey_binding_table.inc"
#undef XE_HID_WINKEY_BINDING
window->AddInputListener(&window_input_listener_, window_z_order);
}
WinKeyInputDriver::~WinKeyInputDriver() = default;
WinKeyInputDriver::~WinKeyInputDriver() {
window()->RemoveInputListener(&window_input_listener_);
}
X_STATUS WinKeyInputDriver::Setup() { return X_STATUS_SUCCESS; }
@@ -162,7 +137,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
int16_t thumb_rx = 0;
int16_t thumb_ry = 0;
if (window()->has_focus() && is_active()) {
if (window()->HasFocus() && is_active()) {
bool capital = IsKeyToggled(VK_CAPITAL) || IsKeyDown(VK_SHIFT);
for (const KeyBinding& b : key_bindings_) {
if (((b.lowercase == b.uppercase) || (b.lowercase && !capital) ||
@@ -331,6 +306,29 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
return result;
}
void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyDown(ui::KeyEvent& e) {
driver_.OnKey(e, true);
}
void WinKeyInputDriver::WinKeyWindowInputListener::OnKeyUp(ui::KeyEvent& e) {
driver_.OnKey(e, false);
}
void WinKeyInputDriver::OnKey(ui::KeyEvent& e, bool is_down) {
if (!is_active()) {
return;
}
KeyEvent key;
key.virtual_key = e.virtual_key();
key.transition = is_down;
key.prev_state = e.prev_state();
key.repeat_count = e.repeat_count();
auto global_lock = global_critical_region_.Acquire();
key_events_.push(key);
}
} // namespace winkey
} // namespace hid
} // namespace xe

View File

@@ -20,9 +20,9 @@ namespace xe {
namespace hid {
namespace winkey {
class WinKeyInputDriver : public InputDriver {
class WinKeyInputDriver final : public InputDriver {
public:
explicit WinKeyInputDriver(xe::ui::Window* window);
explicit WinKeyInputDriver(xe::ui::Window* window, size_t window_z_order);
~WinKeyInputDriver() override;
X_STATUS Setup() override;
@@ -49,15 +49,31 @@ class WinKeyInputDriver : public InputDriver {
bool lowercase = false;
};
xe::global_critical_region global_critical_region_;
std::queue<KeyEvent> key_events_;
std::vector<KeyBinding> key_bindings_;
class WinKeyWindowInputListener final : public ui::WindowInputListener {
public:
explicit WinKeyWindowInputListener(WinKeyInputDriver& driver)
: driver_(driver) {}
uint32_t packet_number_;
void OnKeyDown(ui::KeyEvent& e) override;
void OnKeyUp(ui::KeyEvent& e) override;
private:
WinKeyInputDriver& driver_;
};
void ParseKeyBinding(ui::VirtualKey virtual_key,
const std::string_view description,
const std::string_view binding);
void OnKey(ui::KeyEvent& e, bool is_down);
WinKeyWindowInputListener window_input_listener_;
xe::global_critical_region global_critical_region_;
std::queue<KeyEvent> key_events_;
std::vector<KeyBinding> key_bindings_;
uint32_t packet_number_ = 1;
};
} // namespace winkey

View File

@@ -15,8 +15,9 @@ namespace xe {
namespace hid {
namespace xinput {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window) {
return std::make_unique<XInputInputDriver>(window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order) {
return std::make_unique<XInputInputDriver>(window, window_z_order);
}
} // namespace xinput

View File

@@ -18,7 +18,8 @@ namespace xe {
namespace hid {
namespace xinput {
std::unique_ptr<InputDriver> Create(xe::ui::Window* window);
std::unique_ptr<InputDriver> Create(xe::ui::Window* window,
size_t window_z_order);
} // namespace xinput
} // namespace hid

View File

@@ -21,8 +21,9 @@ namespace xe {
namespace hid {
namespace xinput {
XInputInputDriver::XInputInputDriver(xe::ui::Window* window)
: InputDriver(window),
XInputInputDriver::XInputInputDriver(xe::ui::Window* window,
size_t window_z_order)
: InputDriver(window, window_z_order),
module_(nullptr),
XInputGetCapabilities_(nullptr),
XInputGetState_(nullptr),

View File

@@ -16,9 +16,9 @@ namespace xe {
namespace hid {
namespace xinput {
class XInputInputDriver : public InputDriver {
class XInputInputDriver final : public InputDriver {
public:
explicit XInputInputDriver(xe::ui::Window* window);
explicit XInputInputDriver(xe::ui::Window* window, size_t window_z_order);
~XInputInputDriver() override;
X_STATUS Setup() override;
@@ -30,7 +30,7 @@ class XInputInputDriver : public InputDriver {
X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags,
X_INPUT_KEYSTROKE* out_keystroke) override;
protected:
private:
void* module_;
void* XInputGetCapabilities_;
void* XInputGetState_;