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