diff options
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java')
-rw-r--r-- | src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java | 258 |
1 files changed, 182 insertions, 76 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index b06ccc5ec6..1218164d05 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2017 BogDan Vatra <bogdan@kde.org> -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ ** @@ -69,6 +69,7 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; +import android.view.Display; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.Menu; @@ -154,6 +155,7 @@ public class QtActivityDelegate private CursorHandle m_leftSelectionHandle; private CursorHandle m_rightSelectionHandle; private EditPopupMenu m_editPopupMenu; + private boolean m_isPluginRunning = false; public void setFullScreen(boolean enterFullScreen) { @@ -190,6 +192,11 @@ public class QtActivityDelegate } } + public boolean isKeyboardVisible() + { + return m_keyboardIsVisible; + } + // input method hints - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h private final int ImhHiddenText = 0x1; private final int ImhSensitiveData = 0x2; @@ -233,7 +240,6 @@ public class QtActivityDelegate private QtAccessibilityDelegate m_accessibilityDelegate = null; - public boolean setKeyboardVisibility(boolean visibility, long timeStamp) { if (m_showHideTimeStamp > timeStamp) @@ -243,7 +249,7 @@ public class QtActivityDelegate if (m_keyboardIsVisible == visibility) return false; m_keyboardIsVisible = visibility; - QtNative.keyboardVisibilityChanged(m_keyboardIsVisible); + QtNative.keyboardVisibilityUpdated(m_keyboardIsVisible); if (visibility == false) updateFullScreen(); // Hiding the keyboard clears the immersive mode, so we need to set it again. @@ -334,29 +340,32 @@ public class QtActivityDelegate if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) { if ((inputHints & ImhDate) != 0) inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE; - if ((inputHints & ImhTime) != 0) + else inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME; } // else { TYPE_DATETIME_VARIATION_NORMAL(0) } } else { // CLASS_TEXT - if ((inputHints & (ImhEmailCharactersOnly | ImhUrlCharactersOnly)) != 0) { - if ((inputHints & ImhUrlCharactersOnly) != 0) { - inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI; - - if (enterKeyType == 0) // not explicitly overridden - imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO; - } else if ((inputHints & ImhEmailCharactersOnly) != 0) { - inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; - } - } else if ((inputHints & ImhHiddenText) != 0) { + if ((inputHints & ImhHiddenText) != 0) { inputType |= android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD; } else if ((inputHints & ImhSensitiveData) != 0 || ((inputHints & ImhNoPredictiveText) != 0 && System.getenv("QT_ANDROID_ENABLE_WORKAROUND_TO_DISABLE_PREDICTIVE_TEXT") != null)) { inputType |= android.text.InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; + } else if ((inputHints & ImhUrlCharactersOnly) != 0) { + inputType |= android.text.InputType.TYPE_TEXT_VARIATION_URI; + if (enterKeyType == 0) // not explicitly overridden + imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO; + } else if ((inputHints & ImhEmailCharactersOnly) != 0) { + inputType |= android.text.InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS; } - if ((inputHints & ImhMultiLine) != 0) + if ((inputHints & ImhMultiLine) != 0) { inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE; + // Clear imeOptions for Multi-Line Type + // User should be able to insert new line in such case + imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE; + } + if ((inputHints & (ImhNoPredictiveText | ImhSensitiveData | ImhHiddenText)) != 0) + inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; if ((inputHints & ImhUppercaseOnly) != 0) { initialCapsMode |= android.text.TextUtils.CAP_MODE_CHARACTERS; @@ -365,11 +374,6 @@ public class QtActivityDelegate initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES; inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; } - - if ((inputHints & ImhNoPredictiveText) != 0 || (inputHints & ImhSensitiveData) != 0 - || (inputHints & ImhHiddenText) != 0) { - inputType |= android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS; - } } if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0) @@ -492,6 +496,17 @@ public class QtActivityDelegate private static final int CursorHandleShowSelection = 2; private static final int CursorHandleShowEdit = 0x100; + public int getSelectHandleWidth() + { + int width = 0; + if (m_leftSelectionHandle != null && m_rightSelectionHandle != null) + width = Math.max(m_leftSelectionHandle.width(), m_rightSelectionHandle.width()); + else if (m_cursorHandle != null) + width = m_cursorHandle.width(); + + return width; + } + /* called from the C++ code when the position of the cursor or selection handles needs to be adjusted. mode is one of QAndroidInputContext::CursorHandleShowMode @@ -564,6 +579,100 @@ public class QtActivityDelegate } } + private final DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() + { + @Override + public void onDisplayAdded(int displayId) { } + + private boolean isSimilarRotation(int r1, int r2) + { + return (r1 == r2) + || (r1 == Surface.ROTATION_0 && r2 == Surface.ROTATION_180) + || (r1 == Surface.ROTATION_180 && r2 == Surface.ROTATION_0) + || (r1 == Surface.ROTATION_90 && r2 == Surface.ROTATION_270) + || (r1 == Surface.ROTATION_270 && r2 == Surface.ROTATION_90); + } + + @Override + public void onDisplayChanged(int displayId) + { + Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + ? m_activity.getWindowManager().getDefaultDisplay() + : m_activity.getDisplay(); + m_currentRotation = display.getRotation(); + m_layout.setActivityDisplayRotation(m_currentRotation); + // Process orientation change only if it comes after the size + // change, or if the screen is rotated by 180 degrees. + // Otherwise it will be processed in QtLayout. + if (isSimilarRotation(m_currentRotation, m_layout.displayRotation())) + QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation); + + float refreshRate = display.getRefreshRate(); + QtNative.handleRefreshRateChanged(refreshRate); + } + + @Override + public void onDisplayRemoved(int displayId) { } + }; + + public boolean updateActivity(Activity activity) + { + try { + // set new activity + loadActivity(activity); + + // update the new activity content view to old layout + ViewGroup layoutParent = (ViewGroup)m_layout.getParent(); + if (layoutParent != null) + layoutParent.removeView(m_layout); + + m_activity.setContentView(m_layout); + + // force c++ native activity object to update + return QtNative.updateNativeActivity(); + } catch (Exception e) { + Log.w(QtNative.QtTAG, "Failed to update the activity."); + e.printStackTrace(); + return false; + } + } + + private void loadActivity(Activity activity) + throws NoSuchMethodException, PackageManager.NameNotFoundException + { + m_activity = activity; + + QtNative.setActivity(m_activity, this); + setActionBarVisibility(false); + + Class<?> activityClass = m_activity.getClass(); + m_super_dispatchKeyEvent = + activityClass.getMethod("super_dispatchKeyEvent", KeyEvent.class); + m_super_onRestoreInstanceState = + activityClass.getMethod("super_onRestoreInstanceState", Bundle.class); + m_super_onRetainNonConfigurationInstance = + activityClass.getMethod("super_onRetainNonConfigurationInstance"); + m_super_onSaveInstanceState = + activityClass.getMethod("super_onSaveInstanceState", Bundle.class); + m_super_onKeyDown = + activityClass.getMethod("super_onKeyDown", Integer.TYPE, KeyEvent.class); + m_super_onKeyUp = + activityClass.getMethod("super_onKeyUp", Integer.TYPE, KeyEvent.class); + m_super_onConfigurationChanged = + activityClass.getMethod("super_onConfigurationChanged", Configuration.class); + m_super_onActivityResult = + activityClass.getMethod("super_onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class); + m_super_onWindowFocusChanged = + activityClass.getMethod("super_onWindowFocusChanged", Boolean.TYPE); + m_super_dispatchGenericMotionEvent = + activityClass.getMethod("super_dispatchGenericMotionEvent", MotionEvent.class); + + m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode; + + DisplayManager displayManager = (DisplayManager)m_activity.getSystemService(Context.DISPLAY_SERVICE); + displayManager.registerDisplayListener(displayListener, null); + } + public boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams) { /// check parameters integrity @@ -573,10 +682,14 @@ public class QtActivityDelegate return false; } - m_activity = activity; - setActionBarVisibility(false); - QtNative.setActivity(m_activity, this); - QtNative.setClassLoader(classLoader); + try { + loadActivity(activity); + QtNative.setClassLoader(classLoader); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) { for (String className: Objects.requireNonNull(loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY))) { if (className.length() == 0) @@ -621,22 +734,6 @@ public class QtActivityDelegate loaderParams.getBoolean(EXTRACT_STYLE_MINIMAL_KEY)); } - try { - m_super_dispatchKeyEvent = m_activity.getClass().getMethod("super_dispatchKeyEvent", KeyEvent.class); - m_super_onRestoreInstanceState = m_activity.getClass().getMethod("super_onRestoreInstanceState", Bundle.class); - m_super_onRetainNonConfigurationInstance = m_activity.getClass().getMethod("super_onRetainNonConfigurationInstance"); - m_super_onSaveInstanceState = m_activity.getClass().getMethod("super_onSaveInstanceState", Bundle.class); - m_super_onKeyDown = m_activity.getClass().getMethod("super_onKeyDown", Integer.TYPE, KeyEvent.class); - m_super_onKeyUp = m_activity.getClass().getMethod("super_onKeyUp", Integer.TYPE, KeyEvent.class); - m_super_onConfigurationChanged = m_activity.getClass().getMethod("super_onConfigurationChanged", Configuration.class); - m_super_onActivityResult = m_activity.getClass().getMethod("super_onActivityResult", Integer.TYPE, Integer.TYPE, Intent.class); - m_super_onWindowFocusChanged = m_activity.getClass().getMethod("super_onWindowFocusChanged", Boolean.TYPE); - m_super_dispatchGenericMotionEvent = m_activity.getClass().getMethod("super_dispatchGenericMotionEvent", MotionEvent.class); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - int necessitasApiLevel = 1; if (loaderParams.containsKey(NECESSITAS_API_LEVEL_KEY)) necessitasApiLevel = loaderParams.getInt(NECESSITAS_API_LEVEL_KEY); @@ -662,33 +759,6 @@ public class QtActivityDelegate else m_applicationParameters = ""; - try { - m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode; - } catch (Exception e) { - e.printStackTrace(); - } - - DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() { - @Override - public void onDisplayAdded(int displayId) { } - - @Override - public void onDisplayChanged(int displayId) { - m_currentRotation = m_activity.getWindowManager().getDefaultDisplay().getRotation(); - QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation); - } - - @Override - public void onDisplayRemoved(int displayId) { } - }; - - try { - DisplayManager displayManager = (DisplayManager) m_activity.getSystemService(Context.DISPLAY_SERVICE); - displayManager.registerDisplayListener(displayListener, null); - } catch (Exception e) { - e.printStackTrace(); - } - m_mainLib = QtNative.loadMainLibrary(m_mainLib, nativeLibsDir); return m_mainLib != null; } @@ -777,7 +847,7 @@ public class QtActivityDelegate m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky"); int id = info.metaData.getInt(splashScreenKey); m_splashScreen = new ImageView(m_activity); - m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id)); + m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id, m_activity.getTheme())); m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY); m_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); m_layout.addView(m_splashScreen); @@ -803,9 +873,15 @@ public class QtActivityDelegate else m_nativeOrientation = Configuration.ORIENTATION_PORTRAIT; + m_layout.setNativeOrientation(m_nativeOrientation); QtNative.handleOrientationChanged(rotation, m_nativeOrientation); m_currentRotation = rotation; + float refreshRate = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) + ? m_activity.getWindowManager().getDefaultDisplay().getRefreshRate() + : m_activity.getDisplay().getRefreshRate(); + QtNative.handleRefreshRateChanged(refreshRate); + m_layout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -817,6 +893,10 @@ public class QtActivityDelegate DisplayMetrics metrics = new DisplayMetrics(); m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics); final int kbHeight = metrics.heightPixels - r.bottom; + if (kbHeight < 0) { + setKeyboardVisibility(false, System.nanoTime()); + return true; + } final int[] location = new int[2]; m_layout.getLocationOnScreen(location); QtNative.keyboardGeometryChanged(location[0], r.bottom - location[1], @@ -861,18 +941,18 @@ public class QtActivityDelegate m_splashScreen.startAnimation(fadeOut); } - public void notifyAccessibilityLocationChange() + public void notifyAccessibilityLocationChange(int viewId) { if (m_accessibilityDelegate == null) return; - m_accessibilityDelegate.notifyLocationChange(); + m_accessibilityDelegate.notifyLocationChange(viewId); } - public void notifyObjectHide(int viewId) + public void notifyObjectHide(int viewId, int parentId) { if (m_accessibilityDelegate == null) return; - m_accessibilityDelegate.notifyObjectHide(viewId); + m_accessibilityDelegate.notifyObjectHide(viewId, parentId); } public void notifyObjectFocus(int viewId) @@ -882,6 +962,25 @@ public class QtActivityDelegate m_accessibilityDelegate.notifyObjectFocus(viewId); } + public void notifyValueChanged(int viewId, String value) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyValueChanged(viewId, value); + } + + public void notifyScrolledEvent(int viewId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyScrolledEvent(viewId); + } + + public void notifyQtAndroidPluginRunning(boolean running) + { + m_isPluginRunning = running; + } + public void initializeAccessibility() { m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout, this); @@ -989,7 +1088,7 @@ public class QtActivityDelegate public boolean onKeyDown(int keyCode, KeyEvent event) { - if (!m_started) + if (!m_started || !m_isPluginRunning) return false; m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event); @@ -1023,7 +1122,7 @@ public class QtActivityDelegate public boolean onKeyUp(int keyCode, KeyEvent event) { - if (!m_started) + if (!m_started || !m_isPluginRunning) return false; if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP @@ -1194,7 +1293,7 @@ public class QtActivityDelegate if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) { m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data)); } else { - m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId)); + m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme())); } if (m_dummyView != null) { m_layout.removeView(m_dummyView); @@ -1226,7 +1325,14 @@ public class QtActivityDelegate public void setSurfaceGeometry(int id, int x, int y, int w, int h) { if (m_surfaces.containsKey(id)) { QtSurface surface = m_surfaces.get(id); - surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); + QtLayout.LayoutParams params = new QtLayout.LayoutParams(w, h, x, y); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + if (m_activity.isInMultiWindowMode()) { + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + } + } + surface.setLayoutParams(params); } else if (m_nativeViews.containsKey(id)) { View view = m_nativeViews.get(id); view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); |