6package org.qtproject.qt.android;
8import android.app.Activity;
9import android.content.Context;
10import android.content.Intent;
11import android.content.pm.ActivityInfo;
12import android.content.pm.ApplicationInfo;
13import android.content.pm.PackageManager;
14import android.content.pm.PackageManager.NameNotFoundException;
15import android.content.res.AssetManager;
16import android.content.res.Configuration;
17import android.graphics.Color;
18import android.graphics.drawable.ColorDrawable;
19import android.graphics.drawable.Drawable;
20import android.graphics.Rect;
21import android.net.LocalServerSocket;
22import android.net.LocalSocket;
23import android.os.Build;
24import android.os.Bundle;
25import android.os.Handler;
26import android.os.ResultReceiver;
27import android.text.method.MetaKeyKeyListener;
28import android.util.Base64;
29import android.util.DisplayMetrics;
30import android.util.Log;
31import android.util.TypedValue;
32import android.view.animation.AccelerateInterpolator;
33import android.view.animation.AlphaAnimation;
34import android.view.animation.Animation;
35import android.view.ContextMenu;
36import android.view.ContextMenu.ContextMenuInfo;
37import android.view.Display;
38import android.view.KeyCharacterMap;
39import android.view.KeyEvent;
40import android.view.Menu;
41import android.view.MenuItem;
42import android.view.MotionEvent;
43import android.view.Surface;
44import android.view.View;
45import android.view.ViewConfiguration;
46import android.view.ViewGroup;
47import android.view.Window;
48import android.view.WindowInsetsController;
49import android.view.WindowManager;
50import android.view.inputmethod.InputMethodManager;
51import android.view.ViewTreeObserver;
52import android.widget.ImageView;
53import android.widget.PopupMenu;
54import android.hardware.display.DisplayManager;
56import java.io.BufferedReader;
57import java.io.DataOutputStream;
59import java.io.FileWriter;
60import java.io.InputStreamReader;
61import java.io.IOException;
62import java.lang.reflect.Constructor;
63import java.lang.reflect.Method;
64import java.util.ArrayList;
65import java.util.HashMap;
66import java.util.Objects;
72 private Activity m_activity =
null;
73 private Method m_super_dispatchKeyEvent =
null;
74 private Method m_super_onRestoreInstanceState =
null;
75 private Method m_super_onRetainNonConfigurationInstance =
null;
76 private Method m_super_onSaveInstanceState =
null;
77 private Method m_super_onKeyDown =
null;
78 private Method m_super_onKeyUp =
null;
79 private Method m_super_onConfigurationChanged =
null;
80 private Method m_super_onActivityResult =
null;
81 private Method m_super_dispatchGenericMotionEvent =
null;
82 private Method m_super_onWindowFocusChanged =
null;
84 private static final String NATIVE_LIBRARIES_KEY =
"native.libraries";
85 private static final String BUNDLED_LIBRARIES_KEY =
"bundled.libraries";
86 private static final String MAIN_LIBRARY_KEY =
"main.library";
87 private static final String ENVIRONMENT_VARIABLES_KEY =
"environment.variables";
88 private static final String APPLICATION_PARAMETERS_KEY =
"application.parameters";
89 private static final String STATIC_INIT_CLASSES_KEY =
"static.init.classes";
95 private static String m_applicationParameters =
null;
97 private int m_currentRotation = -1;
98 private int m_nativeOrientation = Configuration.ORIENTATION_UNDEFINED;
100 private String m_mainLib;
101 private long m_metaState;
102 private int m_lastChar = 0;
103 private int m_softInputMode = 0;
105 private boolean m_started =
false;
106 private HashMap<Integer, QtSurface> m_surfaces =
null;
107 private HashMap<Integer, View> m_nativeViews =
null;
109 private ImageView m_splashScreen =
null;
110 private boolean m_splashScreenSticky =
false;
112 private InputMethodManager m_imm =
null;
113 private boolean m_quitApp =
true;
114 private View m_dummyView =
null;
115 private boolean m_keyboardIsVisible =
false;
117 private long m_showHideTimeStamp = System.nanoTime();
118 private int m_portraitKeyboardHeight = 0;
119 private int m_landscapeKeyboardHeight = 0;
120 private int m_probeKeyboardHeightDelay = 50;
125 private boolean m_isPluginRunning =
false;
132 if (m_systemUiVisibility == systemUiVisibility)
135 m_systemUiVisibility = systemUiVisibility;
136 setLayoutInDisplayCutoutMode();
138 int systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_VISIBLE;
139 switch (m_systemUiVisibility) {
141 m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
142 m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
145 m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
146 m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
147 systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
148 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
149 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
150 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
151 | View.SYSTEM_UI_FLAG_FULLSCREEN
152 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
156 m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
157 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
158 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
159 m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
163 m_activity.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibilityFlags);
165 m_layout.requestLayout();
168 private void setLayoutInDisplayCutoutMode()
170 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
171 int cutOutMode = WindowManager.
LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
173 cutOutMode = WindowManager.
LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
175 m_activity.getWindow().getAttributes().layoutInDisplayCutoutMode = cutOutMode;
189 return m_keyboardIsVisible;
193 private final int ImhHiddenText = 0x1;
194 private final int ImhSensitiveData = 0x2;
195 private final int ImhNoAutoUppercase = 0x4;
196 private final int ImhPreferNumbers = 0x8;
197 private final int ImhPreferUppercase = 0x10;
198 private final int ImhPreferLowercase = 0x20;
199 private final int ImhNoPredictiveText = 0x40;
201 private final int ImhDate = 0x80;
202 private final int ImhTime = 0x100;
204 private final int ImhPreferLatin = 0x200;
206 private final int ImhMultiLine = 0x400;
208 private final int ImhDigitsOnly = 0x10000;
209 private final int ImhFormattedNumbersOnly = 0x20000;
210 private final int ImhUppercaseOnly = 0x40000;
211 private final int ImhLowercaseOnly = 0x80000;
212 private final int ImhDialableCharactersOnly = 0x100000;
213 private final int ImhEmailCharactersOnly = 0x200000;
214 private final int ImhUrlCharactersOnly = 0x400000;
215 private final int ImhLatinOnly = 0x800000;
218 private final int EnterKeyDefault = 0;
219 private final int EnterKeyReturn = 1;
220 private final int EnterKeyDone = 2;
221 private final int EnterKeyGo = 3;
222 private final int EnterKeySend = 4;
223 private final int EnterKeySearch = 5;
224 private final int EnterKeyNext = 6;
225 private final int EnterKeyPrevious = 7;
236 if (m_showHideTimeStamp > timeStamp)
238 m_showHideTimeStamp = timeStamp;
240 if (m_keyboardIsVisible == visibility)
242 m_keyboardIsVisible = visibility;
245 if (visibility ==
false)
254 m_editText.postDelayed(
new Runnable() {
257 m_imm.restartInput(m_editText);
258 m_editText.m_optionsChanged =
false;
268 DisplayMetrics
metrics =
new DisplayMetrics();
269 m_activity.getWindowManager().getDefaultDisplay().getMetrics(
metrics);
273 final int visibleHeight;
275 visibleHeight = m_portraitKeyboardHeight != 0 ? m_portraitKeyboardHeight : metrics.heightPixels * 3 / 5;
277 visibleHeight = m_landscapeKeyboardHeight != 0 ? m_landscapeKeyboardHeight : metrics.heightPixels / 3;
279 if (m_softInputMode != 0) {
280 m_activity.getWindow().setSoftInputMode(m_softInputMode);
281 final boolean softInputIsHidden = (m_softInputMode & WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) != 0;
282 if (softInputIsHidden)
285 if (
height > visibleHeight)
286 m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
288 m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
291 int initialCapsMode = 0;
293 int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
295 switch (enterKeyType) {
297 imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
300 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
303 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
306 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
309 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
311 case EnterKeyPrevious:
312 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
316 int inputType = android.text.InputType.TYPE_CLASS_TEXT;
318 if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
319 inputType = android.text.InputType.TYPE_CLASS_NUMBER;
320 if ((inputHints & ImhFormattedNumbersOnly) != 0) {
321 inputType |= (android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL
322 | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
325 if ((inputHints & ImhHiddenText) != 0)
326 inputType |= android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD;
327 }
else if ((inputHints & ImhDialableCharactersOnly) != 0) {
328 inputType = android.text.InputType.TYPE_CLASS_PHONE;
329 }
else if ((inputHints & (ImhDate | ImhTime)) != 0) {
330 inputType = android.text.InputType.TYPE_CLASS_DATETIME;
331 if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) {
332 if ((inputHints & ImhDate) != 0)
333 inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE;
335 inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME;
338 if ((inputHints & ImhHiddenText) != 0) {
339 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
340 }
else if ((inputHints & ImhSensitiveData) != 0 ||
341 ((inputHints & ImhNoPredictiveText) != 0 &&
342 System.getenv(
"QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT") !=
null)) {
343 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD;
344 }
else if ((inputHints & ImhUrlCharactersOnly) != 0) {
345 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI;
346 if (enterKeyType == 0)
347 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
348 }
else if ((inputHints & ImhEmailCharactersOnly) != 0) {
349 inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;
352 if ((inputHints & ImhMultiLine) != 0) {
353 inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
356 imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
358 if ((inputHints & (ImhNoPredictiveText | ImhSensitiveData | ImhHiddenText)) != 0)
359 inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
361 if ((inputHints & ImhUppercaseOnly) != 0) {
362 initialCapsMode |= android.text.TextUtils.CAP_MODE_CHARACTERS;
363 inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
364 }
else if ((inputHints & ImhLowercaseOnly) == 0 && (inputHints & ImhNoAutoUppercase) == 0) {
365 initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES;
366 inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
370 if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
371 imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
378 m_editText.requestFocus();
379 m_editText.postDelayed(
new Runnable() {
382 m_imm.showSoftInput(m_editText, 0,
new ResultReceiver(
new Handler()) {
384 protected void onReceiveResult(
int resultCode,
Bundle resultData) {
385 switch (resultCode) {
386 case InputMethodManager.RESULT_SHOWN:
387 QtNativeInputConnection.updateCursorPosition();
389 case InputMethodManager.RESULT_UNCHANGED_SHOWN:
391 if (m_softInputMode == 0) {
393 m_layout.postDelayed(
new Runnable() {
396 if (!m_keyboardIsVisible)
398 DisplayMetrics
metrics =
new DisplayMetrics();
399 m_activity.getWindowManager().getDefaultDisplay().getMetrics(
metrics);
401 m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(
r);
402 if (
metrics.heightPixels !=
r.bottom) {
404 if (m_landscapeKeyboardHeight !=
r.bottom) {
405 m_landscapeKeyboardHeight =
r.bottom;
409 if (m_portraitKeyboardHeight !=
r.bottom) {
410 m_portraitKeyboardHeight =
r.bottom;
417 if (m_probeKeyboardHeightDelay < 1000)
418 m_probeKeyboardHeightDelay *= 2;
421 }, m_probeKeyboardHeightDelay);
424 case InputMethodManager.RESULT_HIDDEN:
425 case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
431 if (m_editText.m_optionsChanged) {
432 m_imm.restartInput(m_editText);
433 m_editText.m_optionsChanged =
false;
443 m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0,
new ResultReceiver(
new Handler()) {
445 protected void onReceiveResult(
int resultCode,
Bundle resultData) {
446 switch (resultCode) {
447 case InputMethodManager.RESULT_SHOWN:
448 case InputMethodManager.RESULT_UNCHANGED_SHOWN:
451 case InputMethodManager.RESULT_HIDDEN:
452 case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
460 int getAppIconSize(Activity
a)
462 int size =
a.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
463 if (size < 36 || size > 512) {
464 DisplayMetrics
metrics =
new DisplayMetrics();
465 a.getWindowManager().getDefaultDisplay().getMetrics(
metrics);
466 size = metrics.densityDpi / 10 * 3;
477 public void updateSelection(
int selStart,
int selEnd,
int candidatesStart,
int candidatesEnd)
482 m_imm.updateSelection(m_editText, selStart, selEnd, candidatesStart, candidatesEnd);
486 private static final int CursorHandleNotShown = 0;
487 private static final int CursorHandleShowNormal = 1;
488 private static final int CursorHandleShowSelection = 2;
489 private static final int CursorHandleShowEdit = 0x100;
494 if (m_leftSelectionHandle !=
null && m_rightSelectionHandle !=
null) {
495 width = Math.max(m_leftSelectionHandle.
width(), m_rightSelectionHandle.
width());
496 }
else if (m_cursorHandle !=
null) {
510 case CursorHandleNotShown:
511 if (m_cursorHandle !=
null) {
512 m_cursorHandle.
hide();
513 m_cursorHandle =
null;
515 if (m_rightSelectionHandle !=
null) {
516 m_rightSelectionHandle.
hide();
517 m_leftSelectionHandle.
hide();
518 m_rightSelectionHandle =
null;
519 m_leftSelectionHandle =
null;
521 if (m_editPopupMenu !=
null)
522 m_editPopupMenu.
hide();
525 case CursorHandleShowNormal:
526 if (m_cursorHandle ==
null) {
528 android.R.attr.textSelectHandle,
false);
531 if (m_rightSelectionHandle !=
null) {
532 m_rightSelectionHandle.
hide();
533 m_leftSelectionHandle.
hide();
534 m_rightSelectionHandle =
null;
535 m_leftSelectionHandle =
null;
539 case CursorHandleShowSelection:
540 if (m_rightSelectionHandle ==
null) {
542 !rtl ? android.R.attr.textSelectHandleLeft :
543 android.R.attr.textSelectHandleRight,
546 !rtl ? android.R.attr.textSelectHandleRight :
547 android.R.attr.textSelectHandleLeft,
552 if (m_cursorHandle !=
null) {
553 m_cursorHandle.
hide();
554 m_cursorHandle =
null;
556 mode |= CursorHandleShowEdit;
563 if ((
mode & CursorHandleShowEdit) == CursorHandleShowEdit && editButtons != 0) {
564 m_editPopupMenu.
setPosition(editX, editY, editButtons, m_cursorHandle, m_leftSelectionHandle,
565 m_rightSelectionHandle);
567 if (m_editPopupMenu !=
null)
568 m_editPopupMenu.
hide();
572 private final DisplayManager.DisplayListener displayListener =
new DisplayManager.DisplayListener()
575 public void onDisplayAdded(
int displayId) {
579 private boolean isSimilarRotation(
int r1,
int r2)
582 || (
r1 == Surface.ROTATION_0 &&
r2 == Surface.ROTATION_180)
583 || (
r1 == Surface.ROTATION_180 &&
r2 == Surface.ROTATION_0)
584 || (
r1 == Surface.ROTATION_90 &&
r2 == Surface.ROTATION_270)
585 || (
r1 == Surface.ROTATION_270 &&
r2 == Surface.ROTATION_90);
589 public void onDisplayChanged(
int displayId)
592 ? m_activity.getWindowManager().getDefaultDisplay()
593 : m_activity.getDisplay();
594 m_currentRotation =
display.getRotation();
600 QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation);
602 float refreshRate =
display.getRefreshRate();
603 QtNative.handleRefreshRateChanged(refreshRate);
604 QtNative.handleScreenChanged(displayId);
608 public void onDisplayRemoved(
int displayId) {
609 QtNative.handleScreenRemoved(displayId);
617 loadActivity(activity);
620 ViewGroup layoutParent = (ViewGroup)m_layout.getParent();
621 if (layoutParent !=
null)
622 layoutParent.removeView(m_layout);
624 m_activity.setContentView(m_layout);
628 }
catch (Exception
e) {
635 private void loadActivity(Activity activity)
636 throws NoSuchMethodException, PackageManager.NameNotFoundException
638 m_activity = activity;
641 setActionBarVisibility(
false);
643 Class<?> activityClass = m_activity.getClass();
644 m_super_dispatchKeyEvent =
645 activityClass.getMethod(
"super_dispatchKeyEvent", KeyEvent.class);
646 m_super_onRestoreInstanceState =
647 activityClass.getMethod(
"super_onRestoreInstanceState",
Bundle.class);
648 m_super_onRetainNonConfigurationInstance =
649 activityClass.getMethod(
"super_onRetainNonConfigurationInstance");
650 m_super_onSaveInstanceState =
651 activityClass.getMethod(
"super_onSaveInstanceState",
Bundle.class);
653 activityClass.getMethod(
"super_onKeyDown",
Integer.TYPE, KeyEvent.class);
655 activityClass.getMethod(
"super_onKeyUp",
Integer.TYPE, KeyEvent.class);
656 m_super_onConfigurationChanged =
657 activityClass.getMethod(
"super_onConfigurationChanged", Configuration.class);
658 m_super_onActivityResult =
659 activityClass.getMethod(
"super_onActivityResult",
Integer.TYPE,
Integer.TYPE, Intent.class);
660 m_super_onWindowFocusChanged =
661 activityClass.getMethod(
"super_onWindowFocusChanged",
Boolean.TYPE);
662 m_super_dispatchGenericMotionEvent =
663 activityClass.getMethod(
"super_dispatchGenericMotionEvent", MotionEvent.class);
665 m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode;
667 DisplayManager displayManager = (DisplayManager)m_activity.getSystemService(Context.DISPLAY_SERVICE);
668 displayManager.registerDisplayListener(displayListener,
null);
671 public boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams)
674 if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY)
675 || !loaderParams.containsKey(BUNDLED_LIBRARIES_KEY)
676 || !loaderParams.containsKey(ENVIRONMENT_VARIABLES_KEY)) {
681 loadActivity(activity);
683 }
catch (Exception
e) {
688 if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) {
689 for (String
className: Objects.requireNonNull(loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY))) {
694 Class<?> initClass = classLoader.loadClass(
className);
695 Object staticInitDataObject = initClass.newInstance();
697 Method
m = initClass.getMethod(
"setActivity", Activity.class,
Object.class);
698 m.invoke(staticInitDataObject, m_activity,
this);
699 }
catch (Exception
e) {
705 Method
m = initClass.getMethod(
"setContext", Context.class);
706 m.invoke(staticInitDataObject, (Context)m_activity);
707 }
catch (Exception
e) {
710 }
catch (Exception
e) {
716 ArrayList<String> libraries = loaderParams.getStringArrayList(BUNDLED_LIBRARIES_KEY);
719 m_mainLib = loaderParams.getString(MAIN_LIBRARY_KEY);
721 if (
null == m_mainLib && libraries.size() > 0) {
722 m_mainLib = libraries.get(libraries.size() - 1);
723 libraries.remove(libraries.size() - 1);
731 "Droid Sans Mono;Droid Sans;Droid Sans Fallback");
736 "Roboto;Droid Sans;Droid Sans Fallback");
738 String.valueOf(getAppIconSize(activity)));
740 if (loaderParams.containsKey(APPLICATION_PARAMETERS_KEY))
741 m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
743 m_applicationParameters =
"";
746 return m_mainLib !=
null;
754 Bundle extras = m_activity.getIntent().getExtras();
755 if (extras !=
null) {
757 final boolean isDebuggable = (m_activity.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
759 throw new Exception();
761 if (extras.containsKey(
"extraenvvars")) {
764 Base64.decode(extras.getString(
"extraenvvars"),
Base64.DEFAULT),
766 }
catch (Exception
e) {
771 if (extras.containsKey(
"extraappparams")) {
773 m_applicationParameters +=
"\t" +
new String(
Base64.decode(extras.getString(
"extraappparams"),
Base64.DEFAULT),
"UTF-8");
774 }
catch (Exception
e) {
778 }
catch (Exception
e) {
780 "extra arguments in non-debug mode.");
789 }
catch (Exception
e) {
805 if (
null == savedInstanceState) {
812 }
catch (Exception
e) {
821 int orientation = m_activity.getResources().getConfiguration().orientation;
824 ActivityInfo
info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
826 String splashScreenKey =
"android.app.splash_screen_drawable_"
827 + (orientation == Configuration.ORIENTATION_LANDSCAPE ?
"landscape" :
"portrait");
828 if (!
info.metaData.containsKey(splashScreenKey))
829 splashScreenKey =
"android.app.splash_screen_drawable";
831 if (
info.metaData.containsKey(splashScreenKey)) {
832 m_splashScreenSticky =
info.metaData.containsKey(
"android.app.splash_screen_sticky") &&
info.metaData.getBoolean(
"android.app.splash_screen_sticky");
833 int id =
info.metaData.getInt(splashScreenKey);
834 m_splashScreen =
new ImageView(m_activity);
835 m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(
id, m_activity.getTheme()));
836 m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY);
837 m_splashScreen.setLayoutParams(
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
838 m_layout.addView(m_splashScreen);
840 }
catch (Exception
e) {
844 m_editText =
new QtEditText(m_activity,
this);
845 m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
846 m_surfaces =
new HashMap<Integer, QtSurface>();
847 m_nativeViews =
new HashMap<Integer, View>();
848 m_activity.registerForContextMenu(m_layout);
849 m_activity.setContentView(m_layout,
850 new ViewGroup.
LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
851 ViewGroup.LayoutParams.MATCH_PARENT));
853 int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
854 boolean rot90 = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
855 boolean currentlyLandscape = (orientation == Configuration.ORIENTATION_LANDSCAPE);
856 if ((currentlyLandscape && !rot90) || (!currentlyLandscape && rot90))
857 m_nativeOrientation = Configuration.ORIENTATION_LANDSCAPE;
859 m_nativeOrientation = Configuration.ORIENTATION_PORTRAIT;
863 m_currentRotation = rotation;
865 handleUiModeChange(m_activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
867 float refreshRate = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
868 ? m_activity.getWindowManager().getDefaultDisplay().getRefreshRate()
869 : m_activity.getDisplay().getRefreshRate();
872 m_layout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
874 public boolean onPreDraw() {
875 if (!m_keyboardIsVisible)
879 m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(
r);
880 DisplayMetrics
metrics =
new DisplayMetrics();
881 m_activity.getWindowManager().getDefaultDisplay().getMetrics(
metrics);
882 final int kbHeight = metrics.heightPixels -
r.bottom;
888 m_layout.getLocationOnScreen(
location);
890 r.width(), kbHeight);
904 if (m_splashScreen ==
null)
908 m_layout.removeView(m_splashScreen);
909 m_splashScreen =
null;
913 final Animation fadeOut =
new AlphaAnimation(1, 0);
914 fadeOut.setInterpolator(
new AccelerateInterpolator());
915 fadeOut.setDuration(duration);
917 fadeOut.setAnimationListener(
new Animation.AnimationListener() {
919 public void onAnimationEnd(Animation animation) { hideSplashScreen(0); }
922 public void onAnimationRepeat(Animation
animation) {}
925 public void onAnimationStart(Animation
animation) {}
928 m_splashScreen.startAnimation(fadeOut);
933 if (m_accessibilityDelegate ==
null)
940 if (m_accessibilityDelegate ==
null)
947 if (m_accessibilityDelegate ==
null)
954 if (m_accessibilityDelegate ==
null)
961 if (m_accessibilityDelegate ==
null)
979 m_super_onWindowFocusChanged.invoke(m_activity, hasFocus);
980 }
catch (Exception
e) {
987 boolean isUiModeDark(Configuration
config)
989 return (
config.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
992 private void handleUiModeChange(
int uiMode)
995 if (Build.VERSION.SDK_INT >= 30) {
998 WindowInsetsController controller =
window.getInsetsController();
999 if (controller !=
null) {
1001 int appearanceLight = Color.luminance(
window.getStatusBarColor()) > 0.5 ?
1002 WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS : 0;
1003 controller.setSystemBarsAppearance(appearanceLight,
1004 WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
1008 case Configuration.UI_MODE_NIGHT_NO:
1009 ExtractStyle.runIfNeeded(m_activity,
false);
1010 QtNative.handleUiDarkModeChanged(0);
1012 case Configuration.UI_MODE_NIGHT_YES:
1013 ExtractStyle.runIfNeeded(m_activity,
true);
1014 QtNative.handleUiDarkModeChanged(1);
1022 m_super_onConfigurationChanged.invoke(m_activity, configuration);
1023 }
catch (Exception
e) {
1024 e.printStackTrace();
1026 handleUiModeChange(configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK);
1041 if (Build.VERSION.SDK_INT < 24 || !m_activity.isInMultiWindowMode())
1062 m_super_onActivityResult.invoke(m_activity, requestCode, resultCode,
data);
1063 }
catch (Exception
e) {
1064 e.printStackTrace();
1079 m_super_onRetainNonConfigurationInstance.invoke(m_activity);
1080 }
catch (Exception
e) {
1081 e.printStackTrace();
1089 m_super_onSaveInstanceState.invoke(m_activity, outState);
1090 }
catch (Exception
e) {
1091 e.printStackTrace();
1093 outState.putInt(
"SystemUiVisibility", m_systemUiVisibility);
1094 outState.putBoolean(
"Started", m_started);
1101 m_super_onRestoreInstanceState.invoke(m_activity, savedInstanceState);
1102 }
catch (Exception
e) {
1103 e.printStackTrace();
1105 m_started = savedInstanceState.getBoolean(
"Started");
1112 if (!m_started || !m_isPluginRunning)
1115 m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode,
event);
1116 int c =
event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState) |
event.getMetaState());
1118 m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState);
1120 if ((
c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
1121 c =
c & KeyCharacterMap.COMBINING_ACCENT_MASK;
1122 int composed = KeyEvent.getDeadChar(m_lastChar,
c);
1126 if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
1127 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1128 || keyCode == KeyEvent.KEYCODE_MUTE)
1129 && System.getenv(
"QT_ANDROID_VOLUME_KEYS") ==
null) {
1134 if (keyCode == KeyEvent.KEYCODE_BACK) {
1135 m_backKeyPressedSent = !m_keyboardIsVisible;
1136 if (!m_backKeyPressedSent)
1146 if (!m_started || !m_isPluginRunning)
1149 if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
1150 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1151 || keyCode == KeyEvent.KEYCODE_MUTE)
1152 && System.getenv(
"QT_ANDROID_VOLUME_KEYS") ==
null) {
1156 if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) {
1157 hideSoftwareKeyboard();
1158 setKeyboardVisibility(
false, System.nanoTime());
1162 m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode,
event);
1170 &&
event.getAction() == KeyEvent.ACTION_MULTIPLE
1171 &&
event.getCharacters() !=
null
1172 &&
event.getCharacters().length() == 1
1173 &&
event.getKeyCode() == 0) {
1182 return (
Boolean) m_super_dispatchKeyEvent.invoke(m_activity,
event);
1183 }
catch (Exception
e) {
1184 e.printStackTrace();
1189 private boolean m_optionsMenuIsVisible =
false;
1197 m_optionsMenuIsVisible =
true;
1210 m_optionsMenuIsVisible =
false;
1216 m_activity.invalidateOptionsMenu();
1219 private boolean m_contextMenuVisible =
false;
1222 ContextMenuInfo menuInfo)
1226 m_contextMenuVisible =
true;
1232 m_contextMenuVisible =
true;
1237 if (!m_contextMenuVisible)
1239 m_contextMenuVisible =
false;
1245 m_contextMenuVisible =
false;
1251 m_layout.postDelayed(
new Runnable() {
1255 PopupMenu popup =
new PopupMenu(m_activity, m_editText);
1257 popup.setOnMenuItemClickListener(
new PopupMenu.OnMenuItemClickListener() {
1259 public boolean onMenuItemClick(MenuItem menuItem) {
1260 return QtActivityDelegate.this.onContextItemSelected(menuItem);
1263 popup.setOnDismissListener(
new PopupMenu.OnDismissListener() {
1265 public void onDismiss(PopupMenu popupMenu) {
1266 QtActivityDelegate.this.onContextMenuClosed(popupMenu.getMenu());
1276 m_activity.closeContextMenu();
1279 private void setActionBarVisibility(
boolean visible)
1281 if (m_activity.getActionBar() ==
null)
1283 if (ViewConfiguration.get(m_activity).hasPermanentMenuKey() || !visible)
1284 m_activity.getActionBar().hide();
1286 m_activity.getActionBar().show();
1290 if (m_dummyView !=
null) {
1291 m_layout.removeView(m_dummyView);
1295 if (m_nativeViews.containsKey(
id))
1296 m_layout.removeView(m_nativeViews.remove(
id));
1298 if (
w < 0 ||
h < 0) {
1299 view.setLayoutParams(
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1300 ViewGroup.LayoutParams.MATCH_PARENT));
1306 m_layout.addView(
view);
1307 m_nativeViews.put(
id,
view);
1312 TypedValue attr =
new TypedValue();
1313 m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr,
true);
1314 if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
1315 m_activity.getWindow().setBackgroundDrawable(
new ColorDrawable(attr.data));
1317 m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme()));
1319 if (m_dummyView !=
null) {
1320 m_layout.removeView(m_dummyView);
1329 if (
w < 0 ||
h < 0) {
1330 surface.setLayoutParams(
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
1331 ViewGroup.LayoutParams.MATCH_PARENT));
1338 final int surfaceCount = getSurfaceCount();
1339 m_layout.addView(surface, surfaceCount);
1342 if (!m_splashScreenSticky)
1350 }
else if (m_nativeViews.containsKey(
id)) {
1351 View
view = m_nativeViews.get(
id);
1364 }
else if (m_nativeViews.containsKey(
id)) {
1365 view = m_nativeViews.remove(
id);
1375 if (
m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
1378 m_layout.removeView(
view);
1391 final int surfaceCount = getSurfaceCount();
1392 if (surfaceCount > 0)
1397 view = m_nativeViews.get(
id);
1410 view = m_nativeViews.get(
id);
1412 final int index = getSurfaceCount();
1423 return (
Boolean) m_super_dispatchGenericMotionEvent.invoke(m_activity, ev);
1424 }
catch (Exception
e) {
1425 e.printStackTrace();
QHash< int, AndroidSurfaceClient * > m_surfaces
void setPosition(final int x, final int y)
static final int PASTE_BUTTON
void setPosition(final int x, final int y, final int buttons, CursorHandle cursorHandle, CursorHandle leftSelectionHandle, CursorHandle rightSelectionHandle)
static void runIfNeeded(Context context, boolean extractDarkMode)
static void setup(Bundle loaderParams)
boolean isKeyboardVisible()
void notifyQtAndroidPluginRunning(boolean running)
static final int ApplicationHidden
void notifyObjectFocus(int viewId)
void insertNativeView(int id, View view, int x, int y, int w, int h)
void notifyScrolledEvent(int viewId)
void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
void onNewIntent(Intent data)
void setSystemUiVisibility(int systemUiVisibility)
boolean onPrepareOptionsMenu(Menu menu)
void hideSplashScreen(final int duration)
void notifyObjectHide(int viewId, int parentId)
void notifyValueChanged(int viewId, String value)
boolean dispatchKeyEvent(KeyEvent event)
void onWindowFocusChanged(boolean hasFocus)
boolean onOptionsItemSelected(MenuItem item)
void bringChildToBack(int id)
void showSoftwareKeyboard(final int x, final int y, final int width, final int height, final int inputHints, final int enterKeyType)
void onCreatePopupMenu(Menu menu)
boolean onKeyUp(int keyCode, KeyEvent event)
static final int SYSTEM_UI_VISIBILITY_NORMAL
void onSaveInstanceState(Bundle outState)
boolean m_backKeyPressedSent
void onRestoreInstanceState(Bundle savedInstanceState)
void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth)
void onConfigurationChanged(Configuration configuration)
void onOptionsMenuClosed(Menu menu)
int getSelectHandleWidth()
static final int ApplicationSuspended
boolean onContextItemSelected(MenuItem item)
void onContextMenuClosed(Menu menu)
boolean setKeyboardVisibility(boolean visibility, long timeStamp)
static final int ApplicationInactive
boolean onCreateOptionsMenu(Menu menu)
boolean onKeyDown(int keyCode, KeyEvent event)
boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams)
void onActivityResult(int requestCode, int resultCode, Intent data)
void onCreate(Bundle savedInstanceState)
boolean updateActivity(Activity activity)
static final int SYSTEM_UI_VISIBILITY_TRANSLUCENT
void setSurfaceGeometry(int id, int x, int y, int w, int h)
boolean dispatchGenericMotionEvent(MotionEvent ev)
boolean startApplication()
Object onRetainNonConfigurationInstance()
void openContextMenu(final int x, final int y, final int w, final int h)
void notifyAccessibilityLocationChange(int viewId)
void updateHandles(int mode, int editX, int editY, int editButtons, int x1, int y1, int x2, int y2, boolean rtl)
static final int ApplicationActive
void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
void bringChildToFront(int id)
void hideSoftwareKeyboard()
void initializeAccessibility()
void destroySurface(int id)
void resetSoftwareKeyboard()
void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
static final int SYSTEM_UI_VISIBILITY_FULLSCREEN
void setInputType(int m_inputType)
void setImeOptions(int m_imeOptions)
void setInitialCapsMode(int m_initialCapsMode)
LayoutParams(int width, int height, int x, int y)
void setActivityDisplayRotation(int rotation)
void setLayoutParams(final View childView, final ViewGroup.LayoutParams params, final boolean forceRedraw)
void moveChild(View view, int index)
void setNativeOrientation(int orientation)
static String nativeLibrariesDir(Context context)
static boolean startApplication(String params, String mainLib)
static native void handleScreenAdded(int displayId)
static native void keyUp(int key, int unicode, int modifier, boolean autoRepeat)
static boolean hasClipboardText()
static final int IdCursorHandle
static native void terminateQt()
static void setEnvironmentVariables(String environmentVariables)
static QtThread m_qtThread
static native void fillContextMenu(Menu menu)
static native void onActivityResult(int requestCode, int resultCode, Intent data)
static native void keyboardGeometryChanged(int x, int y, int width, int height)
static final int IdLeftHandle
static native void sendRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
static native boolean dispatchGenericMotionEvent(MotionEvent ev)
static void setApplicationState(int state)
static void keyboardVisibilityUpdated(boolean visibility)
static native boolean onPrepareOptionsMenu(Menu menu)
static native boolean onContextItemSelected(int itemId, boolean checked)
static final String QtTAG
static String loadMainLibrary(final String mainLibrary, final String nativeLibraryDir)
static native void onCreateContextMenu(ContextMenu menu)
static native boolean onOptionsItemSelected(int itemId, boolean checked)
static void setActivity(Activity qtMainActivity, QtActivityDelegate qtActivityDelegate)
static void loadBundledLibraries(final ArrayList< String > libraries, final String nativeLibraryDir)
static void setEnvironmentVariable(String key, String value)
static native void handleOrientationChanged(int newRotation, int nativeOrientation)
static native void onNewIntent(Intent data)
static native boolean dispatchKeyEvent(KeyEvent event)
static native void onContextMenuClosed(Menu menu)
static native void updateWindow()
static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat)
static native void handleRefreshRateChanged(float refreshRate)
static native boolean updateNativeActivity()
static void loadQtLibraries(final ArrayList< String > libraries)
static native void onOptionsMenuClosed(Menu menu)
static final int IdRightHandle
static void setClassLoader(ClassLoader classLoader)
void notifyLocationChange(int viewId)
void notifyScrolledEvent(int viewId)
void notifyObjectHide(int viewId, int parentId)
void notifyObjectFocus(int viewId)
void notifyValueChanged(int viewId, String value)
QMap< Name, StatePointer > Bundle
struct wl_display * display
static Q_CONSTINIT QBasicAtomicInt running
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLfloat GLfloat GLfloat x1
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat GLfloat GLfloat h
GLfixed GLfixed GLfixed y2
const char className[16]
[1]
QFileInfo info(fileName)
[8]