ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

events.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #if defined(__ANDROID__)
00024 
00025 // Allow use of stuff in <time.h>
00026 #define FORBIDDEN_SYMBOL_EXCEPTION_time_h
00027 
00028 // Disable printf override in common/forbidden.h to avoid
00029 // clashes with log.h from the Android SDK.
00030 // That header file uses
00031 //   __attribute__ ((format(printf, 3, 4)))
00032 // which gets messed up by our override mechanism; this could
00033 // be avoided by either changing the Android SDK to use the equally
00034 // legal and valid
00035 //   __attribute__ ((format(printf, 3, 4)))
00036 // or by refining our printf override to use a varadic macro
00037 // (which then wouldn't be portable, though).
00038 // Anyway, for now we just disable the printf override globally
00039 // for the Android port
00040 #define FORBIDDEN_SYMBOL_EXCEPTION_printf
00041 
00042 #include "backends/platform/android/android.h"
00043 #include "backends/platform/android/events.h"
00044 #include "backends/platform/android/jni.h"
00045 
00046 // floating point. use sparingly
00047 template<class T>
00048 static inline T scalef(T in, float numerator, float denominator) {
00049     return static_cast<float>(in) * numerator / denominator;
00050 }
00051 
00052 static const int kQueuedInputEventDelay = 50;
00053 
00054 void OSystem_Android::setupKeymapper() {
00055 #ifdef ENABLE_KEYMAPPER
00056     using namespace Common;
00057 
00058     Keymapper *mapper = getEventManager()->getKeymapper();
00059 
00060     HardwareInputSet *inputSet = new HardwareInputSet();
00061 
00062     keySet->addHardwareInput(
00063         new HardwareInput("n", KeyState(KEYCODE_n), "n (vk)"));
00064 
00065     mapper->registerHardwareInputSet(inputSet);
00066 
00067     Keymap *globalMap = new Keymap(kGlobalKeymapName);
00068     Action *act;
00069 
00070     act = new Action(globalMap, "VIRT", "Display keyboard");
00071     act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, KBD_CTRL));
00072 
00073     mapper->addGlobalKeymap(globalMap);
00074 
00075     mapper->pushKeymap(kGlobalKeymapName);
00076 #endif
00077 }
00078 
00079 void OSystem_Android::warpMouse(int x, int y) {
00080     ENTER("%d, %d", x, y);
00081 
00082     Common::Event e;
00083 
00084     e.type = Common::EVENT_MOUSEMOVE;
00085     e.mouse.x = x;
00086     e.mouse.y = y;
00087 
00088     clipMouse(e.mouse);
00089 
00090     pushEvent(e);
00091 }
00092 
00093 void OSystem_Android::clipMouse(Common::Point &p) {
00094     const GLESBaseTexture *tex;
00095 
00096     if (_show_overlay)
00097         tex = _overlay_texture;
00098     else
00099         tex = _game_texture;
00100 
00101     p.x = CLIP(p.x, int16(0), int16(tex->width() - 1));
00102     p.y = CLIP(p.y, int16(0), int16(tex->height() - 1));
00103 }
00104 
00105 void OSystem_Android::scaleMouse(Common::Point &p, int x, int y,
00106                                     bool deductDrawRect) {
00107     const GLESBaseTexture *tex;
00108 
00109     if (_show_overlay)
00110         tex = _overlay_texture;
00111     else
00112         tex = _game_texture;
00113 
00114     const Common::Rect &r = tex->getDrawRect();
00115 
00116     if (_touchpad_mode) {
00117         x = x * 100 / _touchpad_scale;
00118         y = y * 100 / _touchpad_scale;
00119     }
00120 
00121     if (deductDrawRect) {
00122         x -= r.left;
00123         y -= r.top;
00124     }
00125 
00126     p.x = scalef(x, tex->width(), r.width());
00127     p.y = scalef(y, tex->height(), r.height());
00128 }
00129 
00130 void OSystem_Android::updateEventScale() {
00131     const GLESBaseTexture *tex;
00132 
00133     if (_show_overlay)
00134         tex = _overlay_texture;
00135     else
00136         tex = _game_texture;
00137 
00138     _eventScaleY = 100 * 480 / tex->height();
00139     _eventScaleX = 100 * 640 / tex->width();
00140 }
00141 
00142 void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
00143                                 int arg4, int arg5, int arg6) {
00144     Common::Event e;
00145 
00146     switch (type) {
00147     case JE_SYS_KEY:
00148         switch (arg1) {
00149         case JACTION_DOWN:
00150             e.type = Common::EVENT_KEYDOWN;
00151             break;
00152         case JACTION_UP:
00153             e.type = Common::EVENT_KEYUP;
00154             break;
00155         default:
00156             LOGE("unhandled jaction on system key: %d", arg1);
00157             return;
00158         }
00159 
00160         switch (arg2) {
00161         case JKEYCODE_BACK:
00162             e.kbd.keycode = Common::KEYCODE_ESCAPE;
00163             e.kbd.ascii = Common::ASCII_ESCAPE;
00164 
00165             pushEvent(e);
00166 
00167             return;
00168 
00169         // special case. we'll only get it's up event
00170         case JKEYCODE_MENU:
00171             e.type = Common::EVENT_MAINMENU;
00172 
00173             pushEvent(e);
00174 
00175             return;
00176 
00177         case JKEYCODE_CAMERA:
00178         case JKEYCODE_SEARCH:
00179             if (arg1 == JACTION_DOWN)
00180                 e.type = Common::EVENT_RBUTTONDOWN;
00181             else
00182                 e.type = Common::EVENT_RBUTTONUP;
00183 
00184             e.mouse = getEventManager()->getMousePos();
00185 
00186             pushEvent(e);
00187 
00188             return;
00189 
00190         default:
00191             LOGW("unmapped system key: %d", arg2);
00192             return;
00193         }
00194 
00195         break;
00196 
00197     case JE_KEY:
00198         switch (arg1) {
00199         case JACTION_DOWN:
00200             e.type = Common::EVENT_KEYDOWN;
00201             break;
00202         case JACTION_UP:
00203             e.type = Common::EVENT_KEYUP;
00204             break;
00205         default:
00206             LOGE("unhandled jaction on key: %d", arg1);
00207             return;
00208         }
00209 
00210         if (arg2 < 1 || arg2 > ARRAYSIZE(jkeymap)) {
00211             if (arg3 < 1) {
00212                 LOGE("received invalid keycode: %d (%d)", arg2, arg3);
00213                 return;
00214             } else {
00215                 // lets bet on the ascii code
00216                 e.kbd.keycode = Common::KEYCODE_INVALID;
00217             }
00218         } else {
00219             e.kbd.keycode = jkeymap[arg2];
00220         }
00221 
00222         if (arg5 > 0)
00223             e.kbdRepeat = true;
00224 
00225         // map special keys to 'our' ascii codes
00226         switch (e.kbd.keycode) {
00227         case Common::KEYCODE_BACKSPACE:
00228             e.kbd.ascii = Common::ASCII_BACKSPACE;
00229             break;
00230         case Common::KEYCODE_TAB:
00231             e.kbd.ascii = Common::ASCII_TAB;
00232             break;
00233         case Common::KEYCODE_RETURN:
00234             e.kbd.ascii = Common::ASCII_RETURN;
00235             break;
00236         case Common::KEYCODE_ESCAPE:
00237             e.kbd.ascii = Common::ASCII_ESCAPE;
00238             break;
00239         case Common::KEYCODE_SPACE:
00240             e.kbd.ascii = Common::ASCII_SPACE;
00241             break;
00242         case Common::KEYCODE_F1:
00243             e.kbd.ascii = Common::ASCII_F1;
00244             break;
00245         case Common::KEYCODE_F2:
00246             e.kbd.ascii = Common::ASCII_F2;
00247             break;
00248         case Common::KEYCODE_F3:
00249             e.kbd.ascii = Common::ASCII_F3;
00250             break;
00251         case Common::KEYCODE_F4:
00252             e.kbd.ascii = Common::ASCII_F4;
00253             break;
00254         case Common::KEYCODE_F5:
00255             e.kbd.ascii = Common::ASCII_F5;
00256             break;
00257         case Common::KEYCODE_F6:
00258             e.kbd.ascii = Common::ASCII_F6;
00259             break;
00260         case Common::KEYCODE_F7:
00261             e.kbd.ascii = Common::ASCII_F7;
00262             break;
00263         case Common::KEYCODE_F8:
00264             e.kbd.ascii = Common::ASCII_F8;
00265             break;
00266         case Common::KEYCODE_F9:
00267             e.kbd.ascii = Common::ASCII_F9;
00268             break;
00269         case Common::KEYCODE_F10:
00270             e.kbd.ascii = Common::ASCII_F10;
00271             break;
00272         case Common::KEYCODE_F11:
00273             e.kbd.ascii = Common::ASCII_F11;
00274             break;
00275         case Common::KEYCODE_F12:
00276             e.kbd.ascii = Common::ASCII_F12;
00277             break;
00278         default:
00279             e.kbd.ascii = arg3;
00280             break;
00281         }
00282 
00283         if (arg4 & JMETA_SHIFT)
00284             e.kbd.flags |= Common::KBD_SHIFT;
00285         // JMETA_ALT is Fn on physical keyboards!
00286         // when mapping this to ALT - as we know it from PC keyboards - all
00287         // Fn combos will be broken (like Fn+q, which needs to end as 1 and
00288         // not ALT+1). Do not want.
00289         //if (arg4 & JMETA_ALT)
00290         //  e.kbd.flags |= Common::KBD_ALT;
00291         if (arg4 & (JMETA_SYM | JMETA_CTRL))
00292             e.kbd.flags |= Common::KBD_CTRL;
00293 
00294         pushEvent(e);
00295 
00296         return;
00297 
00298     case JE_DPAD:
00299         switch (arg2) {
00300         case JKEYCODE_DPAD_UP:
00301         case JKEYCODE_DPAD_DOWN:
00302         case JKEYCODE_DPAD_LEFT:
00303         case JKEYCODE_DPAD_RIGHT:
00304             if (_show_mouse) {
00305                 if (arg1 != JACTION_DOWN)
00306                     return;
00307 
00308                 e.type = Common::EVENT_MOUSEMOVE;
00309 
00310                 e.mouse = getEventManager()->getMousePos();
00311 
00312                 {
00313                     int16 *c;
00314                     int s;
00315 
00316                     if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_DOWN) {
00317                         c = &e.mouse.y;
00318                         s = _eventScaleY;
00319                     } else {
00320                         c = &e.mouse.x;
00321                         s = _eventScaleX;
00322                     }
00323 
00324                     // the longer the button held, the faster the pointer is
00325                     // TODO put these values in some option dlg?
00326                     int f = CLIP(arg4, 1, 8) * _dpad_scale * 100 / s;
00327 
00328                     if (arg2 == JKEYCODE_DPAD_UP || arg2 == JKEYCODE_DPAD_LEFT)
00329                         *c -= f;
00330                     else
00331                         *c += f;
00332                 }
00333 
00334                 clipMouse(e.mouse);
00335 
00336                 pushEvent(e);
00337 
00338                 return;
00339             } else {
00340                 switch (arg1) {
00341                 case JACTION_DOWN:
00342                     e.type = Common::EVENT_KEYDOWN;
00343                     break;
00344                 case JACTION_UP:
00345                     e.type = Common::EVENT_KEYUP;
00346                     break;
00347                 default:
00348                     LOGE("unhandled jaction on dpad key: %d", arg1);
00349                     return;
00350                 }
00351 
00352                 switch (arg2) {
00353                 case JKEYCODE_DPAD_UP:
00354                     e.kbd.keycode = Common::KEYCODE_UP;
00355                     break;
00356                 case JKEYCODE_DPAD_DOWN:
00357                     e.kbd.keycode = Common::KEYCODE_DOWN;
00358                     break;
00359                 case JKEYCODE_DPAD_LEFT:
00360                     e.kbd.keycode = Common::KEYCODE_LEFT;
00361                     break;
00362                 case JKEYCODE_DPAD_RIGHT:
00363                     e.kbd.keycode = Common::KEYCODE_RIGHT;
00364                     break;
00365                 }
00366 
00367                 pushEvent(e);
00368                 return;
00369             }
00370 
00371         case JKEYCODE_DPAD_CENTER:
00372             switch (arg1) {
00373             case JACTION_DOWN:
00374                 e.type = Common::EVENT_LBUTTONDOWN;
00375                 break;
00376             case JACTION_UP:
00377                 e.type = Common::EVENT_LBUTTONUP;
00378                 break;
00379             default:
00380                 LOGE("unhandled jaction on dpad key: %d", arg1);
00381                 return;
00382             }
00383 
00384             e.mouse = getEventManager()->getMousePos();
00385 
00386             pushEvent(e);
00387 
00388             return;
00389         }
00390 
00391     case JE_DOWN:
00392         _touch_pt_down = getEventManager()->getMousePos();
00393         _touch_pt_scroll.x = -1;
00394         _touch_pt_scroll.y = -1;
00395         break;
00396 
00397     case JE_SCROLL:
00398         if (_show_mouse) {
00399             e.type = Common::EVENT_MOUSEMOVE;
00400 
00401             if (_touchpad_mode) {
00402                 if (_touch_pt_scroll.x == -1 && _touch_pt_scroll.y == -1) {
00403                     _touch_pt_scroll.x = arg3;
00404                     _touch_pt_scroll.y = arg4;
00405                     return;
00406                 }
00407 
00408                 scaleMouse(e.mouse, arg3 - _touch_pt_scroll.x,
00409                             arg4 - _touch_pt_scroll.y, false);
00410                 e.mouse += _touch_pt_down;
00411                 clipMouse(e.mouse);
00412             } else {
00413                 scaleMouse(e.mouse, arg3, arg4);
00414                 clipMouse(e.mouse);
00415             }
00416 
00417             pushEvent(e);
00418         }
00419 
00420         return;
00421 
00422     case JE_TAP:
00423         if (_fingersDown > 0) {
00424             _fingersDown = 0;
00425             return;
00426         }
00427 
00428         if (!_virtcontrols_on) {
00429             e.type = Common::EVENT_MOUSEMOVE;
00430 
00431             if (_touchpad_mode) {
00432                 e.mouse = getEventManager()->getMousePos();
00433             } else {
00434                 scaleMouse(e.mouse, arg1, arg2);
00435                 clipMouse(e.mouse);
00436             }
00437 
00438             Common::EventType down, up;
00439 
00440             // TODO put these values in some option dlg?
00441             if (arg3 > 1000) {
00442                 down = Common::EVENT_MBUTTONDOWN;
00443                 up = Common::EVENT_MBUTTONUP;
00444             } else if (arg3 > 500) {
00445                 down = Common::EVENT_RBUTTONDOWN;
00446                 up = Common::EVENT_RBUTTONUP;
00447             } else {
00448                 down = Common::EVENT_LBUTTONDOWN;
00449                 up = Common::EVENT_LBUTTONUP;
00450             }
00451 
00452             lockMutex(_event_queue_lock);
00453 
00454             if (_queuedEventTime)
00455                 _event_queue.push(_queuedEvent);
00456 
00457             if (!_touchpad_mode)
00458                 _event_queue.push(e);
00459 
00460             e.type = down;
00461             _event_queue.push(e);
00462 
00463             e.type = up;
00464             _queuedEvent = e;
00465             _queuedEventTime = getMillis() + kQueuedInputEventDelay;
00466 
00467             unlockMutex(_event_queue_lock);
00468         } else {
00469             keyPress(Common::KEYCODE_RETURN, KeyReceiver::PRESS);
00470         }
00471 
00472         return;
00473 
00474     case JE_DOUBLE_TAP:
00475         if (_show_mouse) {
00476             e.type = Common::EVENT_MOUSEMOVE;
00477 
00478             if (_touchpad_mode) {
00479                 e.mouse = getEventManager()->getMousePos();
00480             } else {
00481                 scaleMouse(e.mouse, arg1, arg2);
00482                 clipMouse(e.mouse);
00483             }
00484 
00485             {
00486                 Common::EventType dptype = Common::EVENT_INVALID;
00487 
00488                 switch (arg3) {
00489                 case JACTION_DOWN:
00490                     dptype = Common::EVENT_LBUTTONDOWN;
00491                     _touch_pt_dt.x = -1;
00492                     _touch_pt_dt.y = -1;
00493                     break;
00494                 case JACTION_UP:
00495                     dptype = Common::EVENT_LBUTTONUP;
00496                     break;
00497                 // held and moved
00498                 case JACTION_MOVE:
00499                     if (_touch_pt_dt.x == -1 && _touch_pt_dt.y == -1) {
00500                         _touch_pt_dt.x = arg1;
00501                         _touch_pt_dt.y = arg2;
00502                         return;
00503                     }
00504 
00505                     dptype = Common::EVENT_MOUSEMOVE;
00506 
00507                     if (_touchpad_mode) {
00508                         scaleMouse(e.mouse, arg1 - _touch_pt_dt.x,
00509                                     arg2 - _touch_pt_dt.y, false);
00510                         e.mouse += _touch_pt_down;
00511 
00512                         clipMouse(e.mouse);
00513                     }
00514 
00515                     break;
00516                 default:
00517                     LOGE("unhandled jaction on double tap: %d", arg3);
00518                     return;
00519                 }
00520 
00521                 lockMutex(_event_queue_lock);
00522                 _event_queue.push(e);
00523                 e.type = dptype;
00524                 _event_queue.push(e);
00525                 unlockMutex(_event_queue_lock);
00526             }
00527         } else {
00528             keyPress(Common::KEYCODE_u, KeyReceiver::PRESS);
00529         }
00530 
00531         return;
00532 
00533 
00534     case JE_TOUCH:
00535     case JE_MULTI:
00536     {
00537         if (!_show_mouse) {
00538             _touchControls.update(arg1, arg2, arg3, arg4);
00539             return;
00540         }
00541         switch (arg2) {
00542         case JACTION_POINTER_DOWN:
00543             if (arg1 > _fingersDown)
00544                 _fingersDown = arg1;
00545                 /* no break */
00546 
00547         case JACTION_DOWN:
00548         case JACTION_MOVE:
00549             return;
00550 
00551         case JACTION_UP:
00552         case JACTION_POINTER_UP: {
00553             if (_show_mouse) {
00554                 if (arg1 != _fingersDown)
00555                     return;
00556                 Common::EventType up;
00557 
00558                 switch (_fingersDown) {
00559                 case 1:
00560                     e.type = Common::EVENT_RBUTTONDOWN;
00561                     up = Common::EVENT_RBUTTONUP;
00562                     break;
00563                 case 2:
00564                     e.type = Common::EVENT_MBUTTONDOWN;
00565                     up = Common::EVENT_MBUTTONUP;
00566                     break;
00567                 default:
00568                     LOGD("unmapped multi tap: %d", _fingersDown);
00569                     return;
00570                 }
00571 
00572                 e.mouse = getEventManager()->getMousePos();
00573 
00574                 lockMutex(_event_queue_lock);
00575 
00576                 if (_queuedEventTime)
00577                     _event_queue.push(_queuedEvent);
00578 
00579                 _event_queue.push(e);
00580 
00581                 e.type = up;
00582                 _queuedEvent = e;
00583                 _queuedEventTime = getMillis() + kQueuedInputEventDelay;
00584 
00585                 unlockMutex(_event_queue_lock);
00586             }
00587             return;
00588         }
00589         }
00590 
00591         return;
00592     }
00593 
00594     case JE_BALL:
00595         e.mouse = getEventManager()->getMousePos();
00596 
00597         switch (arg1) {
00598         case JACTION_DOWN:
00599             e.type = Common::EVENT_LBUTTONDOWN;
00600             break;
00601         case JACTION_UP:
00602             e.type = Common::EVENT_LBUTTONUP;
00603             break;
00604         case JACTION_MOVE:
00605             e.type = Common::EVENT_MOUSEMOVE;
00606 
00607             // already multiplied by 100
00608             e.mouse.x += arg2 * _trackball_scale / _eventScaleX;
00609             e.mouse.y += arg3 * _trackball_scale / _eventScaleY;
00610 
00611             clipMouse(e.mouse);
00612 
00613             break;
00614         default:
00615             LOGE("unhandled jaction on system key: %d", arg1);
00616             return;
00617         }
00618 
00619         pushEvent(e);
00620 
00621         return;
00622 
00623     case JE_QUIT:
00624         e.type = Common::EVENT_QUIT;
00625 
00626         pushEvent(e);
00627 
00628         return;
00629 
00630     default:
00631         LOGE("unknown jevent type: %d", type);
00632 
00633         break;
00634     }
00635 }
00636 
00637 bool OSystem_Android::pollEvent(Common::Event &event) {
00638     //ENTER();
00639 
00640     if (pthread_self() == _main_thread) {
00641         if (_screen_changeid != JNI::surface_changeid) {
00642             if (JNI::egl_surface_width > 0 && JNI::egl_surface_height > 0) {
00643                 // surface changed
00644                 JNI::deinitSurface();
00645                 initSurface();
00646                 initViewport();
00647                 updateScreenRect();
00648                 updateEventScale();
00649 
00650                 // double buffered, flip twice
00651                 clearScreen(kClearUpdate, 2);
00652 
00653                 event.type = Common::EVENT_SCREEN_CHANGED;
00654 
00655                 return true;
00656             } else {
00657                 // surface lost
00658                 deinitSurface();
00659             }
00660         }
00661 
00662         if (JNI::pause) {
00663             deinitSurface();
00664 
00665             LOGD("main thread going to sleep");
00666             sem_wait(&JNI::pause_sem);
00667             LOGD("main thread woke up");
00668         }
00669     }
00670 
00671     lockMutex(_event_queue_lock);
00672 
00673     if (_queuedEventTime && (getMillis() > _queuedEventTime)) {
00674         event = _queuedEvent;
00675         _queuedEventTime = 0;
00676         unlockMutex(_event_queue_lock);
00677         return true;
00678     }
00679 
00680     if (_event_queue.empty()) {
00681         unlockMutex(_event_queue_lock);
00682         return false;
00683     }
00684 
00685     event = _event_queue.pop();
00686 
00687     unlockMutex(_event_queue_lock);
00688 
00689     if (event.type == Common::EVENT_MOUSEMOVE) {
00690         const Common::Point &m = getEventManager()->getMousePos();
00691 
00692         if (m != event.mouse)
00693             _force_redraw = true;
00694     }
00695 
00696     return true;
00697 }
00698 
00699 void OSystem_Android::pushEvent(const Common::Event &event) {
00700     lockMutex(_event_queue_lock);
00701     _event_queue.push(event);
00702     unlockMutex(_event_queue_lock);
00703 }
00704 
00705 void OSystem_Android::keyPress(const Common::KeyCode keycode, const KeyReceiver::KeyPressType type) {
00706     Common::Event e;
00707     e.kbd.keycode = keycode;
00708     lockMutex(_event_queue_lock);
00709     if (type == KeyReceiver::DOWN || type == KeyReceiver::PRESS) {
00710         e.type = Common::EVENT_KEYDOWN;
00711         _event_queue.push(e);
00712     }
00713     if (type == KeyReceiver::UP || type == KeyReceiver::PRESS) {
00714         e.type = Common::EVENT_KEYUP;
00715         _event_queue.push(e);
00716     }
00717     unlockMutex(_event_queue_lock);
00718 }
00719 
00720 #endif


Generated on Sat Feb 23 2019 05:01:02 for ResidualVM by doxygen 1.7.1
curved edge   curved edge