/* 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 "common/scummsys.h" #ifdef _WIN32_WCE #include "common/config-manager.h" #include "backends/events/wincesdl/wincesdl-events.h" #include "backends/platform/wince/CEActionsPocket.h" #include "backends/platform/wince/CEActionsSmartphone.h" #include "backends/platform/wince/CEDevice.h" #include "backends/platform/sdl/sdl.h" WINCESdlEventSource::WINCESdlEventSource() : _tapTime(0), _closeClick(false), _rbutton(false), _graphicsMan(0) { } void WINCESdlEventSource::init(WINCESdlGraphicsManager *graphicsMan) { assert(graphicsMan); _graphicsMan = graphicsMan; } bool WINCESdlEventSource::processMouseEvent(Common::Event &event, int x, int y) { event.mouse.x = x; event.mouse.y = y; // Update the "keyboard mouse" coords _km.x = event.mouse.x * MULTIPLIER; _km.y = event.mouse.y * MULTIPLIER; // Adjust for the screen scaling if (_graphicsMan->_zoomDown) event.mouse.y += 240; event.mouse.x = event.mouse.x * _graphicsMan->_scaleFactorXd / _graphicsMan->_scaleFactorXm; event.mouse.y = event.mouse.y * _graphicsMan->_scaleFactorYd / _graphicsMan->_scaleFactorYm; return true; } bool WINCESdlEventSource::pollEvent(Common::Event &event) { SDL_Event ev; ev.type = SDL_NOEVENT; DWORD currentTime; bool keyEvent = false; bool freeLookActive = _graphicsMan->getFreeLookState(); int deltaX, deltaY; memset(&event, 0, sizeof(Common::Event)); if (handleKbdMouse(event)) { return true; } // If the screen changed, send an Common::EVENT_SCREEN_CHANGED int screenID = _graphicsMan->getScreenChangeID(); if (screenID != _lastScreenID) { _lastScreenID = screenID; event.type = Common::EVENT_SCREEN_CHANGED; return true; } CEDevice::wakeUp(); currentTime = GetTickCount(); while (SDL_PollEvent(&ev)) { switch (ev.type) { case SDL_KEYDOWN: debug(1, "Key down %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); // KMOD_RESERVED is used if the key has been injected by an external buffer if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) { keyEvent = true; _graphicsMan->_lastKeyPressed = ev.key.keysym.sym; _graphicsMan->_keyRepeatTime = currentTime; _graphicsMan->_keyRepeat = 0; if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, true)) return true; } if (GUI_Actions::Instance()->mappingActive()) event.kbd.flags = 0xFF; else if (ev.key.keysym.sym == SDLK_PAUSE) { _graphicsMan->_lastKeyPressed = 0; event.type = Common::EVENT_PREDICTIVE_DIALOG; return true; } event.type = Common::EVENT_KEYDOWN; if (!GUI::Actions::Instance()->mappingActive()) event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; else event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { event.kbd.ascii ^= 0x20; event.kbd.flags = Common::KBD_SHIFT; } return true; case SDL_KEYUP: debug(1, "Key up %X %s", ev.key.keysym.sym, SDL_GetKeyName((SDLKey)ev.key.keysym.sym)); // KMOD_RESERVED is used if the key has been injected by an external buffer if (ev.key.keysym.mod != KMOD_RESERVED && !GUI::Actions::Instance()->mappingActive()) { keyEvent = true; _graphicsMan->_lastKeyPressed = 0; if (!GUI_Actions::Instance()->mappingActive() && GUI_Actions::Instance()->performMapped(ev.key.keysym.sym, false)) return true; } if (GUI_Actions::Instance()->mappingActive()) event.kbd.flags = 0xFF; else if (ev.key.keysym.sym == SDLK_PAUSE) { _graphicsMan->_lastKeyPressed = 0; return false; // chew up the show agi dialog key up event } event.type = Common::EVENT_KEYUP; if (!GUI::Actions::Instance()->mappingActive()) event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; else event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, GUI::Actions::Instance()->mappingActive()); if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { event.kbd.ascii ^= 0x20; event.kbd.flags = Common::KBD_SHIFT; } return true; case SDL_MOUSEMOTION: event.type = Common::EVENT_MOUSEMOVE; if (!processMouseEvent(event, ev.motion.x, ev.motion.y)) { return false; } // update KbdMouse _km.x = ev.motion.x * MULTIPLIER; _km.y = ev.motion.y * MULTIPLIER; _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); return true; case SDL_MOUSEBUTTONDOWN: if (ev.button.button == SDL_BUTTON_LEFT) event.type = Common::EVENT_LBUTTONDOWN; else if (ev.button.button == SDL_BUTTON_RIGHT) event.type = Common::EVENT_RBUTTONDOWN; else break; if (!processMouseEvent(event, ev.button.x, ev.button.y)) { return false; } // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; if (event.mouse.x > _tapX) deltaX = event.mouse.x - _tapX; else deltaX = _tapX - event.mouse.x; if (event.mouse.y > _tapY) deltaY = event.mouse.y - _tapY; else deltaY = _tapY - event.mouse.y; _closeClick = (deltaX <= 5 && deltaY <= 5); if (!_isSmartphone) { // handle double-taps if (_tapTime) { // second tap if (_closeClick && (GetTickCount() - _tapTime < 1000)) { if (event.mouse.y <= 20 && _graphicsMan->_panelInitialized && !_graphicsMan->_noDoubleTapPT) { // top of screen (show panel) _graphicsMan->swap_panel_visibility(); } else if (!_graphicsMan->_noDoubleTapRMB) { // right click event.type = Common::EVENT_RBUTTONDOWN; _rbutton = true; } } _tapTime = 0; } else { _tapTime = GetTickCount(); _tapX = event.mouse.x; _tapY = event.mouse.y; } } if (freeLookActive && !_closeClick) { _rbutton = false; _tapTime = 0; _tapX = event.mouse.x; _tapY = event.mouse.y; event.type = Common::EVENT_MOUSEMOVE; _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); } if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, true)) { if (!_graphicsMan->_toolbarHandler.drawn()) { _graphicsMan->_toolbarHighDrawn = false; _graphicsMan->internUpdateScreen(); } if (_graphicsMan->_newOrientation != _graphicsMan->_orientationLandscape) { _graphicsMan->_orientationLandscape = _graphicsMan->_newOrientation; _graphicsMan->_toolbarHighDrawn = false; ConfMan.setInt("landscape", _graphicsMan->_orientationLandscape); ConfMan.flushToDisk(); _graphicsMan->hotswapGFXMode(); } return false; } return true; case SDL_MOUSEBUTTONUP: if (ev.button.button == SDL_BUTTON_LEFT) event.type = Common::EVENT_LBUTTONUP; else if (ev.button.button == SDL_BUTTON_RIGHT) event.type = Common::EVENT_RBUTTONUP; else break; if (_rbutton) { event.type = Common::EVENT_RBUTTONUP; _rbutton = false; } if (!processMouseEvent(event, ev.button.x, ev.button.y)) { return false; } // update KbdMouse _km.x = ev.button.x * MULTIPLIER; _km.y = ev.button.y * MULTIPLIER; if (freeLookActive && !_closeClick) { _tapX = event.mouse.x; _tapY = event.mouse.y; event.type = Common::EVENT_MOUSEMOVE; _graphicsMan->setMousePos(event.mouse.x, event.mouse.y); } if (_graphicsMan->_toolbarHandler.action(event.mouse.x, event.mouse.y, false)) { if (!_graphicsMan->_toolbarHandler.drawn()) { _graphicsMan->_toolbarHighDrawn = false; _graphicsMan->internUpdateScreen(); } return false; } return true; case SDL_VIDEOEXPOSE: _graphicsMan->notifyVideoExpose(); break; case SDL_QUIT: event.type = Common::EVENT_QUIT; return true; case SDL_ACTIVEEVENT: if (ev.active.state & SDL_APPMOUSEFOCUS) debug(2, "%s mouse focus.", ev.active.gain ? "Got" : "Lost"); if (ev.active.state & SDL_APPINPUTFOCUS) debug(2, "%s input focus.", ev.active.gain ? "Got" : "Lost"); if (ev.active.state & SDL_APPACTIVE) debug(2, "%s total focus.", ev.active.gain ? "Got" : "Lost"); if (ev.active.state & SDL_APPINPUTFOCUS) { _graphicsMan->_hasfocus = ev.active.gain; SDL_PauseAudio(!_graphicsMan->_hasfocus); if (_graphicsMan->_hasfocus) _graphicsMan->notifyVideoExpose(); } break; } } // Simulate repeated key for backend if (!keyEvent && _graphicsMan->_lastKeyPressed && (int)currentTime > _graphicsMan->_keyRepeatTime + _graphicsMan->_keyRepeatTrigger) { _graphicsMan->_keyRepeatTime = currentTime; _graphicsMan->_keyRepeat++; GUI_Actions::Instance()->performMapped(_graphicsMan->_lastKeyPressed, true); } return false; } int WINCESdlEventSource::mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { if (GUI::Actions::Instance()->mappingActive()) return key; if (unfilter) { switch (key) { case SDLK_ESCAPE: return SDLK_BACKSPACE; case SDLK_F8: return SDLK_ASTERISK; case SDLK_F9: return SDLK_HASH; default: return key; } } if (key >= SDLK_KP0 && key <= SDLK_KP9) { return key - SDLK_KP0 + '0'; } else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) { return key; } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { return 0; } return key; } #endif /* _WIN32_WCE */