scummvm/backends/platform/ios7/ios7_game_controller.mm
Lars Sundström 80cb6427e1 IOS7: Trigger joystick presses only once for buttons A and B
All buttons and triggers on MFi game controllers are pressure sensitive
which means that when pressing buttons the registered
valueChangedHandler function is called multiple times providing updates
on the pressure value the button is pressed with. This causes multiple
kInputJoystickButtonDown events to be sent to the EventManager.
In adventure games the pressure value is not relevant and could cause
problems for the user that it triggers multiple presses on e.g. the B
button which often is mapped to the right mouse button. In some games
a click on the right mouse button changes what action that should be
performed.

Keep track on if the joystick buttons A or B (often mapped as left and
right mouse buttons) are being pressed. If the button is already
pressed do not add a new event until the button isn't pressed anymore.

To not interfere with any open dialog, don't send key events while the
keyboard is visible.
2023-04-27 21:17:58 +01:00

146 lines
4.3 KiB
Text

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Disable symbol overrides so that we can use system headers.
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "common/events.h"
#include "backends/platform/ios7/ios7_game_controller.h"
#include "backends/platform/ios7/ios7_video.h"
@interface GameController()
@property (nonatomic, assign) BOOL firstButtonPressed;
@property (nonatomic, assign) BOOL secondButtonPressed;
@end
@implementation GameController
@synthesize view;
- (id)initWithView:(iPhoneView *)view {
self = [super init];
if (self) {
[self setView:view];
}
_firstButtonPressed = _secondButtonPressed = NO;
return self;
}
// Override the setter method
- (void)setIsConnected:(BOOL)isConnected {
// Inform that input changed
_isConnected = isConnected;
[view addEvent:InternalEvent(kInputChanged, 0, 0)];
}
- (void)handlePointerMoveTo:(CGPoint)point {
int x, y;
// Only set valid mouse coordinates in games
if (![view getMouseCoords:point eventX:&x eventY:&y]) {
return;
}
[view setPointerPosition:point];
if (_firstButtonPressed) {
[view addEvent:InternalEvent(kInputMouseDragged, x, y)];
} else if (_secondButtonPressed) {
[view addEvent:InternalEvent(kInputMouseSecondDragged, x, y)];
} else {
[view addEvent:InternalEvent(kInputMouseDragged, x, y)];
}
}
- (void)handleMouseButtonAction:(GameControllerMouseButton)button isPressed:(bool)pressed at:(CGPoint)point{
int x, y;
// Only set valid mouse coordinates in games
if (![view getMouseCoords:[view pointerPosition] eventX:&x eventY:&y]) {
return;
}
[view setPointerPosition:point];
switch (button) {
case kGameControllerMouseButtonLeft:
if (pressed) {
_firstButtonPressed = YES;
[view addEvent:InternalEvent(kInputMouseDown, x, y)];
} else {
_firstButtonPressed = NO;
[view addEvent:InternalEvent(kInputMouseUp, x, y)];
}
break;
case kGameControllerMouseButtonRight:
if (pressed) {
_secondButtonPressed = YES;
[view addEvent:InternalEvent(kInputMouseSecondDown, x, y)];
} else {
_secondButtonPressed = NO;
[view addEvent:InternalEvent(kInputMouseSecondUp, x, y)];
}
break;
default:
break;
}
}
- (void)handleJoystickAxisMotionX:(int)x andY:(int)y forJoystick:(GameControllerJoystick)joystick {
if (joystick == kGameControllerJoystickLeft) {
[view addEvent:InternalEvent(kInputJoystickAxisMotion, Common::JOYSTICK_AXIS_LEFT_STICK_X, x)];
[view addEvent:InternalEvent(kInputJoystickAxisMotion, Common::JOYSTICK_AXIS_LEFT_STICK_Y, y)];
} else {
[view addEvent:InternalEvent(kInputJoystickAxisMotion, Common::JOYSTICK_AXIS_RIGHT_STICK_X, x)];
[view addEvent:InternalEvent(kInputJoystickAxisMotion, Common::JOYSTICK_AXIS_RIGHT_STICK_Y, y)];
}
}
- (void)handleJoystickButtonAction:(int)button isPressed:(bool)pressed {
bool addEvent = true;
if (button == Common::JOYSTICK_BUTTON_A) {
if (_firstButtonPressed) {
if (pressed) {
addEvent = false;
}
}
_firstButtonPressed = pressed;
} else if (button == Common::JOYSTICK_BUTTON_B) {
if (_secondButtonPressed) {
if (pressed) {
addEvent = false;
}
}
_secondButtonPressed = pressed;
}
// Do not send button presses if keyboard is shown because if e.g.
// the "Do you want to quit?" dialog is shown the wait for user
// input will end (treating the button push as a mouse click) while
// the user tried to select the "y" or "n" character on the tvOS
// keyboard.
if (addEvent && ![view isKeyboardShown]) {
[view addEvent:InternalEvent(pressed ? kInputJoystickButtonDown : kInputJoystickButtonUp, button, 0)];
}
}
@end