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 // Disable symbol overrides so that we can use system headers.
24 #define FORBIDDEN_SYMBOL_ALLOW_ALL
25
26 #include "gui/message.h"
27 #include "common/translation.h"
28
29 #include "backends/platform/ios7/ios7_osys_main.h"
30
31 static const int kQueuedInputEventDelay = 50;
32
pollEvent(Common::Event & event)33 bool OSystem_iOS7::pollEvent(Common::Event &event) {
34 //printf("pollEvent()\n");
35
36 long curTime = getMillis();
37
38 if (_timerCallback && (curTime >= _timerCallbackNext)) {
39 _timerCallback(_timerCallbackTimer);
40 _timerCallbackNext = curTime + _timerCallbackTimer;
41 }
42
43 if (_queuedInputEvent.type != Common::EVENT_INVALID && curTime >= _queuedEventTime) {
44 event = _queuedInputEvent;
45 _queuedInputEvent.type = Common::EVENT_INVALID;
46 return true;
47 }
48
49 InternalEvent internalEvent;
50
51 if (iOS7_fetchEvent(&internalEvent)) {
52 switch (internalEvent.type) {
53 case kInputMouseDown:
54 if (!handleEvent_mouseDown(event, internalEvent.value1, internalEvent.value2))
55 return false;
56 break;
57
58 case kInputMouseUp:
59 if (!handleEvent_mouseUp(event, internalEvent.value1, internalEvent.value2))
60 return false;
61 break;
62
63 case kInputMouseDragged:
64 if (!handleEvent_mouseDragged(event, internalEvent.value1, internalEvent.value2))
65 return false;
66 break;
67
68 case kInputOrientationChanged:
69 handleEvent_orientationChanged(internalEvent.value1);
70 return false;
71
72 case kInputApplicationSuspended:
73 handleEvent_applicationSuspended();
74 return false;
75
76 case kInputApplicationResumed:
77 handleEvent_applicationResumed();
78 return false;
79
80 case kInputApplicationSaveState:
81 handleEvent_applicationSaveState();
82 return false;
83
84 case kInputApplicationRestoreState:
85 handleEvent_applicationRestoreState();
86 return false;
87
88 case kInputApplicationClearState:
89 handleEvent_applicationClearState();
90 return false;
91
92 case kInputMouseSecondDragged:
93 if (!handleEvent_mouseSecondDragged(event, internalEvent.value1, internalEvent.value2))
94 return false;
95 break;
96 case kInputMouseSecondDown:
97 _secondaryTapped = true;
98 if (!handleEvent_secondMouseDown(event, internalEvent.value1, internalEvent.value2))
99 return false;
100 break;
101 case kInputMouseSecondUp:
102 _secondaryTapped = false;
103 if (!handleEvent_secondMouseUp(event, internalEvent.value1, internalEvent.value2))
104 return false;
105 break;
106
107 case kInputKeyPressed:
108 handleEvent_keyPressed(event, internalEvent.value1);
109 break;
110
111 case kInputSwipe:
112 if (!handleEvent_swipe(event, internalEvent.value1, internalEvent.value2))
113 return false;
114 break;
115
116 case kInputTap:
117 if (!handleEvent_tap(event, (UIViewTapDescription) internalEvent.value1, internalEvent.value2))
118 return false;
119 break;
120
121 case kInputMainMenu:
122 event.type = Common::EVENT_MAINMENU;
123 _queuedInputEvent.type = Common::EVENT_INVALID;
124 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
125 break;
126
127 default:
128 break;
129 }
130
131 return true;
132 }
133 return false;
134 }
135
handleEvent_mouseDown(Common::Event & event,int x,int y)136 bool OSystem_iOS7::handleEvent_mouseDown(Common::Event &event, int x, int y) {
137 //printf("Mouse down at (%u, %u)\n", x, y);
138
139 // Workaround: kInputMouseSecondToggled isn't always sent when the
140 // secondary finger is lifted. Need to make sure we get out of that mode.
141 _secondaryTapped = false;
142
143 if (_touchpadModeEnabled) {
144 _lastPadX = x;
145 _lastPadY = y;
146 } else
147 warpMouse(x, y);
148
149 if (_mouseClickAndDragEnabled) {
150 event.type = Common::EVENT_LBUTTONDOWN;
151 event.mouse.x = _videoContext->mouseX;
152 event.mouse.y = _videoContext->mouseY;
153 return true;
154 } else {
155 _lastMouseDown = getMillis();
156 }
157 return false;
158 }
159
handleEvent_mouseUp(Common::Event & event,int x,int y)160 bool OSystem_iOS7::handleEvent_mouseUp(Common::Event &event, int x, int y) {
161 //printf("Mouse up at (%u, %u)\n", x, y);
162
163 if (_secondaryTapped) {
164 _secondaryTapped = false;
165 if (!handleEvent_secondMouseUp(event, x, y))
166 return false;
167 } else if (_mouseClickAndDragEnabled) {
168 event.type = Common::EVENT_LBUTTONUP;
169 event.mouse.x = _videoContext->mouseX;
170 event.mouse.y = _videoContext->mouseY;
171 } else {
172 if (getMillis() - _lastMouseDown < 250) {
173 event.type = Common::EVENT_LBUTTONDOWN;
174 event.mouse.x = _videoContext->mouseX;
175 event.mouse.y = _videoContext->mouseY;
176
177 _queuedInputEvent.type = Common::EVENT_LBUTTONUP;
178 _queuedInputEvent.mouse.x = _videoContext->mouseX;
179 _queuedInputEvent.mouse.y = _videoContext->mouseY;
180 _lastMouseTap = getMillis();
181 _queuedEventTime = _lastMouseTap + kQueuedInputEventDelay;
182 } else
183 return false;
184 }
185
186 return true;
187 }
188
handleEvent_secondMouseDown(Common::Event & event,int x,int y)189 bool OSystem_iOS7::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
190 _lastSecondaryDown = getMillis();
191 _gestureStartX = x;
192 _gestureStartY = y;
193
194 if (_mouseClickAndDragEnabled) {
195 event.type = Common::EVENT_LBUTTONUP;
196 event.mouse.x = _videoContext->mouseX;
197 event.mouse.y = _videoContext->mouseY;
198
199 _queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
200 _queuedInputEvent.mouse.x = _videoContext->mouseX;
201 _queuedInputEvent.mouse.y = _videoContext->mouseY;
202 } else
203 return false;
204
205 return true;
206 }
207
handleEvent_secondMouseUp(Common::Event & event,int x,int y)208 bool OSystem_iOS7::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
209 int curTime = getMillis();
210
211 if (curTime - _lastSecondaryDown < 400) {
212 //printf("Right tap!\n");
213 if (curTime - _lastSecondaryTap < 400 && !_videoContext->overlayVisible) {
214 //printf("Right escape!\n");
215 event.type = Common::EVENT_KEYDOWN;
216 _queuedInputEvent.type = Common::EVENT_KEYUP;
217
218 event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
219 event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
220 event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
221 _queuedEventTime = curTime + kQueuedInputEventDelay;
222 _lastSecondaryTap = 0;
223 } else if (!_mouseClickAndDragEnabled) {
224 //printf("Rightclick!\n");
225 event.type = Common::EVENT_RBUTTONDOWN;
226 event.mouse.x = _videoContext->mouseX;
227 event.mouse.y = _videoContext->mouseY;
228 _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
229 _queuedInputEvent.mouse.x = _videoContext->mouseX;
230 _queuedInputEvent.mouse.y = _videoContext->mouseY;
231 _lastSecondaryTap = curTime;
232 _queuedEventTime = curTime + kQueuedInputEventDelay;
233 } else {
234 //printf("Right nothing!\n");
235 return false;
236 }
237 }
238 if (_mouseClickAndDragEnabled) {
239 event.type = Common::EVENT_RBUTTONUP;
240 event.mouse.x = _videoContext->mouseX;
241 event.mouse.y = _videoContext->mouseY;
242 }
243
244 return true;
245 }
246
handleEvent_mouseDragged(Common::Event & event,int x,int y)247 bool OSystem_iOS7::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
248 if (_lastDragPosX == x && _lastDragPosY == y)
249 return false;
250
251 _lastDragPosX = x;
252 _lastDragPosY = y;
253
254 //printf("Mouse dragged at (%u, %u)\n", x, y);
255 int mouseNewPosX;
256 int mouseNewPosY;
257 if (_touchpadModeEnabled) {
258 int deltaX = _lastPadX - x;
259 int deltaY = _lastPadY - y;
260 _lastPadX = x;
261 _lastPadY = y;
262
263 mouseNewPosX = (int)(_videoContext->mouseX - deltaX / 0.5f);
264 mouseNewPosY = (int)(_videoContext->mouseY - deltaY / 0.5f);
265
266 int widthCap = _videoContext->overlayVisible ? _videoContext->overlayWidth : _videoContext->screenWidth;
267 int heightCap = _videoContext->overlayVisible ? _videoContext->overlayHeight : _videoContext->screenHeight;
268
269 if (mouseNewPosX < 0)
270 mouseNewPosX = 0;
271 else if (mouseNewPosX > widthCap)
272 mouseNewPosX = widthCap;
273
274 if (mouseNewPosY < 0)
275 mouseNewPosY = 0;
276 else if (mouseNewPosY > heightCap)
277 mouseNewPosY = heightCap;
278
279 } else {
280 mouseNewPosX = x;
281 mouseNewPosY = y;
282 }
283
284 event.type = Common::EVENT_MOUSEMOVE;
285 event.mouse.x = mouseNewPosX;
286 event.mouse.y = mouseNewPosY;
287 warpMouse(mouseNewPosX, mouseNewPosY);
288
289 return true;
290 }
291
handleEvent_mouseSecondDragged(Common::Event & event,int x,int y)292 bool OSystem_iOS7::handleEvent_mouseSecondDragged(Common::Event &event, int x, int y) {
293 if (_gestureStartX == -1 || _gestureStartY == -1) {
294 return false;
295 }
296
297 static const int kNeededLength = 100;
298 static const int kMaxDeviation = 20;
299
300 int vecX = (x - _gestureStartX);
301 int vecY = (y - _gestureStartY);
302
303 int absX = abs(vecX);
304 int absY = abs(vecY);
305
306 //printf("(%d, %d)\n", vecX, vecY);
307
308 if (absX >= kNeededLength || absY >= kNeededLength) { // Long enough gesture to react upon.
309 _gestureStartX = -1;
310 _gestureStartY = -1;
311
312 if (absX < kMaxDeviation && vecY >= kNeededLength) {
313 // Swipe down
314 event.type = Common::EVENT_MAINMENU;
315 _queuedInputEvent.type = Common::EVENT_INVALID;
316
317 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
318 return true;
319 }
320
321 if (absX < kMaxDeviation && -vecY >= kNeededLength) {
322 // Swipe up
323 _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
324 Common::U32String dialogMsg;
325 if (_mouseClickAndDragEnabled) {
326 _touchpadModeEnabled = false;
327 dialogMsg = _("Mouse-click-and-drag mode enabled.");
328 } else
329 dialogMsg = _("Mouse-click-and-drag mode disabled.");
330 GUI::TimedMessageDialog dialog(dialogMsg, 1500);
331 dialog.runModal();
332 return false;
333 }
334
335 if (absY < kMaxDeviation && vecX >= kNeededLength) {
336 // Swipe right
337 _touchpadModeEnabled = !_touchpadModeEnabled;
338 Common::U32String dialogMsg;
339 if (_touchpadModeEnabled)
340 dialogMsg = _("Touchpad mode enabled.");
341 else
342 dialogMsg = _("Touchpad mode disabled.");
343 GUI::TimedMessageDialog dialog(dialogMsg, 1500);
344 dialog.runModal();
345 return false;
346
347 }
348
349 if (absY < kMaxDeviation && -vecX >= kNeededLength) {
350 // Swipe left
351 return false;
352 }
353 }
354
355 return false;
356 }
357
handleEvent_orientationChanged(int orientation)358 void OSystem_iOS7::handleEvent_orientationChanged(int orientation) {
359 //printf("Orientation: %i\n", orientation);
360
361 ScreenOrientation newOrientation;
362 switch (orientation) {
363 case 1:
364 newOrientation = kScreenOrientationPortrait;
365 break;
366 case 2:
367 newOrientation = kScreenOrientationFlippedPortrait;
368 break;
369 case 3:
370 newOrientation = kScreenOrientationLandscape;
371 break;
372 case 4:
373 newOrientation = kScreenOrientationFlippedLandscape;
374 break;
375 default:
376 return;
377 }
378
379 if (_screenOrientation != newOrientation) {
380 _screenOrientation = newOrientation;
381 rebuildSurface();
382 }
383 }
384
rebuildSurface()385 void OSystem_iOS7::rebuildSurface() {
386 updateOutputSurface();
387
388 dirtyFullScreen();
389 if (_videoContext->overlayVisible) {
390 dirtyFullOverlayScreen();
391 }
392 updateScreen();
393 }
394
handleEvent_applicationSuspended()395 void OSystem_iOS7::handleEvent_applicationSuspended() {
396 suspendLoop();
397 }
398
handleEvent_applicationResumed()399 void OSystem_iOS7::handleEvent_applicationResumed() {
400 rebuildSurface();
401 }
402
handleEvent_keyPressed(Common::Event & event,int keyPressed)403 void OSystem_iOS7::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
404 int ascii = keyPressed;
405 //printf("key: %i\n", keyPressed);
406
407 // Map LF character to Return key/CR character
408 if (keyPressed == 10) {
409 keyPressed = Common::KEYCODE_RETURN;
410 ascii = Common::ASCII_RETURN;
411 }
412
413 event.type = Common::EVENT_KEYDOWN;
414 _queuedInputEvent.type = Common::EVENT_KEYUP;
415
416 event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
417 event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
418 event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
419 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
420 }
421
handleEvent_swipe(Common::Event & event,int direction,int touches)422 bool OSystem_iOS7::handleEvent_swipe(Common::Event &event, int direction, int touches) {
423 if (touches == 3) {
424 Common::KeyCode keycode = Common::KEYCODE_INVALID;
425 switch ((UIViewSwipeDirection)direction) {
426 case kUIViewSwipeUp:
427 keycode = Common::KEYCODE_UP;
428 break;
429 case kUIViewSwipeDown:
430 keycode = Common::KEYCODE_DOWN;
431 break;
432 case kUIViewSwipeLeft:
433 keycode = Common::KEYCODE_LEFT;
434 break;
435 case kUIViewSwipeRight:
436 keycode = Common::KEYCODE_RIGHT;
437 break;
438 default:
439 return false;
440 }
441
442 event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
443 event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
444 event.type = Common::EVENT_KEYDOWN;
445 _queuedInputEvent.type = Common::EVENT_KEYUP;
446 event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
447 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
448
449 return true;
450 }
451 else if (touches == 2) {
452 switch ((UIViewSwipeDirection)direction) {
453 case kUIViewSwipeUp: {
454 _mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
455 Common::U32String dialogMsg;
456 if (_mouseClickAndDragEnabled) {
457 _touchpadModeEnabled = false;
458 dialogMsg = _("Mouse-click-and-drag mode enabled.");
459 } else
460 dialogMsg = _("Mouse-click-and-drag mode disabled.");
461 GUI::TimedMessageDialog dialog(dialogMsg, 1500);
462 dialog.runModal();
463 return false;
464 }
465
466 case kUIViewSwipeDown: {
467 // Swipe down
468 event.type = Common::EVENT_MAINMENU;
469 _queuedInputEvent.type = Common::EVENT_INVALID;
470 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
471 return true;
472 }
473
474 case kUIViewSwipeRight: {
475 // Swipe right
476 _touchpadModeEnabled = !_touchpadModeEnabled;
477 Common::U32String dialogMsg;
478 if (_touchpadModeEnabled)
479 dialogMsg = _("Touchpad mode enabled.");
480 else
481 dialogMsg = _("Touchpad mode disabled.");
482 GUI::TimedMessageDialog dialog(dialogMsg, 1500);
483 dialog.runModal();
484 return false;
485 }
486
487 default:
488 break;
489 }
490 }
491 return false;
492 }
493
handleEvent_tap(Common::Event & event,UIViewTapDescription type,int touches)494 bool OSystem_iOS7::handleEvent_tap(Common::Event &event, UIViewTapDescription type, int touches) {
495 if (touches == 1) {
496 if (type == kUIViewTapDouble) {
497 event.type = Common::EVENT_RBUTTONDOWN;
498 _queuedInputEvent.type = Common::EVENT_RBUTTONUP;
499 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
500 return true;
501 }
502 }
503 else if (touches == 2) {
504 if (type == kUIViewTapDouble) {
505 event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
506 event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
507 event.type = Common::EVENT_KEYDOWN;
508 _queuedInputEvent.type = Common::EVENT_KEYUP;
509 event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
510 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
511 return true;
512 }
513 }
514 return false;
515 }
516