Fix some input behavior that got lost in the previous commits.

This commit is contained in:
Henrik Rydgård
2026-06-24 21:48:20 +02:00
parent b01812e671
commit 02e9deb232
8 changed files with 71 additions and 98 deletions
+16
View File
@@ -3,6 +3,8 @@
#include <functional>
#include <string>
#include "Common/Common.h"
// The Native App API.
//
// Implement these functions and you've got a native app. These are called
@@ -17,6 +19,19 @@ struct AxisInput;
class GraphicsContext;
class AudioBackend;
enum class KeyModifier {
NONE = 0,
LCTRL = 1,
RCTRL = 2,
LSHIFT = 4,
RSHIFT = 8,
LALT = 16,
RALT = 32,
LMETA = 64,
RMETA = 128,
};
ENUM_CLASS_BITOPS(KeyModifier);
// The first function to get called, just write strings to the two pointers.
// This might get called multiple times in some implementations, you must be able to handle that.
void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, bool *landscape, std::string *version);
@@ -55,6 +70,7 @@ bool NativeKey(const KeyInput &key);
void NativeAxis(const AxisInput *axis, size_t count);
void NativeAccelerometer(float tiltX, float tiltY, float tiltZ);
void NativeMouseDelta(float dx, float dy);
KeyModifier NativeGetKeyModifiers(); // TODO: Move this to input handling somewhere? But don't want it in each backend...
// Called when it's process a frame, including rendering. If the device can keep up, this
// will be called sixty times per second. Main thread.
+1 -1
View File
@@ -80,7 +80,7 @@ enum class InputMode {
Keyboard = 1,
Mouse = 2,
Other = 4,
ImDebuggerToggle = 8, // ugly hack
ImDebuggerToggle = 8, // ugly hack. debugger and pause goes through.
};
ENUM_CLASS_BITOPS(InputMode);
+1 -1
View File
@@ -339,7 +339,7 @@ float GetTargetScore(const Point2D &originPos, int originIndex, const View *orig
const float vertOverlap = VerticalOverlap(origin->GetBounds(), destination->GetBounds());
if (horizOverlap == 1.0f && vertOverlap == 1.0f) {
if (direction != FocusMove::PREV_PAGE && direction != FocusMove::NEXT_PAGE) {
INFO_LOG(Log::UI, "Contain overlap: %s, %s", origin->Tag().c_str(), destination->Tag().c_str());
// INFO_LOG(Log::UI, "Contain overlap: %s, %s", origin->Tag().c_str(), destination->Tag().c_str());
return 0.0f;
}
}
+12 -30
View File
@@ -21,6 +21,7 @@
using namespace std::placeholders;
#include "Common/System/NativeApp.h"
#include "Common/Render/TextureAtlas.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
#include "Common/File/FileUtil.h"
@@ -1190,36 +1191,11 @@ InputMode EmuScreen::PassInputToMapper() const {
return modes;
}
bool EmuScreen::UnsyncKey(const KeyInput &key) {
// Update imgui modifier flags
if (key.flags & (KeyInputFlags::DOWN | KeyInputFlags::UP)) {
bool down = (key.flags & KeyInputFlags::DOWN) != 0;
switch (key.keyCode) {
case NKCODE_CTRL_LEFT: keyCtrlLeft_ = down; break;
case NKCODE_CTRL_RIGHT: keyCtrlRight_ = down; break;
case NKCODE_SHIFT_LEFT: keyShiftLeft_ = down; break;
case NKCODE_SHIFT_RIGHT: keyShiftRight_ = down; break;
case NKCODE_ALT_LEFT: keyAltLeft_ = down; break;
case NKCODE_ALT_RIGHT: keyAltRight_ = down; break;
default: break;
}
}
return UIScreen::UnsyncKey(key);
}
void EmuScreen::UnsyncAxis(const AxisInput *axes, size_t count) {
if (UI::IsFocusMovementEnabled()) {
// Otherwise no use for axis events - we send them to the control mapper.
return UIScreen::UnsyncAxis(axes, count);
}
return g_controlMapper.Axis(axes, count);
}
bool EmuScreen::key(const KeyInput &key) {
bool retval = UIScreen::key(key);
if (!retval && g_Config.bShowImDebugger && imguiInited_) {
ImGui_ImplPlatform_KeyEvent(key);
}
@@ -1948,9 +1924,15 @@ void EmuScreen::runImDebugger() {
// Update keyboard modifiers.
auto &io = ImGui::GetIO();
io.AddKeyEvent(ImGuiMod_Ctrl, keyCtrlLeft_ || keyCtrlRight_);
io.AddKeyEvent(ImGuiMod_Shift, keyShiftLeft_ || keyShiftRight_);
io.AddKeyEvent(ImGuiMod_Alt, keyAltLeft_ || keyAltRight_);
KeyModifier modifiers = NativeGetKeyModifiers();
const bool keyCtrl = (modifiers & KeyModifier::LCTRL) || (modifiers & KeyModifier::RCTRL);
const bool keyShift = (modifiers & KeyModifier::LSHIFT) || (modifiers & KeyModifier::RSHIFT);
const bool keyAlt = (modifiers & KeyModifier::LALT) || (modifiers & KeyModifier::RALT);
io.AddKeyEvent(ImGuiMod_Ctrl, keyCtrl);
io.AddKeyEvent(ImGuiMod_Shift, keyShift);
io.AddKeyEvent(ImGuiMod_Alt, keyAlt);
// io.AddKeyEvent(ImGuiMod_Super, e.key.super);
ImGuiID dockID = ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode);
-5
View File
@@ -54,11 +54,6 @@ public:
InputMode PassInputToMapper() const override;
// Note: Unlike your average boring UIScreen, here we override the Unsync* functions
// to get minimal latency and full control. We forward to UIScreen when needed.
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput *axes, size_t count) override;
// We also need to do some special handling of queued UI events to handle closing the chat window.
bool key(const KeyInput &key) override;
void touch(const TouchInput &key) override;
+33 -43
View File
@@ -1369,19 +1369,11 @@ static void ProcessWheelRelease(InputKeyCode keyCode, double now, bool keyPress)
}
}
enum class Modifier {
NONE = 0,
LCTRL = 1,
RCTRL = 2,
LSHIFT = 4,
RSHIFT = 8,
LALT = 16,
RALT = 32,
LMETA = 64,
RMETA = 128,
};
ENUM_CLASS_BITOPS(Modifier);
static Modifier g_modifiersPressed{};
KeyModifier g_modifiersPressed{};
KeyModifier NativeGetKeyModifiers() {
return g_modifiersPressed;
}
bool NativeKey(const KeyInput &key) {
double now = time_now_d();
@@ -1435,6 +1427,13 @@ bool NativeKey(const KeyInput &key) {
}
#endif
HLEPlugins::SetKey(key.keyCode, (key.flags & KeyInputFlags::DOWN) ? 1 : 0);
// Handle releases of mousewheel keys.
if ((key.flags & KeyInputFlags::DOWN) && key.deviceId == DEVICE_ID_MOUSE && (key.keyCode == NKCODE_EXT_MOUSEWHEEL_UP || key.keyCode == NKCODE_EXT_MOUSEWHEEL_DOWN)) {
ProcessWheelRelease(key.keyCode, now, true);
}
if (!g_screenManager) {
return false;
}
@@ -1479,40 +1478,31 @@ bool NativeKey(const KeyInput &key) {
g_controlMapper.Key(key);
}
// Handle releases of mousewheel keys.
if ((key.flags & KeyInputFlags::DOWN) && key.deviceId == DEVICE_ID_MOUSE && (key.keyCode == NKCODE_EXT_MOUSEWHEEL_UP || key.keyCode == NKCODE_EXT_MOUSEWHEEL_DOWN)) {
ProcessWheelRelease(key.keyCode, now, true);
}
HLEPlugins::SetKey(key.keyCode, (key.flags & KeyInputFlags::DOWN) ? 1 : 0);
// Track and update modifiers.
// Track modifier keys.
if (key.flags & KeyInputFlags::DOWN) {
switch (key.keyCode) {
case NKCODE_CTRL_LEFT: g_modifiersPressed |= Modifier::LCTRL; break;
case NKCODE_CTRL_RIGHT: g_modifiersPressed |= Modifier::RCTRL; break;
case NKCODE_SHIFT_LEFT: g_modifiersPressed |= Modifier::LSHIFT; break;
case NKCODE_SHIFT_RIGHT: g_modifiersPressed |= Modifier::RSHIFT; break;
case NKCODE_ALT_LEFT: g_modifiersPressed |= Modifier::LALT; break;
case NKCODE_ALT_RIGHT: g_modifiersPressed |= Modifier::RALT; break;
case NKCODE_META_LEFT: g_modifiersPressed |= Modifier::LMETA; break;
case NKCODE_META_RIGHT: g_modifiersPressed |= Modifier::RMETA; break;
case NKCODE_CTRL_LEFT: g_modifiersPressed |= KeyModifier::LCTRL; break;
case NKCODE_CTRL_RIGHT: g_modifiersPressed |= KeyModifier::RCTRL; break;
case NKCODE_SHIFT_LEFT: g_modifiersPressed |= KeyModifier::LSHIFT; break;
case NKCODE_SHIFT_RIGHT: g_modifiersPressed |= KeyModifier::RSHIFT; break;
case NKCODE_ALT_LEFT: g_modifiersPressed |= KeyModifier::LALT; break;
case NKCODE_ALT_RIGHT: g_modifiersPressed |= KeyModifier::RALT; break;
case NKCODE_META_LEFT: g_modifiersPressed |= KeyModifier::LMETA; break;
case NKCODE_META_RIGHT: g_modifiersPressed |= KeyModifier::RMETA; break;
default:
break;
}
}
if (key.flags & KeyInputFlags::UP) {
switch (key.keyCode) {
case NKCODE_CTRL_LEFT: g_modifiersPressed &= ~Modifier::LCTRL; break;
case NKCODE_CTRL_RIGHT: g_modifiersPressed &= ~Modifier::RCTRL; break;
case NKCODE_SHIFT_LEFT: g_modifiersPressed &= ~Modifier::LSHIFT; break;
case NKCODE_SHIFT_RIGHT: g_modifiersPressed &= ~Modifier::RSHIFT; break;
case NKCODE_ALT_LEFT: g_modifiersPressed &= ~Modifier::LALT; break;
case NKCODE_ALT_RIGHT: g_modifiersPressed &= ~Modifier::RALT; break;
case NKCODE_META_LEFT: g_modifiersPressed &= ~Modifier::LMETA; break;
case NKCODE_META_RIGHT: g_modifiersPressed &= ~Modifier::RMETA; break;
case NKCODE_CTRL_LEFT: g_modifiersPressed &= ~KeyModifier::LCTRL; break;
case NKCODE_CTRL_RIGHT: g_modifiersPressed &= ~KeyModifier::RCTRL; break;
case NKCODE_SHIFT_LEFT: g_modifiersPressed &= ~KeyModifier::LSHIFT; break;
case NKCODE_SHIFT_RIGHT: g_modifiersPressed &= ~KeyModifier::RSHIFT; break;
case NKCODE_ALT_LEFT: g_modifiersPressed &= ~KeyModifier::LALT; break;
case NKCODE_ALT_RIGHT: g_modifiersPressed &= ~KeyModifier::RALT; break;
case NKCODE_META_LEFT: g_modifiersPressed &= ~KeyModifier::LMETA; break;
case NKCODE_META_RIGHT: g_modifiersPressed &= ~KeyModifier::RMETA; break;
default:
break;
}
@@ -1520,16 +1510,16 @@ bool NativeKey(const KeyInput &key) {
KeyInputFlags modifierFlags{};
if (g_modifiersPressed & (Modifier::LCTRL | Modifier::RCTRL)) {
if (g_modifiersPressed & (KeyModifier::LCTRL | KeyModifier::RCTRL)) {
modifierFlags |= KeyInputFlags::MOD_CTRL;
}
if (g_modifiersPressed & (Modifier::LSHIFT | Modifier::RSHIFT)) {
if (g_modifiersPressed & (KeyModifier::LSHIFT | KeyModifier::RSHIFT)) {
modifierFlags |= KeyInputFlags::MOD_SHIFT;
}
if (g_modifiersPressed & (Modifier::LALT | Modifier::RALT)) {
if (g_modifiersPressed & (KeyModifier::LALT | KeyModifier::RALT)) {
modifierFlags |= KeyInputFlags::MOD_ALT;
}
if (g_modifiersPressed & (Modifier::LMETA | Modifier::RMETA)) {
if (g_modifiersPressed & (KeyModifier::LMETA | KeyModifier::RMETA)) {
modifierFlags |= KeyInputFlags::MOD_META;
}
@@ -1561,7 +1551,7 @@ void NativeAxis(const AxisInput *axes, size_t count) {
return;
}
if (g_screenManager->PassInputToMapper() & InputMode::Other) {
if (g_screenManager->PassInputToMapper() & (InputMode::Other | InputMode::ImDebuggerToggle)) {
g_controlMapper.Axis(axes, count);
}
+4 -14
View File
@@ -335,6 +335,10 @@ void GamePauseScreen::update() {
UpdateUIState(UISTATE_PAUSEMENU);
UIScreen::update();
if (g_controlMapper.PollPauseTrigger()) {
TriggerFinish(DR_BACK);
}
if (finishNextFrame_) {
TriggerFinish(finishNextFrameResult_);
finishNextFrame_ = false;
@@ -376,20 +380,6 @@ GamePauseScreen::~GamePauseScreen() {
__DisplaySetWasPaused();
}
bool GamePauseScreen::UnsyncKey(const KeyInput &key) {
bool retval = UIScreen::UnsyncKey(key);
retval = g_controlMapper.Key(key) || retval;
if (g_controlMapper.PollPauseTrigger()) {
TriggerFinish(DR_BACK);
}
return retval;
}
void GamePauseScreen::UnsyncAxis(const AxisInput *axes, size_t count) {
UIScreen::UnsyncAxis(axes, count);
g_controlMapper.Axis(axes, count);
}
void GamePauseScreen::OnVKey(VirtKey virtualKeyCode, bool down) {
// Simple de-bounce using createdTime_, just to be safe.
if (down && virtualKeyCode == VIRTKEY_PAUSE && time_now_d() > createdTime_ + 0.1) {
+4 -4
View File
@@ -38,6 +38,10 @@ public:
const char *tag() const override { return "GamePause"; }
InputMode PassInputToMapper() const override {
return InputMode::ImDebuggerToggle;
}
protected:
void CreateViews() override;
void update() override;
@@ -45,10 +49,6 @@ protected:
ViewLayoutMode LayoutMode() const override {
return ViewLayoutMode::ApplyInsets;
}
// For processing of certain mapped keys.
bool UnsyncKey(const KeyInput &key) override;
void UnsyncAxis(const AxisInput *axes, size_t count) override;
void OnVKey(VirtKey virtualKeyCode, bool down) override;
private: