We now delay the mouseup events for 50ms, rather than just delaying them for an additional couple of pollEvent (which doesn't work anymore due to changes in the eventhandling code elsewhere). This fixes #3018512.
527 lines
14 KiB
C++
527 lines
14 KiB
C++
/* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
// Disable symbol overrides so that we can use system headers.
|
|
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
|
|
|
#include "gui/message.h"
|
|
#include "common/translation.h"
|
|
|
|
#include "osys_main.h"
|
|
|
|
static const int kQueuedInputEventDelay = 50;
|
|
|
|
bool OSystem_IPHONE::pollEvent(Common::Event &event) {
|
|
//printf("pollEvent()\n");
|
|
|
|
long curTime = getMillis();
|
|
|
|
if (_timerCallback && (curTime >= _timerCallbackNext)) {
|
|
_timerCallback(_timerCallbackTimer);
|
|
_timerCallbackNext = curTime + _timerCallbackTimer;
|
|
}
|
|
|
|
if (_queuedInputEvent.type != (Common::EventType)0 && curTime >= _queuedEventTime) {
|
|
event = _queuedInputEvent;
|
|
_queuedInputEvent.type = (Common::EventType)0;
|
|
return true;
|
|
}
|
|
|
|
int eventType;
|
|
float xUnit, yUnit;
|
|
|
|
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit)) {
|
|
int x = 0;
|
|
int y = 0;
|
|
switch (_screenOrientation) {
|
|
case kScreenOrientationPortrait:
|
|
if (_overlayVisible) {
|
|
x = (int)(xUnit * _overlayWidth);
|
|
y = (int)(yUnit * _overlayHeight);
|
|
} else {
|
|
x = (int)(xUnit * _screenWidth);
|
|
y = (int)(yUnit * _screenHeight);
|
|
}
|
|
break;
|
|
case kScreenOrientationLandscape:
|
|
if (_overlayVisible) {
|
|
x = (int)(yUnit * _overlayWidth);
|
|
y = (int)((1.0 - xUnit) * _overlayHeight);
|
|
} else {
|
|
x = (int)(yUnit * _screenWidth);
|
|
y = (int)((1.0 - xUnit) * _screenHeight);
|
|
}
|
|
break;
|
|
case kScreenOrientationFlippedLandscape:
|
|
if (_overlayVisible) {
|
|
x = (int)((1.0 - yUnit) * _overlayWidth);
|
|
y = (int)(xUnit * _overlayHeight);
|
|
} else {
|
|
x = (int)((1.0 - yUnit) * _screenWidth);
|
|
y = (int)(xUnit * _screenHeight);
|
|
}
|
|
break;
|
|
}
|
|
|
|
switch ((InputEvent)eventType) {
|
|
case kInputMouseDown:
|
|
if (!handleEvent_mouseDown(event, x, y))
|
|
return false;
|
|
break;
|
|
|
|
case kInputMouseUp:
|
|
if (!handleEvent_mouseUp(event, x, y))
|
|
return false;
|
|
break;
|
|
|
|
case kInputMouseDragged:
|
|
if (!handleEvent_mouseDragged(event, x, y))
|
|
return false;
|
|
break;
|
|
case kInputMouseSecondDragged:
|
|
if (!handleEvent_mouseSecondDragged(event, x, y))
|
|
return false;
|
|
break;
|
|
case kInputMouseSecondDown:
|
|
_secondaryTapped = true;
|
|
if (!handleEvent_secondMouseDown(event, x, y))
|
|
return false;
|
|
break;
|
|
case kInputMouseSecondUp:
|
|
_secondaryTapped = false;
|
|
if (!handleEvent_secondMouseUp(event, x, y))
|
|
return false;
|
|
break;
|
|
case kInputOrientationChanged:
|
|
handleEvent_orientationChanged((int)xUnit);
|
|
return false;
|
|
break;
|
|
|
|
case kInputApplicationSuspended:
|
|
suspendLoop();
|
|
return false;
|
|
break;
|
|
|
|
case kInputKeyPressed:
|
|
handleEvent_keyPressed(event, (int)xUnit);
|
|
break;
|
|
|
|
case kInputSwipe:
|
|
if (!handleEvent_swipe(event, (int)xUnit))
|
|
return false;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_mouseDown(Common::Event &event, int x, int y) {
|
|
//printf("Mouse down at (%u, %u)\n", x, y);
|
|
|
|
// Workaround: kInputMouseSecondToggled isn't always sent when the
|
|
// secondary finger is lifted. Need to make sure we get out of that mode.
|
|
_secondaryTapped = false;
|
|
|
|
if (_touchpadModeEnabled) {
|
|
_lastPadX = x;
|
|
_lastPadY = y;
|
|
} else
|
|
warpMouse(x, y);
|
|
|
|
if (_mouseClickAndDragEnabled) {
|
|
event.type = Common::EVENT_LBUTTONDOWN;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
return true;
|
|
} else {
|
|
_lastMouseDown = getMillis();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_mouseUp(Common::Event &event, int x, int y) {
|
|
//printf("Mouse up at (%u, %u)\n", x, y);
|
|
|
|
if (_secondaryTapped) {
|
|
_secondaryTapped = false;
|
|
if (!handleEvent_secondMouseUp(event, x, y))
|
|
return false;
|
|
}
|
|
else if (_mouseClickAndDragEnabled) {
|
|
event.type = Common::EVENT_LBUTTONUP;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
} else {
|
|
if (getMillis() - _lastMouseDown < 250) {
|
|
event.type = Common::EVENT_LBUTTONDOWN;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
|
|
_queuedInputEvent.type = Common::EVENT_LBUTTONUP;
|
|
_queuedInputEvent.mouse.x = _mouseX;
|
|
_queuedInputEvent.mouse.y = _mouseY;
|
|
_lastMouseTap = getMillis();
|
|
_queuedEventTime = _lastMouseTap + kQueuedInputEventDelay;
|
|
} else
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
|
|
_lastSecondaryDown = getMillis();
|
|
_gestureStartX = x;
|
|
_gestureStartY = y;
|
|
|
|
if (_mouseClickAndDragEnabled) {
|
|
event.type = Common::EVENT_LBUTTONUP;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
|
|
_queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
|
|
_queuedInputEvent.mouse.x = _mouseX;
|
|
_queuedInputEvent.mouse.y = _mouseY;
|
|
}
|
|
else
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
|
|
int curTime = getMillis();
|
|
|
|
if (curTime - _lastSecondaryDown < 400 ) {
|
|
//printf("Right tap!\n");
|
|
if (curTime - _lastSecondaryTap < 400 && !_overlayVisible) {
|
|
//printf("Right escape!\n");
|
|
event.type = Common::EVENT_KEYDOWN;
|
|
_queuedInputEvent.type = Common::EVENT_KEYUP;
|
|
|
|
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
|
|
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
|
|
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
|
|
_queuedEventTime = curTime + kQueuedInputEventDelay;
|
|
_lastSecondaryTap = 0;
|
|
} else if (!_mouseClickAndDragEnabled) {
|
|
//printf("Rightclick!\n");
|
|
event.type = Common::EVENT_RBUTTONDOWN;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
_queuedInputEvent.type = Common::EVENT_RBUTTONUP;
|
|
_queuedInputEvent.mouse.x = _mouseX;
|
|
_queuedInputEvent.mouse.y = _mouseY;
|
|
_lastSecondaryTap = curTime;
|
|
_queuedEventTime = curTime + kQueuedInputEventDelay;
|
|
} else {
|
|
//printf("Right nothing!\n");
|
|
return false;
|
|
}
|
|
}
|
|
if (_mouseClickAndDragEnabled) {
|
|
event.type = Common::EVENT_RBUTTONUP;
|
|
event.mouse.x = _mouseX;
|
|
event.mouse.y = _mouseY;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
|
|
if (_lastDragPosX == x && _lastDragPosY == y)
|
|
return false;
|
|
|
|
_lastDragPosX = x;
|
|
_lastDragPosY = y;
|
|
|
|
//printf("Mouse dragged at (%u, %u)\n", x, y);
|
|
int mouseNewPosX;
|
|
int mouseNewPosY;
|
|
if (_touchpadModeEnabled ) {
|
|
int deltaX = _lastPadX - x;
|
|
int deltaY = _lastPadY - y;
|
|
_lastPadX = x;
|
|
_lastPadY = y;
|
|
|
|
mouseNewPosX = (int)(_mouseX - deltaX / 0.5f);
|
|
mouseNewPosY = (int)(_mouseY - deltaY / 0.5f);
|
|
|
|
int widthCap = _overlayVisible ? _overlayWidth : _screenWidth;
|
|
int heightCap = _overlayVisible ? _overlayHeight : _screenHeight;
|
|
|
|
if (mouseNewPosX < 0)
|
|
mouseNewPosX = 0;
|
|
else if (mouseNewPosX > widthCap)
|
|
mouseNewPosX = widthCap;
|
|
|
|
if (mouseNewPosY < 0)
|
|
mouseNewPosY = 0;
|
|
else if (mouseNewPosY > heightCap)
|
|
mouseNewPosY = heightCap;
|
|
|
|
} else {
|
|
mouseNewPosX = x;
|
|
mouseNewPosY = y;
|
|
}
|
|
|
|
event.type = Common::EVENT_MOUSEMOVE;
|
|
event.mouse.x = mouseNewPosX;
|
|
event.mouse.y = mouseNewPosY;
|
|
warpMouse(mouseNewPosX, mouseNewPosY);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, int y) {
|
|
if (_gestureStartX == -1 || _gestureStartY == -1) {
|
|
return false;
|
|
}
|
|
|
|
static const int kNeededLength = 100;
|
|
static const int kMaxDeviation = 20;
|
|
|
|
int vecX = (x - _gestureStartX);
|
|
int vecY = (y - _gestureStartY);
|
|
|
|
int absX = abs(vecX);
|
|
int absY = abs(vecY);
|
|
|
|
//printf("(%d, %d)\n", vecX, vecY);
|
|
|
|
if (absX >= kNeededLength || absY >= kNeededLength) { // Long enough gesture to react upon.
|
|
_gestureStartX = -1;
|
|
_gestureStartY = -1;
|
|
|
|
if (absX < kMaxDeviation && vecY >= kNeededLength) {
|
|
// Swipe down
|
|
event.type = Common::EVENT_KEYDOWN;
|
|
_queuedInputEvent.type = Common::EVENT_KEYUP;
|
|
|
|
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
|
|
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
|
|
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
|
|
_queuedEventTime = getMillis() + kQueuedInputEventDelay;
|
|
return true;
|
|
}
|
|
|
|
if (absX < kMaxDeviation && -vecY >= kNeededLength) {
|
|
// Swipe up
|
|
_mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
|
|
const char *dialogMsg;
|
|
if (_mouseClickAndDragEnabled) {
|
|
_touchpadModeEnabled = false;
|
|
dialogMsg = "Mouse-click-and-drag mode enabled.";
|
|
} else
|
|
dialogMsg = "Mouse-click-and-drag mode disabled.";
|
|
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
|
|
dialog.runModal();
|
|
return false;
|
|
}
|
|
|
|
if (absY < kMaxDeviation && vecX >= kNeededLength) {
|
|
// Swipe right
|
|
_touchpadModeEnabled = !_touchpadModeEnabled;
|
|
const char *dialogMsg;
|
|
if (_touchpadModeEnabled)
|
|
dialogMsg = _("Touchpad mode enabled.");
|
|
else
|
|
dialogMsg = _("Touchpad mode disabled.");
|
|
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
|
|
dialog.runModal();
|
|
return false;
|
|
|
|
}
|
|
|
|
if (absY < kMaxDeviation && -vecX >= kNeededLength) {
|
|
// Swipe left
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void OSystem_IPHONE::handleEvent_orientationChanged(int orientation) {
|
|
//printf("Orientation: %i\n", orientation);
|
|
|
|
ScreenOrientation newOrientation;
|
|
switch (orientation) {
|
|
case 1:
|
|
newOrientation = kScreenOrientationPortrait;
|
|
break;
|
|
case 3:
|
|
newOrientation = kScreenOrientationLandscape;
|
|
break;
|
|
case 4:
|
|
newOrientation = kScreenOrientationFlippedLandscape;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
|
|
if (_screenOrientation != newOrientation) {
|
|
_screenOrientation = newOrientation;
|
|
iPhone_initSurface(_screenWidth, _screenHeight);
|
|
|
|
dirtyFullScreen();
|
|
if (_overlayVisible)
|
|
dirtyFullOverlayScreen();
|
|
updateScreen();
|
|
}
|
|
}
|
|
|
|
void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
|
|
int ascii = keyPressed;
|
|
//printf("key: %i\n", keyPressed);
|
|
|
|
// We remap some of the iPhone keyboard keys.
|
|
// The first ten here are the row of symbols below the numeric keys.
|
|
switch (keyPressed) {
|
|
case 45:
|
|
keyPressed = Common::KEYCODE_F1;
|
|
ascii = Common::ASCII_F1;
|
|
break;
|
|
case 47:
|
|
keyPressed = Common::KEYCODE_F2;
|
|
ascii = Common::ASCII_F2;
|
|
break;
|
|
case 58:
|
|
keyPressed = Common::KEYCODE_F3;
|
|
ascii = Common::ASCII_F3;
|
|
break;
|
|
case 59:
|
|
keyPressed = Common::KEYCODE_F4;
|
|
ascii = Common::ASCII_F4;
|
|
break;
|
|
case 40:
|
|
keyPressed = Common::KEYCODE_F5;
|
|
ascii = Common::ASCII_F5;
|
|
break;
|
|
case 41:
|
|
keyPressed = Common::KEYCODE_F6;
|
|
ascii = Common::ASCII_F6;
|
|
break;
|
|
case 36:
|
|
keyPressed = Common::KEYCODE_F7;
|
|
ascii = Common::ASCII_F7;
|
|
break;
|
|
case 38:
|
|
keyPressed = Common::KEYCODE_F8;
|
|
ascii = Common::ASCII_F8;
|
|
break;
|
|
case 64:
|
|
keyPressed = Common::KEYCODE_F9;
|
|
ascii = Common::ASCII_F9;
|
|
break;
|
|
case 34:
|
|
keyPressed = Common::KEYCODE_F10;
|
|
ascii = Common::ASCII_F10;
|
|
break;
|
|
case 10:
|
|
keyPressed = Common::KEYCODE_RETURN;
|
|
ascii = Common::ASCII_RETURN;
|
|
break;
|
|
}
|
|
event.type = Common::EVENT_KEYDOWN;
|
|
_queuedInputEvent.type = Common::EVENT_KEYUP;
|
|
|
|
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
|
|
event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
|
|
event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
|
|
_queuedEventTime = getMillis() + kQueuedInputEventDelay;
|
|
}
|
|
|
|
bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) {
|
|
Common::KeyCode keycode = Common::KEYCODE_INVALID;
|
|
switch (_screenOrientation) {
|
|
case kScreenOrientationPortrait:
|
|
switch ((UIViewSwipeDirection)direction) {
|
|
case kUIViewSwipeUp:
|
|
keycode = Common::KEYCODE_UP;
|
|
break;
|
|
case kUIViewSwipeDown:
|
|
keycode = Common::KEYCODE_DOWN;
|
|
break;
|
|
case kUIViewSwipeLeft:
|
|
keycode = Common::KEYCODE_LEFT;
|
|
break;
|
|
case kUIViewSwipeRight:
|
|
keycode = Common::KEYCODE_RIGHT;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case kScreenOrientationLandscape:
|
|
switch ((UIViewSwipeDirection)direction) {
|
|
case kUIViewSwipeUp:
|
|
keycode = Common::KEYCODE_LEFT;
|
|
break;
|
|
case kUIViewSwipeDown:
|
|
keycode = Common::KEYCODE_RIGHT;
|
|
break;
|
|
case kUIViewSwipeLeft:
|
|
keycode = Common::KEYCODE_DOWN;
|
|
break;
|
|
case kUIViewSwipeRight:
|
|
keycode = Common::KEYCODE_UP;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
case kScreenOrientationFlippedLandscape:
|
|
switch ((UIViewSwipeDirection)direction) {
|
|
case kUIViewSwipeUp:
|
|
keycode = Common::KEYCODE_RIGHT;
|
|
break;
|
|
case kUIViewSwipeDown:
|
|
keycode = Common::KEYCODE_LEFT;
|
|
break;
|
|
case kUIViewSwipeLeft:
|
|
keycode = Common::KEYCODE_UP;
|
|
break;
|
|
case kUIViewSwipeRight:
|
|
keycode = Common::KEYCODE_DOWN;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
|
|
event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
|
|
event.type = Common::EVENT_KEYDOWN;
|
|
_queuedInputEvent.type = Common::EVENT_KEYUP;
|
|
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
|
|
_queuedEventTime = getMillis() + kQueuedInputEventDelay;
|
|
|
|
return true;
|
|
}
|