Skip to content

Latest commit

 

History

History
2328 lines (1991 loc) · 81.7 KB

SDLActivity.java

File metadata and controls

2328 lines (1991 loc) · 81.7 KB
 
1
2
package org.libsdl.app;
Oct 27, 2020
Oct 27, 2020
3
4
5
6
7
8
9
10
11
12
13
14
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.UiModeManager;
import android.content.ClipboardManager;
import android.content.ClipData;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
Feb 6, 2018
Feb 6, 2018
15
import android.content.res.Configuration;
Oct 27, 2020
Oct 27, 2020
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
Oct 15, 2015
Oct 15, 2015
30
import android.text.InputType;
Oct 27, 2020
Oct 27, 2020
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
47
48
49
50
51
52
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.LinearLayout;
Oct 27, 2020
Oct 27, 2020
53
import android.widget.RelativeLayout;
54
import android.widget.TextView;
Oct 27, 2020
Oct 27, 2020
55
56
57
58
import java.util.Hashtable;
import java.util.Locale;
59
60
61
62
/**
SDL Activity
*/
Jun 18, 2018
Jun 18, 2018
63
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
64
65
private static final String TAG = "SDL";
Jan 14, 2019
Jan 14, 2019
66
public static boolean mIsResumedCalled, mHasFocus;
Apr 22, 2019
Apr 22, 2019
67
public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24);
Apr 8, 2017
Apr 8, 2017
68
Mar 16, 2018
Mar 16, 2018
69
// Cursor types
Oct 27, 2020
Oct 27, 2020
70
// private static final int SDL_SYSTEM_CURSOR_NONE = -1;
Mar 16, 2018
Mar 16, 2018
71
72
73
74
75
76
77
78
79
80
81
82
83
private static final int SDL_SYSTEM_CURSOR_ARROW = 0;
private static final int SDL_SYSTEM_CURSOR_IBEAM = 1;
private static final int SDL_SYSTEM_CURSOR_WAIT = 2;
private static final int SDL_SYSTEM_CURSOR_CROSSHAIR = 3;
private static final int SDL_SYSTEM_CURSOR_WAITARROW = 4;
private static final int SDL_SYSTEM_CURSOR_SIZENWSE = 5;
private static final int SDL_SYSTEM_CURSOR_SIZENESW = 6;
private static final int SDL_SYSTEM_CURSOR_SIZEWE = 7;
private static final int SDL_SYSTEM_CURSOR_SIZENS = 8;
private static final int SDL_SYSTEM_CURSOR_SIZEALL = 9;
private static final int SDL_SYSTEM_CURSOR_NO = 10;
private static final int SDL_SYSTEM_CURSOR_HAND = 11;
Aug 23, 2018
Aug 23, 2018
84
85
86
87
88
89
90
protected static final int SDL_ORIENTATION_UNKNOWN = 0;
protected static final int SDL_ORIENTATION_LANDSCAPE = 1;
protected static final int SDL_ORIENTATION_LANDSCAPE_FLIPPED = 2;
protected static final int SDL_ORIENTATION_PORTRAIT = 3;
protected static final int SDL_ORIENTATION_PORTRAIT_FLIPPED = 4;
protected static int mCurrentOrientation;
May 8, 2020
May 8, 2020
91
protected static Locale mCurrentLocale;
Aug 23, 2018
Aug 23, 2018
92
Apr 8, 2017
Apr 8, 2017
93
94
// Handle the state of the native layer
public enum NativeState {
Oct 23, 2017
Oct 23, 2017
95
INIT, RESUMED, PAUSED
Apr 8, 2017
Apr 8, 2017
96
97
98
99
100
}
public static NativeState mNextNativeState;
public static NativeState mCurrentNativeState;
101
/** If shared libraries (e.g. SDL or the native application) could not be loaded. */
Sep 25, 2020
Sep 25, 2020
102
public static boolean mBrokenLibraries = true;
103
104
105
106
107
// Main components
protected static SDLActivity mSingleton;
protected static SDLSurface mSurface;
protected static View mTextEdit;
Aug 14, 2017
Aug 14, 2017
108
protected static boolean mScreenKeyboardShown;
109
protected static ViewGroup mLayout;
Aug 28, 2017
Aug 28, 2017
110
protected static SDLClipboardHandler mClipboardHandler;
Nov 3, 2018
Nov 3, 2018
111
protected static Hashtable<Integer, PointerIcon> mCursors;
Mar 16, 2018
Mar 16, 2018
112
protected static int mLastCursorID;
May 29, 2018
May 29, 2018
113
protected static SDLGenericMotionListener_API12 mMotionListener;
Aug 9, 2018
Aug 9, 2018
114
protected static HIDDeviceManager mHIDDeviceManager;
115
116
117
118
// This is what SDL runs in. It invokes SDL_main(), eventually
protected static Thread mSDLThread;
May 29, 2018
May 29, 2018
119
120
protected static SDLGenericMotionListener_API12 getMotionListener() {
if (mMotionListener == null) {
Jun 5, 2018
Jun 5, 2018
121
122
if (Build.VERSION.SDK_INT >= 26) {
mMotionListener = new SDLGenericMotionListener_API26();
Oct 27, 2020
Oct 27, 2020
123
} else if (Build.VERSION.SDK_INT >= 24) {
May 29, 2018
May 29, 2018
124
125
126
127
128
129
130
131
132
mMotionListener = new SDLGenericMotionListener_API24();
} else {
mMotionListener = new SDLGenericMotionListener_API12();
}
}
return mMotionListener;
}
Aug 28, 2017
Aug 28, 2017
133
134
135
136
137
138
139
140
141
142
143
144
/**
* This method returns the name of the shared object with the application entry point
* It can be overridden by derived classes.
*/
protected String getMainSharedObject() {
String library;
String[] libraries = SDLActivity.mSingleton.getLibraries();
if (libraries.length > 0) {
library = "lib" + libraries[libraries.length - 1] + ".so";
} else {
library = "libmain.so";
}
Sep 5, 2018
Sep 5, 2018
145
return getContext().getApplicationInfo().nativeLibraryDir + "/" + library;
Aug 28, 2017
Aug 28, 2017
146
147
148
149
150
151
152
153
154
155
}
/**
* This method returns the name of the application entry point
* It can be overridden by derived classes.
*/
protected String getMainFunction() {
return "SDL_main";
}
156
157
158
159
160
161
162
163
164
165
/**
* This method is called by SDL before loading the native shared libraries.
* It can be overridden to provide names of shared libraries to be loaded.
* The default implementation returns the defaults. It never returns null.
* An array returned by a new implementation must at least contain "SDL2".
* Also keep in mind that the order the libraries are loaded may matter.
* @return names of shared libraries to be loaded (e.g. "SDL2", "main").
*/
protected String[] getLibraries() {
return new String[] {
Apr 17, 2019
Apr 17, 2019
166
"hidapi",
167
168
169
170
171
172
173
174
175
176
177
178
"SDL2",
// "SDL2_image",
// "SDL2_mixer",
// "SDL2_net",
// "SDL2_ttf",
"main"
};
}
// Load the .so
public void loadLibraries() {
for (String lib : getLibraries()) {
Oct 4, 2018
Oct 4, 2018
179
SDL.loadLibrary(lib);
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
}
}
/**
* This method is called by SDL before starting the native application thread.
* It can be overridden to provide the arguments after the application name.
* The default implementation returns an empty array. It never returns null.
* @return arguments for the native application.
*/
protected String[] getArguments() {
return new String[0];
}
public static void initialize() {
// The static nature of the singleton and Android quirkyness force us to initialize everything here
// Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
mSingleton = null;
mSurface = null;
mTextEdit = null;
mLayout = null;
Aug 28, 2017
Aug 28, 2017
200
mClipboardHandler = null;
Oct 28, 2020
Oct 28, 2020
201
mCursors = new Hashtable<Integer, PointerIcon>();
Mar 16, 2018
Mar 16, 2018
202
mLastCursorID = 0;
Apr 8, 2017
Apr 8, 2017
204
mIsResumedCalled = false;
Apr 8, 2017
Apr 8, 2017
206
207
mNextNativeState = NativeState.INIT;
mCurrentNativeState = NativeState.INIT;
208
209
210
211
212
}
// Setup
@Override
protected void onCreate(Bundle savedInstanceState) {
Oct 10, 2018
Oct 10, 2018
213
214
Log.v(TAG, "Device: " + Build.DEVICE);
Log.v(TAG, "Model: " + Build.MODEL);
Aug 28, 2017
Aug 28, 2017
215
Log.v(TAG, "onCreate()");
216
217
super.onCreate(savedInstanceState);
Jan 10, 2019
Jan 10, 2019
218
219
220
221
222
223
try {
Thread.currentThread().setName("SDLActivity");
} catch (Exception e) {
Log.v(TAG, "modify thread properties failed " + e.toString());
}
224
225
226
227
// Load shared libraries
String errorMsgBrokenLib = "";
try {
loadLibraries();
Sep 25, 2020
Sep 25, 2020
228
mBrokenLibraries = false; /* success */
229
230
231
232
233
234
235
236
237
238
239
240
} catch(UnsatisfiedLinkError e) {
System.err.println(e.getMessage());
mBrokenLibraries = true;
errorMsgBrokenLib = e.getMessage();
} catch(Exception e) {
System.err.println(e.getMessage());
mBrokenLibraries = true;
errorMsgBrokenLib = e.getMessage();
}
if (mBrokenLibraries)
{
Dec 19, 2017
Dec 19, 2017
241
mSingleton = this;
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall."
+ System.getProperty("line.separator")
+ System.getProperty("line.separator")
+ "Error: " + errorMsgBrokenLib);
dlgAlert.setTitle("SDL Error");
dlgAlert.setPositiveButton("Exit",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,int id) {
// if this button is clicked, close current activity
SDLActivity.mSingleton.finish();
}
});
dlgAlert.setCancelable(false);
dlgAlert.create().show();
return;
}
Aug 28, 2017
Aug 28, 2017
262
// Set up JNI
Sep 22, 2017
Sep 22, 2017
263
SDL.setupJNI();
Aug 28, 2017
Aug 28, 2017
264
Sep 22, 2017
Sep 22, 2017
265
266
267
268
269
270
// Initialize state
SDL.initialize();
// So we can call stuff from static callbacks
mSingleton = this;
SDL.setContext(this);
Oct 27, 2020
Oct 27, 2020
272
mClipboardHandler = new SDLClipboardHandler();
Aug 28, 2017
Aug 28, 2017
273
Oct 8, 2018
Oct 8, 2018
274
mHIDDeviceManager = HIDDeviceManager.acquire(this);
Aug 9, 2018
Aug 9, 2018
275
Aug 28, 2017
Aug 28, 2017
276
277
278
// Set up the surface
mSurface = new SDLSurface(getApplication());
Jul 27, 2016
Jul 27, 2016
279
mLayout = new RelativeLayout(this);
280
281
mLayout.addView(mSurface);
Aug 23, 2018
Aug 23, 2018
282
283
// Get our current screen orientation and pass it down.
mCurrentOrientation = SDLActivity.getCurrentOrientation();
Mar 13, 2019
Mar 13, 2019
284
// Only record current orientation
Aug 23, 2018
Aug 23, 2018
285
286
SDLActivity.onNativeOrientationChanged(mCurrentOrientation);
May 8, 2020
May 8, 2020
287
288
289
290
291
292
293
294
295
try {
if (Build.VERSION.SDK_INT < 24) {
mCurrentLocale = getContext().getResources().getConfiguration().locale;
} else {
mCurrentLocale = getContext().getResources().getConfiguration().getLocales().get(0);
}
} catch(Exception ignored) {
}
296
setContentView(mLayout);
Oct 23, 2017
Oct 23, 2017
297
Feb 12, 2018
Feb 12, 2018
298
setWindowStyle(false);
Nov 2, 2017
Nov 2, 2017
299
Jun 18, 2018
Jun 18, 2018
300
301
getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(this);
302
303
304
305
306
307
308
309
310
311
312
// Get filename from "Open with" of another application
Intent intent = getIntent();
if (intent != null && intent.getData() != null) {
String filename = intent.getData().getPath();
if (filename != null) {
Log.v(TAG, "Got filename: " + filename);
SDLActivity.onNativeDropFile(filename);
}
}
}
Apr 22, 2019
Apr 22, 2019
313
protected void pauseNativeThread() {
Apr 8, 2017
Apr 8, 2017
314
315
mNextNativeState = NativeState.PAUSED;
mIsResumedCalled = false;
316
317
if (SDLActivity.mBrokenLibraries) {
Apr 22, 2019
Apr 22, 2019
318
return;
Apr 8, 2017
Apr 8, 2017
321
SDLActivity.handleNativeState();
Apr 22, 2019
Apr 22, 2019
324
protected void resumeNativeThread() {
Apr 8, 2017
Apr 8, 2017
325
326
mNextNativeState = NativeState.RESUMED;
mIsResumedCalled = true;
327
328
329
330
331
if (SDLActivity.mBrokenLibraries) {
return;
}
Apr 8, 2017
Apr 8, 2017
332
SDLActivity.handleNativeState();
Apr 22, 2019
Apr 22, 2019
335
336
337
338
339
// Events
@Override
protected void onPause() {
Log.v(TAG, "onPause()");
super.onPause();
Jan 26, 2020
Jan 26, 2020
340
341
342
343
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(true);
}
Apr 22, 2019
Apr 22, 2019
344
345
346
347
348
349
350
351
352
if (!mHasMultiWindow) {
pauseNativeThread();
}
}
@Override
protected void onResume() {
Log.v(TAG, "onResume()");
super.onResume();
Jan 26, 2020
Jan 26, 2020
353
354
355
356
if (mHIDDeviceManager != null) {
mHIDDeviceManager.setFrozen(false);
}
Apr 22, 2019
Apr 22, 2019
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
if (!mHasMultiWindow) {
resumeNativeThread();
}
}
@Override
protected void onStop() {
Log.v(TAG, "onStop()");
super.onStop();
if (mHasMultiWindow) {
pauseNativeThread();
}
}
@Override
protected void onStart() {
Log.v(TAG, "onStart()");
super.onStart();
if (mHasMultiWindow) {
resumeNativeThread();
}
}
Aug 23, 2018
Aug 23, 2018
380
381
382
383
384
385
386
387
388
389
public static int getCurrentOrientation() {
final Context context = SDLActivity.getContext();
final Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int result = SDL_ORIENTATION_UNKNOWN;
switch (display.getRotation()) {
case Surface.ROTATION_0:
result = SDL_ORIENTATION_PORTRAIT;
break;
Jan 10, 2019
Jan 10, 2019
390
Aug 23, 2018
Aug 23, 2018
391
392
393
case Surface.ROTATION_90:
result = SDL_ORIENTATION_LANDSCAPE;
break;
Jan 10, 2019
Jan 10, 2019
394
Aug 23, 2018
Aug 23, 2018
395
396
397
case Surface.ROTATION_180:
result = SDL_ORIENTATION_PORTRAIT_FLIPPED;
break;
Jan 10, 2019
Jan 10, 2019
398
Aug 23, 2018
Aug 23, 2018
399
400
401
402
403
404
405
case Surface.ROTATION_270:
result = SDL_ORIENTATION_LANDSCAPE_FLIPPED;
break;
}
return result;
}
406
407
408
409
410
411
412
413
414
415
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
if (SDLActivity.mBrokenLibraries) {
return;
}
Apr 22, 2019
Apr 22, 2019
416
mHasFocus = hasFocus;
Apr 8, 2017
Apr 8, 2017
418
mNextNativeState = NativeState.RESUMED;
Jun 5, 2018
Jun 5, 2018
419
SDLActivity.getMotionListener().reclaimRelativeMouseModeIfNeeded();
Apr 22, 2019
Apr 22, 2019
420
421
422
423
SDLActivity.handleNativeState();
nativeFocusChanged(true);
Apr 8, 2017
Apr 8, 2017
424
} else {
Apr 22, 2019
Apr 22, 2019
425
426
427
428
429
nativeFocusChanged(false);
if (!mHasMultiWindow) {
mNextNativeState = NativeState.PAUSED;
SDLActivity.handleNativeState();
}
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
}
}
@Override
public void onLowMemory() {
Log.v(TAG, "onLowMemory()");
super.onLowMemory();
if (SDLActivity.mBrokenLibraries) {
return;
}
SDLActivity.nativeLowMemory();
}
May 8, 2020
May 8, 2020
445
446
447
448
449
@Override
public void onConfigurationChanged(Configuration newConfig) {
Log.v(TAG, "onConfigurationChanged()");
super.onConfigurationChanged(newConfig);
Sep 25, 2020
Sep 25, 2020
450
451
452
453
if (SDLActivity.mBrokenLibraries) {
return;
}
May 8, 2020
May 8, 2020
454
if (mCurrentLocale == null || !mCurrentLocale.equals(newConfig.locale)) {
May 8, 2020
May 8, 2020
455
456
457
458
459
mCurrentLocale = newConfig.locale;
SDLActivity.onNativeLocaleChanged();
}
}
460
461
462
463
@Override
protected void onDestroy() {
Log.v(TAG, "onDestroy()");
Aug 9, 2018
Aug 9, 2018
464
if (mHIDDeviceManager != null) {
Oct 8, 2018
Oct 8, 2018
465
HIDDeviceManager.release(mHIDDeviceManager);
Aug 9, 2018
Aug 9, 2018
466
467
468
mHIDDeviceManager = null;
}
469
470
471
472
473
474
if (SDLActivity.mBrokenLibraries) {
super.onDestroy();
return;
}
if (SDLActivity.mSDLThread != null) {
Jan 10, 2019
Jan 10, 2019
475
476
477
478
479
// Send Quit event to "SDLThread" thread
SDLActivity.nativeSendQuit();
// Wait for "SDLThread" thread to end
480
481
482
try {
SDLActivity.mSDLThread.join();
} catch(Exception e) {
Jan 10, 2019
Jan 10, 2019
483
Log.v(TAG, "Problem stopping SDLThread: " + e);
Jan 10, 2019
Jan 10, 2019
487
488
SDLActivity.nativeQuit();
489
490
491
super.onDestroy();
}
Jul 12, 2018
Jul 12, 2018
492
493
494
495
496
497
498
499
500
501
502
503
504
505
@Override
public void onBackPressed() {
// Check if we want to block the back button in case of mouse right click.
//
// If we do, the normal hardware back button will no longer work and people have to use home,
// but the mouse right click will work.
//
String trapBack = SDLActivity.nativeGetHint("SDL_ANDROID_TRAP_BACK_BUTTON");
if ((trapBack != null) && trapBack.equals("1")) {
// Exit and let the mouse handler handle this button (if appropriate)
return;
}
// Default system back button behavior.
Dec 20, 2019
Dec 20, 2019
506
507
508
if (!isFinishing()) {
super.onBackPressed();
}
Jul 12, 2018
Jul 12, 2018
509
510
511
512
513
514
515
516
517
518
519
520
}
// Called by JNI from SDL.
public static void manualBackButton() {
mSingleton.pressBackButton();
}
// Used to get us onto the activity's main thread
public void pressBackButton() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Dec 20, 2019
Dec 20, 2019
521
522
523
if (!SDLActivity.this.isFinishing()) {
SDLActivity.this.superOnBackPressed();
}
Jul 12, 2018
Jul 12, 2018
524
525
526
527
528
529
}
});
}
// Used to access the system back behavior.
public void superOnBackPressed() {
Jun 11, 2019
Jun 11, 2019
530
super.onBackPressed();
Jul 12, 2018
Jul 12, 2018
531
532
}
533
534
535
536
537
538
539
540
541
542
543
544
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (SDLActivity.mBrokenLibraries) {
return false;
}
int keyCode = event.getKeyCode();
// Ignore certain special keys so they're handled by Android
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
keyCode == KeyEvent.KEYCODE_CAMERA ||
Aug 31, 2017
Aug 31, 2017
545
546
keyCode == KeyEvent.KEYCODE_ZOOM_IN || /* API 11 */
keyCode == KeyEvent.KEYCODE_ZOOM_OUT /* API 11 */
547
548
549
550
551
552
) {
return false;
}
return super.dispatchKeyEvent(event);
}
Apr 8, 2017
Apr 8, 2017
553
554
555
556
557
558
/* Transition to next state */
public static void handleNativeState() {
if (mNextNativeState == mCurrentNativeState) {
// Already in same state, discard.
return;
Apr 8, 2017
Apr 8, 2017
561
562
563
564
565
// Try a transition to init state
if (mNextNativeState == NativeState.INIT) {
mCurrentNativeState = mNextNativeState;
return;
Apr 8, 2017
Apr 8, 2017
567
568
569
// Try a transition to paused state
if (mNextNativeState == NativeState.PAUSED) {
Jan 10, 2019
Jan 10, 2019
570
571
572
573
if (mSDLThread != null) {
nativePause();
}
if (mSurface != null) {
Oct 24, 2017
Oct 24, 2017
574
mSurface.handlePause();
Jan 10, 2019
Jan 10, 2019
575
}
Apr 8, 2017
Apr 8, 2017
576
577
578
579
580
581
mCurrentNativeState = mNextNativeState;
return;
}
// Try a transition to resumed state
if (mNextNativeState == NativeState.RESUMED) {
Jan 14, 2019
Jan 14, 2019
582
if (mSurface.mIsSurfaceReady && mHasFocus && mIsResumedCalled) {
Aug 28, 2017
Aug 28, 2017
583
584
585
586
587
if (mSDLThread == null) {
// This is the entry point to the C app.
// Start up the C app thread and enable sensor input for the first time
// FIXME: Why aren't we enabling sensor input at start?
Nov 2, 2017
Nov 2, 2017
588
mSDLThread = new Thread(new SDLMain(), "SDLThread");
Aug 28, 2017
Aug 28, 2017
589
590
mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
mSDLThread.start();
Jan 16, 2019
Jan 16, 2019
591
Jan 14, 2019
Jan 14, 2019
592
593
594
// No nativeResume(), don't signal Android_ResumeSem
} else {
nativeResume();
Aug 28, 2017
Aug 28, 2017
595
}
Oct 27, 2020
Oct 27, 2020
596
mSurface.handleResume();
Aug 28, 2017
Aug 28, 2017
597
598
599
600
mCurrentNativeState = mNextNativeState;
}
}
601
602
603
604
}
// Messages from the SDLMain thread
static final int COMMAND_CHANGE_TITLE = 1;
Feb 12, 2018
Feb 12, 2018
605
static final int COMMAND_CHANGE_WINDOW_STYLE = 2;
606
static final int COMMAND_TEXTEDIT_HIDE = 3;
Jan 2, 2019
Jan 2, 2019
607
static final int COMMAND_CHANGE_SURFACEVIEW_FORMAT = 4;
608
609
610
611
static final int COMMAND_SET_KEEP_SCREEN_ON = 5;
protected static final int COMMAND_USER = 0x8000;
Jun 18, 2018
Jun 18, 2018
612
613
protected static boolean mFullscreenModeActive;
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
/**
* This method is called by SDL if SDL did not handle a message itself.
* This happens if a received message contains an unsupported command.
* Method can be overwritten to handle Messages in a different class.
* @param command the command of the message.
* @param param the parameter of the message. May be null.
* @return if the message was handled in overridden method.
*/
protected boolean onUnhandledMessage(int command, Object param) {
return false;
}
/**
* A Handler class for Messages from native SDL applications.
* It uses current Activities as target (e.g. for the title).
* static to prevent implicit references to enclosing object.
*/
protected static class SDLCommandHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Sep 22, 2017
Sep 22, 2017
634
Context context = SDL.getContext();
635
636
637
638
639
640
641
642
643
644
645
646
if (context == null) {
Log.e(TAG, "error handling message, getContext() returned null");
return;
}
switch (msg.arg1) {
case COMMAND_CHANGE_TITLE:
if (context instanceof Activity) {
((Activity) context).setTitle((String)msg.obj);
} else {
Log.e(TAG, "error handling message, getContext() returned no Activity");
}
break;
Feb 12, 2018
Feb 12, 2018
647
case COMMAND_CHANGE_WINDOW_STYLE:
Oct 27, 2020
Oct 27, 2020
648
649
650
651
652
653
if (Build.VERSION.SDK_INT >= 19) {
if (context instanceof Activity) {
Window window = ((Activity) context).getWindow();
if (window != null) {
if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
Feb 12, 2018
Feb 12, 2018
654
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
Jun 13, 2018
Jun 13, 2018
655
656
657
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
Sep 25, 2018
Sep 25, 2018
658
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
Oct 27, 2020
Oct 27, 2020
659
660
661
662
663
664
665
666
667
668
669
window.getDecorView().setSystemUiVisibility(flags);
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
SDLActivity.mFullscreenModeActive = true;
} else {
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
window.getDecorView().setSystemUiVisibility(flags);
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
SDLActivity.mFullscreenModeActive = false;
}
Feb 12, 2018
Feb 12, 2018
670
}
Oct 27, 2020
Oct 27, 2020
671
672
} else {
Log.e(TAG, "error handling message, getContext() returned no Activity");
Feb 12, 2018
Feb 12, 2018
673
674
675
}
}
break;
676
677
case COMMAND_TEXTEDIT_HIDE:
if (mTextEdit != null) {
Oct 1, 2016
Oct 1, 2016
678
679
680
// Note: On some devices setting view to GONE creates a flicker in landscape.
// Setting the View's sizes to 0 is similar to GONE but without the flicker.
// The sizes will be set to useful values when the keyboard is shown again.
Oct 2, 2016
Oct 2, 2016
681
mTextEdit.setLayoutParams(new RelativeLayout.LayoutParams(0, 0));
682
683
684
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
Jan 16, 2019
Jan 16, 2019
685
Aug 14, 2017
Aug 14, 2017
686
mScreenKeyboardShown = false;
Dec 19, 2019
Dec 19, 2019
687
688
mSurface.requestFocus();
689
690
691
692
}
break;
case COMMAND_SET_KEEP_SCREEN_ON:
{
Aug 28, 2017
Aug 28, 2017
693
694
695
if (context instanceof Activity) {
Window window = ((Activity) context).getWindow();
if (window != null) {
Oct 27, 2020
Oct 27, 2020
696
if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {
Aug 28, 2017
Aug 28, 2017
697
698
699
700
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
701
702
703
704
}
}
break;
}
Jan 2, 2019
Jan 2, 2019
705
706
case COMMAND_CHANGE_SURFACEVIEW_FORMAT:
{
Apr 23, 2019
Apr 23, 2019
707
int format = (Integer) msg.obj;
Jan 2, 2019
Jan 2, 2019
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
int pf;
if (SDLActivity.mSurface == null) {
return;
}
SurfaceHolder holder = SDLActivity.mSurface.getHolder();
if (holder == null) {
return;
}
if (format == 1) {
pf = PixelFormat.RGBA_8888;
} else if (format == 2) {
pf = PixelFormat.RGBX_8888;
} else {
pf = PixelFormat.RGB_565;
}
holder.setFormat(pf);
break;
}
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
default:
if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
Log.e(TAG, "error handling message, command is " + msg.arg1);
}
}
}
}
// Handler for the messages
Handler commandHandler = new SDLCommandHandler();
// Send a message from the SDLMain thread
boolean sendCommand(int command, Object data) {
Message msg = commandHandler.obtainMessage();
msg.arg1 = command;
msg.obj = data;
Sep 29, 2018
Sep 29, 2018
747
748
boolean result = commandHandler.sendMessage(msg);
Oct 27, 2020
Oct 27, 2020
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
if (Build.VERSION.SDK_INT >= 19) {
if (command == COMMAND_CHANGE_WINDOW_STYLE) {
// Ensure we don't return until the resize has actually happened,
// or 500ms have passed.
boolean bShouldWait = false;
if (data instanceof Integer) {
// Let's figure out if we're already laid out fullscreen or not.
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
boolean bFullscreenLayout = ((realMetrics.widthPixels == mSurface.getWidth()) &&
(realMetrics.heightPixels == mSurface.getHeight()));
if ((Integer) data == 1) {
// If we aren't laid out fullscreen or actively in fullscreen mode already, we're going
// to change size and should wait for surfaceChanged() before we return, so the size
// is right back in native code. If we're already laid out fullscreen, though, we're
// not going to change size even if we change decor modes, so we shouldn't wait for
// surfaceChanged() -- which may not even happen -- and should return immediately.
bShouldWait = !bFullscreenLayout;
} else {
// If we're laid out fullscreen (even if the status bar and nav bar are present),
// or are actively in fullscreen, we're going to change size and should wait for
// surfaceChanged before we return, so the size is right back in native code.
bShouldWait = bFullscreenLayout;
}
Sep 29, 2018
Sep 29, 2018
778
}
Oct 22, 2018
Oct 22, 2018
779
Oct 27, 2020
Oct 27, 2020
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
if (bShouldWait && (SDLActivity.getContext() != null)) {
// We'll wait for the surfaceChanged() method, which will notify us
// when called. That way, we know our current size is really the
// size we need, instead of grabbing a size that's still got
// the navigation and/or status bars before they're hidden.
//
// We'll wait for up to half a second, because some devices
// take a surprisingly long time for the surface resize, but
// then we'll just give up and return.
//
synchronized (SDLActivity.getContext()) {
try {
SDLActivity.getContext().wait(500);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
Oct 22, 2018
Oct 22, 2018
796
}
Sep 29, 2018
Sep 29, 2018
797
798
799
800
801
}
}
}
return result;
802
803
804
}
// C functions we call
Aug 28, 2017
Aug 28, 2017
805
806
public static native int nativeSetupJNI();
public static native int nativeRunMain(String library, String function, Object arguments);
807
public static native void nativeLowMemory();
Jan 10, 2019
Jan 10, 2019
808
public static native void nativeSendQuit();
Jan 10, 2019
Jan 10, 2019
809
public static native void nativeQuit();
810
811
public static native void nativePause();
public static native void nativeResume();
Apr 22, 2019
Apr 22, 2019
812
public static native void nativeFocusChanged(boolean hasFocus);
813
public static native void onNativeDropFile(String filename);
Jan 17, 2019
Jan 17, 2019
814
815
public static native void nativeSetScreenResolution(int surfaceWidth, int surfaceHeight, int deviceWidth, int deviceHeight, int format, float rate);
public static native void onNativeResize();
816
817
public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode);
May 23, 2019
May 23, 2019
818
public static native boolean onNativeSoftReturnKey();
819
public static native void onNativeKeyboardFocusLost();
May 29, 2018
May 29, 2018
820
public static native void onNativeMouse(int button, int action, float x, float y, boolean relative);
821
822
823
824
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
int action, float x,
float y, float p);
public static native void onNativeAccel(float x, float y, float z);
Aug 28, 2017
Aug 28, 2017
825
public static native void onNativeClipboardChanged();
Jan 9, 2019
Jan 9, 2019
826
public static native void onNativeSurfaceCreated();
827
828
829
public static native void onNativeSurfaceChanged();
public static native void onNativeSurfaceDestroyed();
public static native String nativeGetHint(String name);
Nov 4, 2017
Nov 4, 2017
830
public static native void nativeSetenv(String name, String value);
Aug 23, 2018
Aug 23, 2018
831
public static native void onNativeOrientationChanged(int orientation);
Jan 10, 2019
Jan 10, 2019
832
public static native void nativeAddTouch(int touchId, String name);
Feb 12, 2020
Feb 12, 2020
833
public static native void nativePermissionResult(int requestCode, boolean result);
May 8, 2020
May 8, 2020
834
public static native void onNativeLocaleChanged();
835
836
837
838
839
840
841
842
843
/**
* This method is called by SDL using JNI.
*/
public static boolean setActivityTitle(String title) {
// Called from SDLMain() thread and can't directly affect the view
return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
}
Feb 12, 2018
Feb 12, 2018
844
845
846
847
848
849
850
851
/**
* This method is called by SDL using JNI.
*/
public static void setWindowStyle(boolean fullscreen) {
// Called from SDLMain() thread and can't directly affect the view
mSingleton.sendCommand(COMMAND_CHANGE_WINDOW_STYLE, fullscreen ? 1 : 0);
}
Aug 14, 2017
Aug 14, 2017
852
853
854
/**
* This method is called by SDL using JNI.
* This is a static method for JNI convenience, it calls a non-static method
Jan 16, 2019
Jan 16, 2019
855
* so that is can be overridden
Aug 14, 2017
Aug 14, 2017
856
857
858
*/
public static void setOrientation(int w, int h, boolean resizable, String hint)
{
Aug 29, 2017
Aug 29, 2017
859
860
861
if (mSingleton != null) {
mSingleton.setOrientationBis(w, h, resizable, hint);
}
Aug 14, 2017
Aug 14, 2017
862
}
Jan 16, 2019
Jan 16, 2019
863
Aug 14, 2017
Aug 14, 2017
864
865
866
/**
* This can be overridden
*/
Jan 16, 2019
Jan 16, 2019
867
public void setOrientationBis(int w, int h, boolean resizable, String hint)
Aug 14, 2017
Aug 14, 2017
868
{
Jan 17, 2020
Jan 17, 2020
869
870
int orientation_landscape = -1;
int orientation_portrait = -1;
Aug 14, 2017
Aug 14, 2017
871
Jan 17, 2020
Jan 17, 2020
872
/* If set, hint "explicitly controls which UI orientations are allowed". */
Oct 30, 2017
Oct 30, 2017
873
if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) {
Jan 17, 2020
Jan 17, 2020
874
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
Oct 30, 2017
Oct 30, 2017
875
} else if (hint.contains("LandscapeRight")) {
Jan 17, 2020
Jan 17, 2020
876
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
Oct 30, 2017
Oct 30, 2017
877
} else if (hint.contains("LandscapeLeft")) {
Jan 17, 2020
Jan 17, 2020
878
879
880
881
882
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
}
if (hint.contains("Portrait") && hint.contains("PortraitUpsideDown")) {
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
Oct 30, 2017
Oct 30, 2017
883
} else if (hint.contains("Portrait")) {
Jan 17, 2020
Jan 17, 2020
884
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
Oct 30, 2017
Oct 30, 2017
885
} else if (hint.contains("PortraitUpsideDown")) {
Jan 17, 2020
Jan 17, 2020
886
orientation_portrait = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
Oct 30, 2017
Oct 30, 2017
887
888
}
Oct 27, 2020
Oct 27, 2020
889
890
891
boolean is_landscape_allowed = (orientation_landscape != -1);
boolean is_portrait_allowed = (orientation_portrait != -1);
int req; /* Requested orientation */
Jan 17, 2020
Jan 17, 2020
892
893
894
895
896
897
898
899
900
901
902
903
/* No valid hint, nothing is explicitly allowed */
if (!is_portrait_allowed && !is_landscape_allowed) {
if (resizable) {
/* All orientations are allowed */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
} else {
/* Fixed window and nothing specified. Get orientation from w/h of created window */
req = (w > h ? ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE : ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
}
} else {
/* At least one orientation is allowed */
Oct 30, 2017
Oct 30, 2017
904
if (resizable) {
Jan 17, 2020
Jan 17, 2020
905
906
907
908
909
910
911
if (is_portrait_allowed && is_landscape_allowed) {
/* hint allows both landscape and portrait, promote to full sensor */
req = ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR;
} else {
/* Use the only one allowed "orientation" */
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
}
Aug 14, 2017
Aug 14, 2017
912
} else {
Jan 17, 2020
Jan 17, 2020
913
914
915
/* Fixed window and both orientations are allowed. Choose one. */
if (is_portrait_allowed && is_landscape_allowed) {
req = (w > h ? orientation_landscape : orientation_portrait);
Oct 30, 2017
Oct 30, 2017
916
} else {
Jan 17, 2020
Jan 17, 2020
917
918
/* Use the only one allowed "orientation" */
req = (is_landscape_allowed ? orientation_landscape : orientation_portrait);
Oct 30, 2017
Oct 30, 2017
919
}
Aug 14, 2017
Aug 14, 2017
920
}
Oct 30, 2017
Oct 30, 2017
921
}
Aug 14, 2017
Aug 14, 2017
922
Apr 28, 2020
Apr 28, 2020
923
Log.v(TAG, "setOrientation() requestedOrientation=" + req + " width=" + w +" height="+ h +" resizable=" + resizable + " hint=" + hint);
Jan 17, 2020
Jan 17, 2020
924
mSingleton.setRequestedOrientation(req);
Aug 14, 2017
Aug 14, 2017
925
926
}
Jun 10, 2019
Jun 10, 2019
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
/**
* This method is called by SDL using JNI.
*/
public static void minimizeWindow() {
if (mSingleton == null) {
return;
}
Intent startMain = new Intent(Intent.ACTION_MAIN);
startMain.addCategory(Intent.CATEGORY_HOME);
startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mSingleton.startActivity(startMain);
}
/**
* This method is called by SDL using JNI.
*/
public static boolean shouldMinimizeOnFocusLoss() {
/*
if (Build.VERSION.SDK_INT >= 24) {
if (mSingleton == null) {
return true;
}
if (mSingleton.isInMultiWindowMode()) {
return false;
}
if (mSingleton.isInPictureInPictureMode()) {
return false;
}
}
return true;
*/
return false;
}
Aug 14, 2017
Aug 14, 2017
966
967
968
/**
* This method is called by SDL using JNI.
*/
Jan 16, 2019
Jan 16, 2019
969
public static boolean isScreenKeyboardShown()
Aug 14, 2017
Aug 14, 2017
970
{
Oct 14, 2017
Oct 14, 2017
971
972
973
if (mTextEdit == null) {
return false;
}
Aug 14, 2017
Aug 14, 2017
974
Oct 14, 2017
Oct 14, 2017
975
976
977
if (!mScreenKeyboardShown) {
return false;
}
Aug 14, 2017
Aug 14, 2017
978
Oct 14, 2017
Oct 14, 2017
979
980
InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
return imm.isAcceptingText();
Aug 14, 2017
Aug 14, 2017
981
982
983
}
May 29, 2018
May 29, 2018
984
985
986
987
988
/**
* This method is called by SDL using JNI.
*/
public static boolean supportsRelativeMouse()
{
Jun 18, 2018
Jun 18, 2018
989
990
991
992
993
// ChromeOS doesn't provide relative mouse motion via the Android 7 APIs
if (isChromebook()) {
return false;
}
Jan 16, 2019
Jan 16, 2019
994
// DeX mode in Samsung Experience 9.0 and earlier doesn't support relative mice properly under
Sep 24, 2018
Sep 24, 2018
995
996
997
998
999
1000
// Android 7 APIs, and simply returns no data under Android 8 APIs.
//
// This is fixed in Samsung Experience 9.5, which corresponds to Android 8.1.0, and
// thus SDK version 27. If we are in DeX mode and not API 27 or higher, as a result,
// we should stick to relative mode.
//