57f931e356934049995e79404f0537a88dcb0c82
28 /**
29 SDL Activity
30 */
36 // Handle the state of the native layer
39 }
46 /** If shared libraries (e.g. SDL or the native application) could not be loaded. */
49 // If we want to separate mouse and touch events.
50 // This is only toggled in native code when a hint is set!
53 // Main components
62 // This is what SDL runs in. It invokes SDL_main(), eventually
65 /**
66 * This method returns the name of the shared object with the application entry point
67 * It can be overridden by derived classes.
68 */
70 String library;
76 }
78 }
80 /**
81 * This method returns the name of the application entry point
82 * It can be overridden by derived classes.
83 */
86 }
88 /**
89 * This method is called by SDL before loading the native shared libraries.
90 * It can be overridden to provide names of shared libraries to be loaded.
91 * The default implementation returns the defaults. It never returns null.
92 * An array returned by a new implementation must at least contain "SDL2".
93 * Also keep in mind that the order the libraries are loaded may matter.
94 * @return names of shared libraries to be loaded (e.g. "SDL2", "main").
95 */
99 // "SDL2_image",
100 // "SDL2_mixer",
101 // "SDL2_net",
102 // "SDL2_ttf",
103 "main"
104 };
105 }
107 // Load the .so
111 }
112 }
114 /**
115 * This method is called by SDL before starting the native application thread.
116 * It can be overridden to provide the arguments after the application name.
117 * The default implementation returns an empty array. It never returns null.
118 * @return arguments for the native application.
119 */
122 }
125 // The static nature of the singleton and Android quirkyness force us to initialize everything here
126 // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
140 }
142 // Setup
143 @Override
150 // Load shared libraries
162 }
165 {
167 dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall."
174 @Override
176 // if this button is clicked, close current activity
178 }
179 });
184 }
186 // Set up JNI
189 // Initialize state
192 // So we can call stuff from static callbacks
199 /* Before API 11, no clipboard notification (eg no SDL_CLIPBOARDUPDATE) */
201 }
203 // Set up the surface
211 // Get filename from "Open with" of another application
218 }
219 }
220 }
222 // Events
223 @Override
232 }
235 }
237 @Override
246 }
249 }
252 @Override
259 }
266 }
269 }
271 @Override
278 }
281 }
283 @Override
289 // Reset everything in case the user re opens the app
292 }
297 // Send a quit message to the application
301 // Now wait for the SDL thread to quit
307 }
310 //Log.v(TAG, "Finished waiting for SDL thread");
311 }
315 // Reset everything in case the user re opens the app
317 }
319 @Override
324 }
327 // Ignore certain special keys so they're handled by Android
333 ) {
335 }
337 }
339 /* Transition to next state */
343 // Already in same state, discard.
345 }
347 // Try a transition to init state
352 }
354 // Try a transition to paused state
360 }
362 // Try a transition to resumed state
366 // This is the entry point to the C app.
367 // Start up the C app thread and enable sensor input for the first time
368 // FIXME: Why aren't we enabling sensor input at start?
374 // Set up a listener thread to catch when the native thread ends
376 @Override
381 // Ignore any exception
383 // Native thread has finished
386 }
387 }
388 }
392 }
397 }
398 }
399 }
401 /* The native thread has finished */
405 }
408 // Messages from the SDLMain thread
416 /**
417 * This method is called by SDL if SDL did not handle a message itself.
418 * This happens if a received message contains an unsupported command.
419 * Method can be overwritten to handle Messages in a different class.
420 * @param command the command of the message.
421 * @param param the parameter of the message. May be null.
422 * @return if the message was handled in overridden method.
423 */
426 }
428 /**
429 * A Handler class for Messages from native SDL applications.
430 * It uses current Activities as target (e.g. for the title).
431 * static to prevent implicit references to enclosing object.
432 */
434 @Override
440 }
447 }
451 // Note: On some devices setting view to GONE creates a flicker in landscape.
452 // Setting the View's sizes to 0 is similar to GONE but without the flicker.
453 // The sizes will be set to useful values when the keyboard is shown again.
456 InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
460 }
463 {
471 }
472 }
473 }
475 }
477 if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
479 }
480 }
481 }
482 }
484 // Handler for the messages
487 // Send a message from the SDLMain thread
493 }
495 // C functions we call
517 /**
518 * This method is called by SDL using JNI.
519 */
521 // Called from SDLMain() thread and can't directly affect the view
523 }
525 /**
526 * This method is called by SDL using JNI.
527 * This is a static method for JNI convenience, it calls a non-static method
528 * so that is can be overridden
529 */
531 {
534 }
535 }
537 /**
538 * This can be overridden
539 */
541 {
557 }
558 }
560 /* no valid hint */
563 /* no fixed orientation */
569 }
570 }
571 }
573 Log.v("SDL", "setOrientation() orientation=" + orientation + " width=" + w +" height="+ h +" resizable=" + resizable + " hint=" + hint);
576 }
577 }
580 /**
581 * This method is called by SDL using JNI.
582 */
584 {
587 }
591 }
593 InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
596 }
598 /**
599 * This method is called by SDL using JNI.
600 */
604 }
606 }
608 /**
609 * This method is called by SDL using JNI.
610 */
613 }
616 /*
617 * This is used to regulate the pan&scan method to have some offset from
618 * the bottom edge of the input region and the top edge of an input
619 * method (soft keyboard)
620 */
630 }
632 @Override
644 }
649 InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
653 }
654 }
656 /**
657 * This method is called by SDL using JNI.
658 */
660 // Transfer the task to the main thread as a Runnable
662 }
666 // Key pressed with Ctrl should be sent as SDL_KEYDOWN/SDL_KEYUP and not SDL_TEXTINPUT
670 }
671 }
674 }
676 /**
677 * This method is called by SDL using JNI.
678 */
682 }
684 }
686 // Input
688 /**
689 * This method is called by SDL using JNI.
690 * @return an array which may be empty but is never null.
691 */
700 }
701 }
703 }
705 // APK expansion files support
707 /** com.android.vending.expansion.zipfile.ZipResourceFile object or null. */
710 /** com.android.vending.expansion.zipfile.ZipResourceFile's getInputStream() or null. */
713 /**
714 * This method is called by SDL using JNI.
715 * @return an InputStream on success or null if no expansion file was used.
716 * @throws IOException on errors. Message is set for the SDL error message.
717 */
719 // Get a ZipResourceFile representing a merger of both the main and patch files
724 }
728 }
730 Integer mainVersion;
731 Integer patchVersion;
738 }
741 // To avoid direct dependency on Google APK expansion library that is
742 // not a part of Android SDK we access it using reflection
754 }
755 }
757 // Get an input stream for a known file inside the expansion file ZIPs
758 InputStream fileStream;
762 // calling "getInputStream" failed
765 }
768 // calling "getInputStream" was successful but null was returned
770 }
773 }
775 // Messagebox
777 /** Result of current messagebox. Also used for blocking the calling thread. */
780 /** Id of current dialog. */
783 /**
784 * This method is called by SDL using JNI.
785 * Shows the messagebox from UI thread and block calling thread.
786 * buttonFlags, buttonIds and buttonTexts must have same length.
787 * @param buttonFlags array containing flags for every button.
788 * @param buttonIds array containing id for every button.
789 * @param buttonTexts array containing text for every button.
790 * @param colors null for default or array of length 5 containing colors.
791 * @return button id or -1.
792 */
804 // sanity checks
808 }
810 // collect arguments for Dialog
821 // trigger Dialog creation on UI thread
824 @Override
827 }
828 });
830 // block the calling thread
838 }
839 }
841 // return selected value
844 }
846 @Override
849 // TODO set values from "flags" to messagebox dialog
851 // get colors
872 }
874 // create dialog with title and a listener to wake up calling thread
880 @Override
884 }
885 }
886 });
888 // create text
895 }
897 // create buttons
912 @Override
916 }
917 });
919 // see SDL_messagebox.h
922 }
925 }
926 }
930 }
932 // TODO set color for border of messagebox button
933 }
937 // setting the color this way removes the style
940 // setting the color this way keeps the style (gradient, padding, etc.)
942 }
943 }
945 // TODO set color for selected messagebox button
946 }
948 }
950 // create content
958 }
960 // add content to dialog and return
964 @Override
970 }
972 }
974 }
975 });
978 }
980 /**
981 * This method is called by SDL using JNI.
982 */
985 }
987 /**
988 * This method is called by SDL using JNI.
989 */
992 }
994 /**
995 * This method is called by SDL using JNI.
996 */
999 }
1001 }
1003 /**
1004 Simple runnable to start the SDL application
1005 */
1007 @Override
1009 // Runs SDL_main()
1018 }
1019 }
1022 /**
1023 SDLSurface. This is what we draw on, so we need to know when it's created
1024 in order to do anything useful.
1026 Because of this, that's where we set up the SDL thread
1027 */
1031 // Sensors
1035 // Keep track of the surface size to normalize touch events
1038 // Startup
1049 mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
1054 }
1056 // Some arbitrary defaults to avoid a potential division by zero
1059 }
1063 }
1072 }
1076 }
1078 // Called when we have a valid drawing surface
1079 @Override
1083 }
1085 // Called when we lose the surface
1086 @Override
1090 // Transition to pause, if needed
1096 }
1098 // Called when the surface is resized
1099 @Override
1141 // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
1147 }
1159 {
1160 // Accept any
1161 }
1162 else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT)
1163 {
1166 }
1167 } else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
1170 }
1171 }
1173 // Special Patch for Square Resolution: Black Berry Passport
1181 }
1182 }
1188 }
1190 /* Surface is ready */
1193 /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
1197 }
1199 // Key events
1200 @Override
1202 // Dispatch the different events depending on where they come from
1203 // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
1204 // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
1205 //
1206 // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
1207 // SOURCE_JOYSTICK, while its key events arrive from the keyboard source
1208 // So, retrieve the device itself and check all of its sources
1210 // Note that we process events with specific key codes here
1214 }
1218 }
1219 }
1220 }
1224 //Log.v("SDL", "key down: " + keyCode);
1227 }
1229 //Log.v("SDL", "key up: " + keyCode);
1232 }
1233 }
1236 // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
1237 // they are ignored here because sending them as mouse input to SDL is messy
1242 // mark the event as handled or it will be handled by system
1243 // handling KEYCODE_BACK by system will call onBackPressed()
1245 }
1246 }
1247 }
1250 }
1252 // Touch events
1253 @Override
1255 /* Ref: http://developer.android.com/training/gestures/multi.html */
1264 // !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
1273 }
1274 }
1285 // may be larger than 1.0f on some devices
1286 // see the documentation of getPressure(i)
1288 }
1290 }
1295 // Primary pointer up/down, the index is always zero
1299 // Non primary pointer up/down
1302 }
1309 // may be larger than 1.0f on some devices
1310 // see the documentation of getPressure(i)
1312 }
1323 // may be larger than 1.0f on some devices
1324 // see the documentation of getPressure(i)
1326 }
1328 }
1333 }
1334 }
1337 }
1339 // Sensor events
1341 // TODO: This uses getDefaultSensor - what if we have >1 accels?
1349 }
1350 }
1352 @Override
1354 // TODO
1355 }
1357 @Override
1378 }
1382 }
1383 }
1384 }
1386 /* This is a fake invisible editor view that receives the input and defines the
1387 * pan&scan region
1388 */
1390 InputConnection ic;
1397 }
1399 @Override
1402 }
1404 @Override
1406 /*
1407 * This handles the hardware keyboard input
1408 */
1412 }
1418 }
1420 }
1422 //
1423 @Override
1425 // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event
1426 // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639
1427 // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
1428 // FIXME: A more effective solution would be to assume our Layout to be RelativeLayout or LinearLayout
1429 // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
1430 // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
1434 }
1435 }
1437 }
1439 @Override
1443 outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
1448 }
1449 }
1456 }
1458 @Override
1460 /*
1461 * This handles the keycodes from soft keyboard (and IME-translated input from hardkeyboard)
1462 */
1467 }
1473 }
1475 }
1477 @Override
1483 }
1485 @Override
1491 }
1497 @Override
1499 // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection
1500 // and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
1503 // backspace(s)
1508 }
1510 }
1513 }
1514 }
1522 }
1526 SDLClipboardHandler,
1532 mClipMgr = (android.content.ClipboardManager) SDL.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
1534 }
1536 @Override
1539 }
1541 @Override
1543 CharSequence text;
1547 }
1549 }
1551 @Override
1556 }
1558 @Override
1561 }
1563 }
1566 SDLClipboardHandler {
1571 mClipMgrOld = (android.text.ClipboardManager) SDL.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
1572 }
1574 @Override
1577 }
1579 @Override
1581 CharSequence text;
1585 }
1587 }
1589 @Override
1592 }
1593 }