/* 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 . * */ #include "common/system.h" #include "m4/platform/events.h" #include "m4/vars.h" #include "m4/m4.h" #include "m4/platform/timer.h" namespace M4 { /* * Define call mask bit fields */ enum { CursorPositionChanged = 0, LeftButtonPressed, LeftButtonReleased, RightButtonPressed, RightButtonReleased }; /* * Define call mask values */ #define CPC ((uint16)(1 << CursorPositionChanged)) #define LBD ((uint16)(1 << LeftButtonPressed)) #define LBU ((uint16)(1 << LeftButtonReleased)) #define LBH ((uint16)(1 << LeftButtonHold)) #define RBD ((uint16)(1 << RightButtonPressed)) #define RBU ((uint16)(1 << RightButtonReleased)) #define RBH ((uint16)(1 << RightButtonHold)) #define LBC (LBD + LBU) #define RBC (RBD + RBU) #define MBC (MBD + MBU) #define MSA (LBC + RBC + CPC) #define OEMA (LBC + RBC + MBC + CPC) #define _MLD (_mouseStateEvent & LBD) #define _ClearMLD _mouseStateEvent &= ~LBD #define _MLU (_mouseStateEvent & LBU) #define _ClearMLU _mouseStateEvent &= ~LBU #define _MRD (_mouseStateEvent & RBD) #define _ClearMRD _mouseStateEvent &= ~RBD #define _MRU (_mouseStateEvent & RBU) #define _ClearMRU _mouseStateEvent &= ~RBU #define _MMOVE ((_mouseX != _oldX) || (_mouseY != _oldY)) #define _MSAVE _oldX = _mouseX; _oldY = _mouseY Events *g_events; Events::Events() { g_events = this; } Events::~Events() { g_events = nullptr; } void Events::process() { pollEvents(); } void Events::pollEvents() { Common::Event ev; while (g_system->getEventManager()->pollEvent(ev)) { if (ev.type == Common::EVENT_QUIT || ev.type == Common::EVENT_RETURN_TO_LAUNCHER) { _G(kernel).going = false; } else if (ev.type >= Common::EVENT_MOUSEMOVE && ev.type <= Common::EVENT_MBUTTONUP) { handleMouseEvent(ev); } else if (ev.type == Common::EVENT_KEYDOWN || ev.type == Common::EVENT_KEYUP) { handleKeyboardEvent(ev); } } } void Events::handleMouseEvent(const Common::Event &ev) { _mouseX = ev.mouse.x; _mouseY = ev.mouse.y; switch (ev.type) { case Common::EVENT_MOUSEMOVE: _mouseStateEvent |= CPC; break; case Common::EVENT_LBUTTONDOWN: _mouseStateEvent |= LBD; ButtonState = 1; break; case Common::EVENT_LBUTTONUP: _mouseStateEvent |= LBU; ButtonState = 0; break; case Common::EVENT_RBUTTONDOWN: _mouseStateEvent |= RBD; ButtonState = 2; break; case Common::EVENT_RBUTTONUP: _mouseStateEvent |= RBU; ButtonState = 0; break; case Common::EVENT_WHEELDOWN: _G(toggle_cursor) = CURSCHANGE_NEXT; break; case Common::EVENT_WHEELUP: _G(toggle_cursor) = CURSCHANGE_PREVIOUS; break; case Common::EVENT_MBUTTONDOWN: _G(toggle_cursor) = CURSCHANGE_TOGGLE; break; default: break; } } void Events::handleKeyboardEvent(const Common::Event &ev) { if (ev.type == Common::EVENT_KEYDOWN && _pendingKeys.size() < 16) _pendingKeys.push(ev.kbd); } MouseEvent Events::mouse_get_event() { process(); switch (_mouse_state) { case _MS_no_event: if (_MLD) { _ClearMLD; if (_dclickTime && (timer_read_60() < _dclickTime)) { _mouse_state = _MS_doubleclick_Down; _dclickTime = 0; return _ME_doubleclick; } _dclickTime = 0; _mouse_state = _MS_L_clickDown; return _ME_L_click; } if (_MRD) { _ClearMRD; _mouse_state = _MS_R_clickDown; return _ME_R_click; } if (_MMOVE) { _MSAVE; return _ME_move; } return _ME_no_event; case _MS_L_clickDown: if (_MLU || !ButtonState) { _dclickTime = timer_read_60() + 15; _ClearMLU; _mouse_state = _MS_no_event; return _ME_L_release; } if (_MMOVE) { _MSAVE; return _ME_L_drag; } return _ME_L_hold; case _MS_R_clickDown: if (_MRU) { _ClearMRU; _mouse_state = _MS_no_event; _G(toggle_cursor) = CURSCHANGE_NEXT; return _ME_R_release; } if (_MMOVE) { _MSAVE; return _ME_R_drag; } return _ME_R_hold; case _MS_doubleclick_Down: if (_MLU) { _ClearMLU; _ClearMLD; _mouse_state = _MS_no_event; return _ME_doubleclick_release; } if (_MMOVE) { _MSAVE; return _ME_doubleclick_drag; } return _ME_doubleclick_hold; default: return _ME_no_event; } return _ME_no_event; } bool Events::util_kbd_check(int32 *parm1) { process(); if (!parm1 || _pendingKeys.empty()) return false; Common::KeyState ks = _pendingKeys.pop(); if (is_mod_key(ks)) return false; int flags = ks.flags & (Common::KBD_CTRL | Common::KBD_ALT); int key = (ks.ascii >= 32 && ks.ascii <= 127 && !flags) ? ks.ascii : (int)ks.keycode; *parm1 = key | (flags << 16); return true; } void Events::delay(uint amount) { uint32 beginTime = g_system->getMillis(), newTime; do { krn_pal_game_task(); g_system->delayMillis(5); process(); newTime = g_system->getMillis(); } while (!g_engine->shouldQuit() && newTime < (beginTime + amount)); } MouseEvent mouse_get_event() { return g_events->mouse_get_event(); } bool util_kbd_check(int32 *parm1) { return g_events->util_kbd_check(parm1); } } // namespace M4