As the virtual keyboard trigger has been moved to CTRL-F7, the previous code which generates a unmodified F7 event to do this will not work. Rather than just adding the CTRL modifier, this code changes the backend to directly generate the virtual keyboard trigger event directly. This avoids any future breakage if the key combination is changed again.
439 lines
10 KiB
C++
439 lines
10 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.
|
|
*
|
|
*/
|
|
|
|
#include <FApp.h>
|
|
#include <FSysSystemTime.h>
|
|
|
|
#include "common/translation.h"
|
|
#include "base/main.h"
|
|
|
|
#include "backends/platform/tizen/form.h"
|
|
#include "backends/platform/tizen/system.h"
|
|
|
|
using namespace Tizen::Base::Collection;
|
|
using namespace Tizen::Base::Runtime;
|
|
using namespace Tizen::Ui::Controls;
|
|
|
|
// round down small Y touch values to 1 to allow the
|
|
// cursor to be positioned at the top of the screen
|
|
#define MIN_TOUCH_Y 20
|
|
|
|
// block for up to 2.5 seconds during shutdown to
|
|
// allow the game thread to exit gracefully.
|
|
#define EXIT_SLEEP_STEP 10
|
|
#define EXIT_SLEEP 250
|
|
|
|
//
|
|
// TizenAppForm
|
|
//
|
|
TizenAppForm::TizenAppForm() :
|
|
_gestureMode(false),
|
|
_osdMessage(NULL),
|
|
_gameThread(NULL),
|
|
_eventQueueLock(NULL),
|
|
_state(kInitState),
|
|
_buttonState(kLeftButton),
|
|
_shortcut(kEscapeKey) {
|
|
}
|
|
|
|
result TizenAppForm::Construct() {
|
|
TizenSystem *tizenSystem = NULL;
|
|
result r = Form::Construct(FORM_STYLE_NORMAL);
|
|
if (!IsFailed(r)) {
|
|
tizenSystem = new TizenSystem(this);
|
|
r = tizenSystem != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
|
|
}
|
|
if (!IsFailed(r)) {
|
|
r = tizenSystem->Construct();
|
|
}
|
|
if (!IsFailed(r)) {
|
|
_gameThread = new Thread();
|
|
r = _gameThread != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
|
|
}
|
|
if (!IsFailed(r)) {
|
|
r = _gameThread->Construct(*this);
|
|
}
|
|
if (!IsFailed(r)) {
|
|
_eventQueueLock = new Mutex();
|
|
r = _eventQueueLock != NULL ? E_SUCCESS : E_OUT_OF_MEMORY;
|
|
}
|
|
if (!IsFailed(r)) {
|
|
r = _eventQueueLock->Create();
|
|
}
|
|
|
|
if (!IsFailed(r)) {
|
|
g_system = tizenSystem;
|
|
} else {
|
|
AppLog("Form startup failed");
|
|
delete tizenSystem;
|
|
delete _gameThread;
|
|
_gameThread = NULL;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
TizenAppForm::~TizenAppForm() {
|
|
logEntered();
|
|
|
|
if (_gameThread && _state != kErrorState) {
|
|
terminate();
|
|
|
|
_gameThread->Stop();
|
|
if (_state != kErrorState) {
|
|
_gameThread->Join();
|
|
}
|
|
|
|
delete _gameThread;
|
|
_gameThread = NULL;
|
|
}
|
|
|
|
delete _eventQueueLock;
|
|
_eventQueueLock = NULL;
|
|
|
|
logLeaving();
|
|
}
|
|
|
|
//
|
|
// abort the game thread
|
|
//
|
|
void TizenAppForm::terminate() {
|
|
if (_state == kActiveState) {
|
|
((TizenSystem *)g_system)->setMute(true);
|
|
|
|
_eventQueueLock->Acquire();
|
|
|
|
Common::Event e;
|
|
e.type = Common::EVENT_QUIT;
|
|
_eventQueue.push(e);
|
|
_state = kClosingState;
|
|
|
|
_eventQueueLock->Release();
|
|
|
|
// block while thread ends
|
|
AppLog("waiting for shutdown");
|
|
for (int i = 0; i < EXIT_SLEEP_STEP && _state == kClosingState; i++) {
|
|
Thread::Sleep(EXIT_SLEEP);
|
|
}
|
|
|
|
if (_state == kClosingState) {
|
|
// failed to terminate - Join() will freeze
|
|
_state = kErrorState;
|
|
}
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::exitSystem() {
|
|
_state = kErrorState;
|
|
|
|
if (_gameThread) {
|
|
_gameThread->Stop();
|
|
delete _gameThread;
|
|
_gameThread = NULL;
|
|
}
|
|
}
|
|
|
|
result TizenAppForm::OnInitializing(void) {
|
|
logEntered();
|
|
|
|
AddOrientationEventListener(*this);
|
|
AddTouchEventListener(*this);
|
|
SetMultipointTouchEnabled(true);
|
|
SetFormBackEventListener(this);
|
|
SetFormMenuEventListener(this);
|
|
|
|
// set focus to enable receiving key events
|
|
SetEnabled(true);
|
|
SetFocusable(true);
|
|
SetFocus();
|
|
|
|
return E_SUCCESS;
|
|
}
|
|
|
|
result TizenAppForm::OnDraw(void) {
|
|
logEntered();
|
|
return E_SUCCESS;
|
|
}
|
|
|
|
void TizenAppForm::OnOrientationChanged(const Control &source, OrientationStatus orientationStatus) {
|
|
logEntered();
|
|
if (_state == kInitState) {
|
|
_state = kActiveState;
|
|
_gameThread->Start();
|
|
}
|
|
}
|
|
|
|
Tizen::Base::Object *TizenAppForm::Run() {
|
|
logEntered();
|
|
|
|
scummvm_main(0, 0);
|
|
if (_state == kActiveState) {
|
|
Tizen::App::Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, NULL);
|
|
}
|
|
_state = kDoneState;
|
|
return NULL;
|
|
}
|
|
|
|
bool TizenAppForm::pollEvent(Common::Event &event) {
|
|
bool result = false;
|
|
|
|
_eventQueueLock->Acquire();
|
|
if (!_eventQueue.empty()) {
|
|
event = _eventQueue.pop();
|
|
result = true;
|
|
}
|
|
if (_osdMessage) {
|
|
TizenSystem *system = (TizenSystem *)g_system;
|
|
TizenGraphicsManager *graphics = system->getGraphics();
|
|
if (graphics) {
|
|
graphics->displayMessageOnOSD(_osdMessage);
|
|
_osdMessage = NULL;
|
|
}
|
|
}
|
|
_eventQueueLock->Release();
|
|
|
|
return result;
|
|
}
|
|
|
|
void TizenAppForm::pushEvent(Common::EventType type, const Point ¤tPosition) {
|
|
TizenSystem *system = (TizenSystem *)g_system;
|
|
TizenGraphicsManager *graphics = system->getGraphics();
|
|
if (graphics) {
|
|
// graphics could be NULL at startup or when
|
|
// displaying the system error screen
|
|
Common::Event e;
|
|
e.type = type;
|
|
e.mouse.x = currentPosition.x;
|
|
e.mouse.y = currentPosition.y > MIN_TOUCH_Y ? currentPosition.y : 1;
|
|
|
|
bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y);
|
|
|
|
_eventQueueLock->Acquire();
|
|
|
|
if (moved && type != Common::EVENT_MOUSEMOVE) {
|
|
Common::Event moveEvent;
|
|
moveEvent.type = Common::EVENT_MOUSEMOVE;
|
|
moveEvent.mouse = e.mouse;
|
|
_eventQueue.push(moveEvent);
|
|
}
|
|
|
|
_eventQueue.push(e);
|
|
_eventQueueLock->Release();
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::pushKey(Common::KeyCode keycode) {
|
|
if (_eventQueueLock) {
|
|
Common::Event e;
|
|
e.synthetic = false;
|
|
e.kbd.keycode = keycode;
|
|
e.kbd.ascii = keycode;
|
|
e.kbd.flags = 0;
|
|
|
|
_eventQueueLock->Acquire();
|
|
e.type = Common::EVENT_KEYDOWN;
|
|
_eventQueue.push(e);
|
|
e.type = Common::EVENT_KEYUP;
|
|
_eventQueue.push(e);
|
|
_eventQueueLock->Release();
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::setButtonShortcut() {
|
|
switch (_buttonState) {
|
|
case kLeftButton:
|
|
setMessage(_s("Right Click Once"));
|
|
_buttonState = kRightButtonOnce;
|
|
break;
|
|
case kRightButtonOnce:
|
|
setMessage(_s("Right Click"));
|
|
_buttonState = kRightButton;
|
|
break;
|
|
case kRightButton:
|
|
setMessage(_s("Move Only"));
|
|
_buttonState = kMoveOnly;
|
|
break;
|
|
case kMoveOnly:
|
|
setMessage(_s("Left Click"));
|
|
_buttonState = kLeftButton;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::setMessage(const char *message) {
|
|
if (_eventQueueLock) {
|
|
_eventQueueLock->Acquire();
|
|
_osdMessage = message;
|
|
_eventQueueLock->Release();
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::setShortcut() {
|
|
logEntered();
|
|
// cycle to the next shortcut
|
|
switch (_shortcut) {
|
|
case kControlMouse:
|
|
setMessage(_s("Escape Key"));
|
|
_shortcut = kEscapeKey;
|
|
break;
|
|
|
|
case kEscapeKey:
|
|
setMessage(_s("Game Menu"));
|
|
_shortcut = kGameMenu;
|
|
break;
|
|
|
|
case kGameMenu:
|
|
setMessage(_s("Show Keypad"));
|
|
_shortcut = kShowKeypad;
|
|
break;
|
|
|
|
case kShowKeypad:
|
|
setMessage(_s("Control Mouse"));
|
|
_shortcut = kControlMouse;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::invokeShortcut() {
|
|
logEntered();
|
|
switch (_shortcut) {
|
|
case kControlMouse:
|
|
setButtonShortcut();
|
|
break;
|
|
|
|
case kEscapeKey:
|
|
pushKey(Common::KEYCODE_ESCAPE);
|
|
break;
|
|
|
|
case kGameMenu:
|
|
_buttonState = kLeftButton;
|
|
pushKey(Common::KEYCODE_F5);
|
|
break;
|
|
|
|
case kShowKeypad:
|
|
showKeypad();
|
|
break;
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::showKeypad() {
|
|
// display the soft keyboard
|
|
if (_state == kActiveState) {
|
|
_buttonState = kLeftButton;
|
|
|
|
Common::Event e;
|
|
e.type = Common::EVENT_VIRTUAL_KEYBOARD;
|
|
if (_eventQueueLock) {
|
|
_eventQueueLock->Acquire();
|
|
_eventQueue.push(e);
|
|
_eventQueueLock->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
int TizenAppForm::getTouchCount() {
|
|
Tizen::Ui::TouchEventManager *touch = Tizen::Ui::TouchEventManager::GetInstance();
|
|
IListT<TouchEventInfo *> *touchList = touch->GetTouchInfoListN();
|
|
int touchCount = touchList->GetCount();
|
|
touchList->RemoveAll();
|
|
delete touchList;
|
|
return touchCount;
|
|
}
|
|
|
|
void TizenAppForm::OnTouchDoublePressed(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
if (_buttonState != kMoveOnly) {
|
|
pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
|
|
currentPosition);
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnTouchFocusIn(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
}
|
|
|
|
void TizenAppForm::OnTouchFocusOut(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
}
|
|
|
|
void TizenAppForm::OnTouchLongPressed(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
logEntered();
|
|
if (_buttonState != kLeftButton) {
|
|
pushKey(Common::KEYCODE_RETURN);
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnTouchMoved(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
if (!_gestureMode) {
|
|
pushEvent(Common::EVENT_MOUSEMOVE, currentPosition);
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnTouchPressed(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
if (getTouchCount() > 1) {
|
|
_gestureMode = true;
|
|
} else if (_buttonState != kMoveOnly) {
|
|
pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN,
|
|
currentPosition);
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnTouchReleased(const Control &source,
|
|
const Point ¤tPosition, const TouchEventInfo &touchInfo) {
|
|
if (_gestureMode) {
|
|
int touchCount = getTouchCount();
|
|
if (touchCount == 1) {
|
|
setShortcut();
|
|
} else {
|
|
if (touchCount == 2) {
|
|
invokeShortcut();
|
|
}
|
|
_gestureMode = false;
|
|
}
|
|
} else if (_buttonState != kMoveOnly) {
|
|
pushEvent(_buttonState == kLeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP,
|
|
currentPosition);
|
|
if (_buttonState == kRightButtonOnce) {
|
|
_buttonState = kLeftButton;
|
|
}
|
|
// flick to skip dialog
|
|
if (touchInfo.IsFlicked()) {
|
|
pushKey(Common::KEYCODE_PERIOD);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnFormBackRequested(Form &source) {
|
|
logEntered();
|
|
if (_state == kActiveState) {
|
|
invokeShortcut();
|
|
}
|
|
}
|
|
|
|
void TizenAppForm::OnFormMenuRequested(Form &source) {
|
|
logEntered();
|
|
if (_state == kActiveState) {
|
|
setShortcut();
|
|
}
|
|
}
|