1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/scummsys.h"
24
25 #if !defined(DISABLE_DEFAULT_EVENTMANAGER)
26
27 #include "common/system.h"
28 #include "common/config-manager.h"
29 #include "common/translation.h"
30 #include "backends/events/default/default-events.h"
31 #include "backends/keymapper/keymapper.h"
32 #include "backends/keymapper/remap-dialog.h"
33 #include "backends/vkeybd/virtual-keyboard.h"
34
35 #include "engines/engine.h"
36 #include "gui/message.h"
37
DefaultEventManager(Common::EventSource * boss)38 DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
39 _buttonState(0),
40 _modifierState(0),
41 _shouldQuit(false),
42 _shouldRTL(false),
43 _confirmExitDialogActive(false) {
44
45 assert(boss);
46
47 _dispatcher.registerSource(boss, false);
48 _dispatcher.registerSource(&_artificialEventSource, false);
49
50 _dispatcher.registerObserver(this, kEventManPriority, false);
51
52 // Reset key repeat
53 _currentKeyDown.keycode = 0;
54 _currentKeyDown.ascii = 0;
55 _currentKeyDown.flags = 0;
56
57 _keyRepeatTime = 0;
58
59 #ifdef ENABLE_VKEYBD
60 _vk = new Common::VirtualKeyboard();
61 #endif
62 #ifdef ENABLE_KEYMAPPER
63 _keymapper = new Common::Keymapper(this);
64 // EventDispatcher will automatically free the keymapper
65 _dispatcher.registerMapper(_keymapper);
66 _remap = false;
67 #else
68 _dispatcher.registerMapper(new Common::DefaultEventMapper());
69 #endif
70 }
71
~DefaultEventManager()72 DefaultEventManager::~DefaultEventManager() {
73 #ifdef ENABLE_VKEYBD
74 delete _vk;
75 #endif
76 }
77
init()78 void DefaultEventManager::init() {
79 #ifdef ENABLE_VKEYBD
80 if (ConfMan.hasKey("vkeybd_pack_name")) {
81 _vk->loadKeyboardPack(ConfMan.get("vkeybd_pack_name"));
82 } else {
83 _vk->loadKeyboardPack("vkeybd_default");
84 }
85 #endif
86 }
87
pollEvent(Common::Event & event)88 bool DefaultEventManager::pollEvent(Common::Event &event) {
89 // Skip recording of these events
90 uint32 time = g_system->getMillis(true);
91 bool result = false;
92
93 _dispatcher.dispatch();
94 if (!_eventQueue.empty()) {
95 event = _eventQueue.pop();
96 result = true;
97 }
98
99 if (result) {
100 event.synthetic = false;
101 switch (event.type) {
102 case Common::EVENT_KEYDOWN:
103 _modifierState = event.kbd.flags;
104 // init continuous event stream
105 _currentKeyDown.ascii = event.kbd.ascii;
106 _currentKeyDown.keycode = event.kbd.keycode;
107 _currentKeyDown.flags = event.kbd.flags;
108 _keyRepeatTime = time + kKeyRepeatInitialDelay;
109
110 if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
111 // WORKAROUND: Some engines incorrectly attempt to use the
112 // ascii value instead of the keycode to detect the backspace
113 // key (a non-portable behavior). This fails at least on
114 // Mac OS X, possibly also on other systems.
115 // As a workaround, we force the ascii value for backspace
116 // key pressed. A better fix would be for engines to stop
117 // making invalid assumptions about ascii values.
118 event.kbd.ascii = Common::KEYCODE_BACKSPACE;
119 _currentKeyDown.ascii = Common::KEYCODE_BACKSPACE;
120 }
121 break;
122
123 case Common::EVENT_KEYUP:
124 _modifierState = event.kbd.flags;
125 if (event.kbd.keycode == _currentKeyDown.keycode) {
126 // Only stop firing events if it's the current key
127 _currentKeyDown.keycode = 0;
128 }
129 break;
130
131 case Common::EVENT_MOUSEMOVE:
132 _mousePos = event.mouse;
133 break;
134
135 case Common::EVENT_LBUTTONDOWN:
136 _mousePos = event.mouse;
137 _buttonState |= LBUTTON;
138 break;
139
140 case Common::EVENT_LBUTTONUP:
141 _mousePos = event.mouse;
142 _buttonState &= ~LBUTTON;
143 break;
144
145 case Common::EVENT_RBUTTONDOWN:
146 _mousePos = event.mouse;
147 _buttonState |= RBUTTON;
148 break;
149
150 case Common::EVENT_RBUTTONUP:
151 _mousePos = event.mouse;
152 _buttonState &= ~RBUTTON;
153 break;
154
155 case Common::EVENT_MAINMENU:
156 if (g_engine && !g_engine->isPaused())
157 g_engine->openMainMenuDialog();
158
159 if (_shouldQuit)
160 event.type = Common::EVENT_QUIT;
161 else if (_shouldRTL)
162 event.type = Common::EVENT_RTL;
163 break;
164 #ifdef ENABLE_VKEYBD
165 case Common::EVENT_VIRTUAL_KEYBOARD:
166 if (_vk->isDisplaying()) {
167 _vk->close(true);
168 } else {
169 if (g_engine)
170 g_engine->pauseEngine(true);
171 _vk->show();
172 if (g_engine)
173 g_engine->pauseEngine(false);
174 result = false;
175 }
176 break;
177 #endif
178 #ifdef ENABLE_KEYMAPPER
179 case Common::EVENT_KEYMAPPER_REMAP:
180 if (!_remap) {
181 _remap = true;
182 Common::RemapDialog _remapDialog;
183 if (g_engine)
184 g_engine->pauseEngine(true);
185 _remapDialog.runModal();
186 if (g_engine)
187 g_engine->pauseEngine(false);
188 _remap = false;
189 }
190 break;
191 #endif
192 case Common::EVENT_RTL:
193 if (ConfMan.getBool("confirm_exit")) {
194 if (g_engine)
195 g_engine->pauseEngine(true);
196 GUI::MessageDialog alert(_("Do you really want to return to the Launcher?"), _("Launcher"), _("Cancel"));
197 result = _shouldRTL = (alert.runModal() == GUI::kMessageOK);
198 if (g_engine)
199 g_engine->pauseEngine(false);
200 } else
201 _shouldRTL = true;
202 break;
203
204 case Common::EVENT_MUTE:
205 if (g_engine)
206 g_engine->flipMute();
207 break;
208
209 case Common::EVENT_QUIT:
210 if (ConfMan.getBool("confirm_exit")) {
211 if (_confirmExitDialogActive) {
212 result = false;
213 break;
214 }
215 _confirmExitDialogActive = true;
216 if (g_engine)
217 g_engine->pauseEngine(true);
218 GUI::MessageDialog alert(_("Do you really want to quit?"), _("Quit"), _("Cancel"));
219 result = _shouldQuit = (alert.runModal() == GUI::kMessageOK);
220 if (g_engine)
221 g_engine->pauseEngine(false);
222 _confirmExitDialogActive = false;
223 } else
224 _shouldQuit = true;
225
226 break;
227
228 default:
229 break;
230 }
231 } else {
232 // Check if event should be sent again (keydown)
233 if (_currentKeyDown.keycode != 0 && _keyRepeatTime < time) {
234 // fire event
235 event.type = Common::EVENT_KEYDOWN;
236 event.synthetic = true;
237 event.kbd.ascii = _currentKeyDown.ascii;
238 event.kbd.keycode = (Common::KeyCode)_currentKeyDown.keycode;
239 event.kbd.flags = _currentKeyDown.flags;
240 _keyRepeatTime = time + kKeyRepeatSustainDelay;
241 result = true;
242 }
243 }
244
245 return result;
246 }
247
pushEvent(const Common::Event & event)248 void DefaultEventManager::pushEvent(const Common::Event &event) {
249 // If already received an EVENT_QUIT, don't add another one
250 if (event.type == Common::EVENT_QUIT) {
251 if (!_shouldQuit)
252 _artificialEventSource.addEvent(event);
253 } else
254 _artificialEventSource.addEvent(event);
255 }
256
257 #endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
258