Gesture control: Prevent pressing touch buttons while performing a gesture.

This commit is contained in:
Henrik Rydgård committed 2026-02-06 13:10:20 +01:00
1 parent fb88dbbbbf
commit 801d379f74
5 files changed
+51 -17

No files matched your search

+1 -1
View File
@@ -691,7 +691,7 @@ static const ConfigSetting gestureControlSettings[] = {
ConfigSetting("DoubleTapGesture", SETTING(g_Config.gestureControls[0], iDoubleTapGesture), 0, CfgFlag::PER_GAME),
ConfigSetting("GestureControlEnabled", SETTING(g_Config.gestureControls[0], bGestureControlEnabled), false, CfgFlag::PER_GAME),
ConfigSetting("AnalogGesture", SETTING(g_Config.gestureControls[0], bAnalogGesture), false, CfgFlag::PER_GAME),
ConfigSetting("AnalogGestureSensibility", SETTING(g_Config.gestureControls[0], fAnalogGestureSensibility), 1.0f, CfgFlag::PER_GAME),
ConfigSetting("AnalogGestureSensibility", SETTING(g_Config.gestureControls[0], fAnalogGestureSensitivity), 1.0f, CfgFlag::PER_GAME),
};
static const ConfigSetting graphicsSettings[] = {
+1 -1
View File
@@ -156,7 +156,7 @@ struct GestureControlConfig : public ConfigBlock {
float fSwipeSmoothing = 0.5f;
int iDoubleTapGesture = 0;
bool bAnalogGesture = false;
float fAnalogGestureSensibility = 1.0f;
float fAnalogGestureSensitivity = 1.0f;
bool CanResetToDefault() const override { return true; }
bool ResetToDefault(std::string_view blockName) override;
+1 -1
View File
@@ -2054,7 +2054,7 @@ void GestureMappingScreen::CreateGestureTab(UI::LinearLayout *vert, int zoneInde
vert->Add(new ItemHeader(co->T("Analog Stick")));
vert->Add(new CheckBox(&zone.bAnalogGesture, co->T("Enable analog stick gesture")));
vert->Add(new PopupSliderChoiceFloat(&zone.fAnalogGestureSensibility, 0.01f, 5.0f, 1.0f, co->T("Sensitivity"), 0.01f, screenManager(), "x"))->SetEnabledPtr(&zone.bAnalogGesture);
vert->Add(new PopupSliderChoiceFloat(&zone.fAnalogGestureSensitivity, 0.01f, 5.0f, 1.0f, co->T("Sensitivity"), 0.01f, screenManager(), "x"))->SetEnabledPtr(&zone.bAnalogGesture);
}
RestoreSettingsScreen::RestoreSettingsScreen(std::string_view title)
+46 -13
View File
@@ -43,6 +43,7 @@ static float g_gamepadOpacity;
static double g_lastTouch;
MultiTouchButton *primaryButton[TOUCH_MAX_POINTERS]{};
std::set<int> g_activeGesturePointers;
void GamepadUpdateOpacity(float force) {
if (force >= 0.0f) {
@@ -122,11 +123,18 @@ bool MultiTouchButton::Touch(const TouchInput &input) {
}
if (input.flags & TouchInputFlags::MOVE) {
if (!(input.flags & TouchInputFlags::MOUSE) || input.buttons) {
bool ignorePress = false;
if (g_activeGesturePointers.count(input.id)) {
// Don't start a button touch if dragging and this pointer is already being used for a gesture.
ignorePress = true;
}
if (bounds_.Contains(input.x, input.y) && !(analogPointerMask & (1 << input.id))) {
if (CanGlide() && !primaryButton[input.id]) {
primaryButton[input.id] = this;
if (!ignorePress) {
if (CanGlide() && !primaryButton[input.id]) {
primaryButton[input.id] = this;
}
pointerDownMask_ |= 1 << input.id;
}
pointerDownMask_ |= 1 << input.id;
} else if (primaryButton[input.id] != this) {
pointerDownMask_ &= ~(1 << input.id);
}
@@ -322,16 +330,23 @@ bool PSPDpad::Touch(const TouchInput &input) {
if (dragPointerId_ == -1 && bounds_.Contains(input.x, input.y)) {
dragPointerId_ = input.id;
usedPointerMask |= 1 << input.id;
ProcessTouch(input.x, input.y, true);
ProcessTouch(input.x, input.y, true, false);
}
}
if (input.flags & TouchInputFlags::MOVE) {
if (!(input.flags & TouchInputFlags::MOUSE) || input.buttons) {
bool ignorePress = false;
if (g_activeGesturePointers.count(input.id)) {
// Don't start a dpad touch if dragging and this pointer is already being used for a gesture.
ignorePress = true;
}
if (dragPointerId_ == -1 && bounds_.Contains(input.x, input.y) && !(analogPointerMask & (1 << input.id))) {
dragPointerId_ = input.id;
}
if (input.id == dragPointerId_) {
ProcessTouch(input.x, input.y, true);
ProcessTouch(input.x, input.y, true, ignorePress);
}
}
}
@@ -339,13 +354,13 @@ bool PSPDpad::Touch(const TouchInput &input) {
if (input.id == dragPointerId_) {
dragPointerId_ = -1;
usedPointerMask &= ~(1 << input.id);
ProcessTouch(input.x, input.y, false);
ProcessTouch(input.x, input.y, false, false);
}
}
return retval;
}
void PSPDpad::ProcessTouch(float x, float y, bool down) {
void PSPDpad::ProcessTouch(float x, float y, bool down, bool ignorePress) {
float stick_size = bounds_.w;
float inv_stick_size = 1.0f / stick_size;
const float deadzone = 0.05f;
@@ -391,7 +406,7 @@ void PSPDpad::ProcessTouch(float x, float y, bool down) {
bool vibrate = false;
static const int dir[4] = { CTRL_RIGHT, CTRL_DOWN, CTRL_LEFT, CTRL_UP };
for (int i = 0; i < 4; i++) {
if (pressed & dir[i]) {
if (!ignorePress && (pressed & dir[i])) {
vibrate = true;
__CtrlUpdateButtons(dir[i], 0);
}
@@ -1078,6 +1093,12 @@ const GestureControlConfig &GestureGamepad::GetZone() {
return g_Config.gestureControls[zoneIndex_];
}
GestureGamepad::~GestureGamepad() {
if (dragPointerId_ != -1) {
g_activeGesturePointers.erase(dragPointerId_);
}
}
bool GestureGamepad::Touch(const TouchInput &input) {
const GestureControlConfig &zone = GetZone();
@@ -1089,6 +1110,7 @@ bool GestureGamepad::Touch(const TouchInput &input) {
if (input.flags & TouchInputFlags::RELEASE_ALL) {
dragPointerId_ = -1;
g_activeGesturePointers.clear();
return false;
}
@@ -1103,6 +1125,7 @@ bool GestureGamepad::Touch(const TouchInput &input) {
lastY_ = input.y;
downX_ = input.x;
downY_ = input.y;
const float now = time_now_d();
if (now - lastTapRelease_ < 0.3f && !haveDoubleTapped_) {
if (zone.iDoubleTapGesture != 0 )
@@ -1120,17 +1143,27 @@ bool GestureGamepad::Touch(const TouchInput &input) {
lastX_ = input.x;
lastY_ = input.y;
const float distance = sqrtf((input.x - downX_) * (input.x - downX_) + (input.y - downY_) * (input.y - downY_));
// TODO: Configurable distance?
if (distance > 50.0f * g_display.dpi_scale_x) {
// The user has dragged some distance from the initial touch. Start ignoring button presses.
g_activeGesturePointers.insert(input.id);
} else {
g_activeGesturePointers.erase(input.id);
}
if (zone.bAnalogGesture) {
const float k = zone.fAnalogGestureSensibility * 0.02;
float dx = (input.x - downX_)*g_display.dpi_scale_x * k;
float dy = (input.y - downY_)*g_display.dpi_scale_y * k;
dx = std::min(1.0f, std::max(-1.0f, dx));
dy = std::min(1.0f, std::max(-1.0f, dy));
const float k = zone.fAnalogGestureSensitivity * 0.02;
float dx = (input.x - downX_) * g_display.dpi_scale_x * k;
float dy = (input.y - downY_) * g_display.dpi_scale_y * k;
dx = std::clamp(dx, -1.0f, 1.0f);
dy = std::clamp(dy, -1.0f, 1.0f);
__CtrlSetAnalogXY(0, dx, -dy);
}
}
}
if (input.flags & TouchInputFlags::UP) {
g_activeGesturePointers.erase(input.id);
if (input.id == dragPointerId_) {
dragPointerId_ = -1;
if (time_now_d() - lastTouchDown_ < 0.3f)
+2 -1
View File
@@ -121,7 +121,7 @@ public:
bool IsDown() const override { return down_ != 0; }
private:
void ProcessTouch(float x, float y, bool down);
void ProcessTouch(float x, float y, bool down, bool ignorePress);
ImageID arrowIndex_;
ImageID arrowDownIndex_;
ImageID overlayIndex_;
@@ -210,6 +210,7 @@ struct GestureControlConfig;
class GestureGamepad : public UI::View {
public:
explicit GestureGamepad(ControlMapper* controlMapper, int zoneIndex, UI::LayoutParams *layoutParams) : UI::View(layoutParams), controlMapper_(controlMapper), zoneIndex_(zoneIndex) {}
~GestureGamepad();
bool Touch(const TouchInput &input) override;
void Update() override;