summaryrefslogtreecommitdiffstats
path: root/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java')
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java1453
1 files changed, 286 insertions, 1167 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
index 4cae9465ba..717cd079a4 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -1,783 +1,155 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 BogDan Vatra <bogdan@kde.org>
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Android port of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 BogDan Vatra <bogdan@kde.org>
+// Copyright (C) 2023 The Qt Company Ltd.
+// Copyright (C) 2016 Olivier Goffart <ogoffart@woboq.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
package org.qtproject.qt.android;
import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.res.AssetManager;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.Rect;
-import android.net.LocalServerSocket;
-import android.net.LocalSocket;
import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.text.method.MetaKeyKeyListener;
-import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import android.view.Display;
+import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.Surface;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.inputmethod.InputMethodManager;
-import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowInsetsController;
import android.widget.ImageView;
import android.widget.PopupMenu;
-import android.hardware.display.DisplayManager;
-import java.io.BufferedReader;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.Objects;
-
-import org.qtproject.qt.android.accessibility.QtAccessibilityDelegate;
-public class QtActivityDelegate
+class QtActivityDelegate extends QtActivityDelegateBase
{
- private Activity m_activity = null;
- private Method m_super_dispatchKeyEvent = null;
- private Method m_super_onRestoreInstanceState = null;
- private Method m_super_onRetainNonConfigurationInstance = null;
- private Method m_super_onSaveInstanceState = null;
- private Method m_super_onKeyDown = null;
- private Method m_super_onKeyUp = null;
- private Method m_super_onConfigurationChanged = null;
- private Method m_super_onActivityResult = null;
- private Method m_super_dispatchGenericMotionEvent = null;
- private Method m_super_onWindowFocusChanged = null;
-
- private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
- private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
- private static final String MAIN_LIBRARY_KEY = "main.library";
- private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
- private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
- private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
- private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
- private static final String EXTRACT_STYLE_KEY = "extract.android.style";
- private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
-
- public static final int SYSTEM_UI_VISIBILITY_NORMAL = 0;
- public static final int SYSTEM_UI_VISIBILITY_FULLSCREEN = 1;
- public static final int SYSTEM_UI_VISIBILITY_TRANSLUCENT = 2;
-
- private static String m_environmentVariables = null;
- private static String m_applicationParameters = null;
+ private static final String QtTAG = "QtActivityDelegate";
- private int m_currentRotation = -1; // undefined
- private int m_nativeOrientation = Configuration.ORIENTATION_UNDEFINED;
-
- private String m_mainLib;
- private long m_metaState;
- private int m_lastChar = 0;
- private int m_softInputMode = 0;
- private int m_systemUiVisibility = SYSTEM_UI_VISIBILITY_NORMAL;
- private boolean m_started = false;
- private HashMap<Integer, QtSurface> m_surfaces = null;
- private HashMap<Integer, View> m_nativeViews = null;
- private QtLayout m_layout = null;
+ private QtRootLayout m_layout = null;
private ImageView m_splashScreen = null;
private boolean m_splashScreenSticky = false;
- private QtEditText m_editText = null;
- private InputMethodManager m_imm = null;
- private boolean m_quitApp = true;
- private View m_dummyView = null;
- private boolean m_keyboardIsVisible = false;
- public boolean m_backKeyPressedSent = false;
- private long m_showHideTimeStamp = System.nanoTime();
- private int m_portraitKeyboardHeight = 0;
- private int m_landscapeKeyboardHeight = 0;
- private int m_probeKeyboardHeightDelay = 50; // ms
- private CursorHandle m_cursorHandle;
- private CursorHandle m_leftSelectionHandle;
- private CursorHandle m_rightSelectionHandle;
- private EditPopupMenu m_editPopupMenu;
- private QtAccessibilityDelegate m_accessibilityDelegate = null;
+ private View m_dummyView = null;
+ private HashMap<Integer, View> m_nativeViews = new HashMap<Integer, View>();
- public void setSystemUiVisibility(int systemUiVisibility)
+ QtActivityDelegate(Activity activity)
{
- if (m_systemUiVisibility == systemUiVisibility)
- return;
-
- m_systemUiVisibility = systemUiVisibility;
-
- int systemUiVisibilityFlags = 0;
- switch (m_systemUiVisibility) {
- case SYSTEM_UI_VISIBILITY_NORMAL:
- m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
- m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_VISIBLE;
- break;
- case SYSTEM_UI_VISIBILITY_FULLSCREEN:
- m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
- systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.INVISIBLE;
- break;
- case SYSTEM_UI_VISIBILITY_TRANSLUCENT:
- m_activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- m_activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- systemUiVisibilityFlags = View.SYSTEM_UI_FLAG_VISIBLE;
- break;
- };
+ super(activity);
- m_activity.getWindow().getDecorView().setSystemUiVisibility(systemUiVisibilityFlags);
-
- m_layout.requestLayout();
- }
-
- public void updateFullScreen()
- {
- if (m_systemUiVisibility == SYSTEM_UI_VISIBILITY_FULLSCREEN) {
- m_systemUiVisibility = SYSTEM_UI_VISIBILITY_NORMAL;
- setSystemUiVisibility(SYSTEM_UI_VISIBILITY_FULLSCREEN);
- }
+ setActionBarVisibility(false);
+ setActivityBackgroundDrawable();
}
- // 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;
- private final int ImhNoAutoUppercase = 0x4;
- private final int ImhPreferNumbers = 0x8;
- private final int ImhPreferUppercase = 0x10;
- private final int ImhPreferLowercase = 0x20;
- private final int ImhNoPredictiveText = 0x40;
-
- private final int ImhDate = 0x80;
- private final int ImhTime = 0x100;
-
- private final int ImhPreferLatin = 0x200;
-
- private final int ImhMultiLine = 0x400;
-
- private final int ImhDigitsOnly = 0x10000;
- private final int ImhFormattedNumbersOnly = 0x20000;
- private final int ImhUppercaseOnly = 0x40000;
- private final int ImhLowercaseOnly = 0x80000;
- private final int ImhDialableCharactersOnly = 0x100000;
- private final int ImhEmailCharactersOnly = 0x200000;
- private final int ImhUrlCharactersOnly = 0x400000;
- private final int ImhLatinOnly = 0x800000;
-
- // enter key type - must be kept in sync with QTDIR/src/corelib/global/qnamespace.h
- private final int EnterKeyDefault = 0;
- private final int EnterKeyReturn = 1;
- private final int EnterKeyDone = 2;
- private final int EnterKeyGo = 3;
- private final int EnterKeySend = 4;
- private final int EnterKeySearch = 5;
- private final int EnterKeyNext = 6;
- private final int EnterKeyPrevious = 7;
-
- // application state
- public static final int ApplicationSuspended = 0x0;
- public static final int ApplicationHidden = 0x1;
- public static final int ApplicationInactive = 0x2;
- public static final int ApplicationActive = 0x4;
-
- public boolean setKeyboardVisibility(boolean visibility, long timeStamp)
- {
- if (m_showHideTimeStamp > timeStamp)
- return false;
- m_showHideTimeStamp = timeStamp;
-
- if (m_keyboardIsVisible == visibility)
- return false;
- m_keyboardIsVisible = visibility;
- QtNative.keyboardVisibilityChanged(m_keyboardIsVisible);
-
- if (visibility == false)
- updateFullScreen(); // Hiding the keyboard clears the immersive mode, so we need to set it again.
-
- return true;
- }
- public void resetSoftwareKeyboard()
+ @UsedFromNativeCode
+ @Override
+ QtLayout getQtLayout()
{
- if (m_imm == null)
- return;
- m_editText.postDelayed(new Runnable() {
- @Override
- public void run() {
- m_imm.restartInput(m_editText);
- m_editText.m_optionsChanged = false;
- }
- }, 5);
- }
-
- public void showSoftwareKeyboard(final int x, final int y, final int width, final int height, final int inputHints, final int enterKeyType)
- {
- if (m_imm == null)
- return;
-
- DisplayMetrics metrics = new DisplayMetrics();
- m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
-
- // If the screen is in portrait mode than we estimate that keyboard height will not be higher than 2/5 of the screen.
- // else than we estimate that keyboard height will not be higher than 2/3 of the screen
- final int visibleHeight;
- if (metrics.widthPixels < metrics.heightPixels)
- visibleHeight = m_portraitKeyboardHeight != 0 ? m_portraitKeyboardHeight : metrics.heightPixels * 3 / 5;
- else
- visibleHeight = m_landscapeKeyboardHeight != 0 ? m_landscapeKeyboardHeight : metrics.heightPixels / 3;
-
- if (m_softInputMode != 0) {
- m_activity.getWindow().setSoftInputMode(m_softInputMode);
- final boolean softInputIsHidden = (m_softInputMode & WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) != 0;
- if (softInputIsHidden)
- return;
- } else {
- if (height > visibleHeight)
- m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
- else
- m_activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
- }
-
- int initialCapsMode = 0;
-
- int imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
-
- switch (enterKeyType) {
- case EnterKeyReturn:
- imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
- break;
- case EnterKeyGo:
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_GO;
- break;
- case EnterKeySend:
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEND;
- break;
- case EnterKeySearch:
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_SEARCH;
- break;
- case EnterKeyNext:
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
- break;
- case EnterKeyPrevious:
- imeOptions = android.view.inputmethod.EditorInfo.IME_ACTION_PREVIOUS;
- break;
- }
-
- int inputType = android.text.InputType.TYPE_CLASS_TEXT;
-
- if ((inputHints & (ImhPreferNumbers | ImhDigitsOnly | ImhFormattedNumbersOnly)) != 0) {
- inputType = android.text.InputType.TYPE_CLASS_NUMBER;
- if ((inputHints & ImhFormattedNumbersOnly) != 0) {
- inputType |= (android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL
- | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
- }
-
- if ((inputHints & ImhHiddenText) != 0)
- inputType |= android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD;
- } else if ((inputHints & ImhDialableCharactersOnly) != 0) {
- inputType = android.text.InputType.TYPE_CLASS_PHONE;
- } else if ((inputHints & (ImhDate | ImhTime)) != 0) {
- inputType = android.text.InputType.TYPE_CLASS_DATETIME;
- if ((inputHints & (ImhDate | ImhTime)) != (ImhDate | ImhTime)) {
- if ((inputHints & ImhDate) != 0)
- inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_DATE;
- else
- inputType |= android.text.InputType.TYPE_DATETIME_VARIATION_TIME;
- } // else { TYPE_DATETIME_VARIATION_NORMAL(0) }
- } else { // CLASS_TEXT
- 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)
- inputType |= android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE;
- 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;
- inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
- } else if ((inputHints & ImhLowercaseOnly) == 0 && (inputHints & ImhNoAutoUppercase) == 0) {
- initialCapsMode |= android.text.TextUtils.CAP_MODE_SENTENCES;
- inputType |= android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
- }
- }
-
- if (enterKeyType == 0 && (inputHints & ImhMultiLine) != 0)
- imeOptions = android.view.inputmethod.EditorInfo.IME_FLAG_NO_ENTER_ACTION;
-
- m_editText.setInitialCapsMode(initialCapsMode);
- m_editText.setImeOptions(imeOptions);
- m_editText.setInputType(inputType);
-
- m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(width, height, x, y), false);
- m_editText.requestFocus();
- m_editText.postDelayed(new Runnable() {
- @Override
- public void run() {
- m_imm.showSoftInput(m_editText, 0, new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- QtNativeInputConnection.updateCursorPosition();
- //FALLTHROUGH
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- if (m_softInputMode == 0) {
- // probe for real keyboard height
- m_layout.postDelayed(new Runnable() {
- @Override
- public void run() {
- if (!m_keyboardIsVisible)
- return;
- DisplayMetrics metrics = new DisplayMetrics();
- m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- Rect r = new Rect();
- m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
- if (metrics.heightPixels != r.bottom) {
- if (metrics.widthPixels > metrics.heightPixels) { // landscape
- if (m_landscapeKeyboardHeight != r.bottom) {
- m_landscapeKeyboardHeight = r.bottom;
- showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
- }
- } else {
- if (m_portraitKeyboardHeight != r.bottom) {
- m_portraitKeyboardHeight = r.bottom;
- showSoftwareKeyboard(x, y, width, height, inputHints, enterKeyType);
- }
- }
- } else {
- // no luck ?
- // maybe the delay was too short, so let's make it longer
- if (m_probeKeyboardHeightDelay < 1000)
- m_probeKeyboardHeightDelay *= 2;
- }
- }
- }, m_probeKeyboardHeightDelay);
- }
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
- });
- if (m_editText.m_optionsChanged) {
- m_imm.restartInput(m_editText);
- m_editText.m_optionsChanged = false;
- }
- }
- }, 15);
+ return m_layout;
}
- public void hideSoftwareKeyboard()
+ @UsedFromNativeCode
+ @Override
+ void setSystemUiVisibility(int systemUiVisibility)
{
- if (m_imm == null)
- return;
- m_imm.hideSoftInputFromWindow(m_editText.getWindowToken(), 0, new ResultReceiver(new Handler()) {
- @Override
- protected void onReceiveResult(int resultCode, Bundle resultData) {
- switch (resultCode) {
- case InputMethodManager.RESULT_SHOWN:
- case InputMethodManager.RESULT_UNCHANGED_SHOWN:
- setKeyboardVisibility(true, System.nanoTime());
- break;
- case InputMethodManager.RESULT_HIDDEN:
- case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
- setKeyboardVisibility(false, System.nanoTime());
- break;
- }
- }
+ QtNative.runAction(() -> {
+ m_displayManager.setSystemUiVisibility(systemUiVisibility);
+ m_layout.requestLayout();
+ QtNative.updateWindow();
});
}
- String getAppIconSize(Activity a)
- {
- int size = a.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
- if (size < 36 || size > 512) { // check size sanity
- DisplayMetrics metrics = new DisplayMetrics();
- a.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- size = metrics.densityDpi / 10 * 3;
- if (size < 36)
- size = 36;
-
- if (size > 512)
- size = 512;
- }
- return "\tQT_ANDROID_APP_ICON_SIZE=" + size;
- }
+ @Override
+ public boolean updateActivityAfterRestart(Activity activity) {
+ boolean updated = super.updateActivityAfterRestart(activity);
+ // TODO verify whether this is even needed, the last I checked the initMembers
+ // recreates the layout anyway
+ // update the new activity content view to old layout
+ ViewGroup layoutParent = (ViewGroup)m_layout.getParent();
+ if (layoutParent != null)
+ layoutParent.removeView(m_layout);
- public void updateSelection(int selStart, int selEnd, int candidatesStart, int candidatesEnd)
- {
- if (m_imm == null)
- return;
+ m_activity.setContentView(m_layout);
- m_imm.updateSelection(m_editText, selStart, selEnd, candidatesStart, candidatesEnd);
+ return updated;
}
- // Values coming from QAndroidInputContext::CursorHandleShowMode
- private static final int CursorHandleNotShown = 0;
- private static final int CursorHandleShowNormal = 1;
- private static final int CursorHandleShowSelection = 2;
- private static final int CursorHandleShowEdit = 0x100;
-
- /* called from the C++ code when the position of the cursor or selection handles needs to
- be adjusted.
- mode is one of QAndroidInputContext::CursorHandleShowMode
- */
- public void updateHandles(int mode, int editX, int editY, int editButtons, int x1, int y1, int x2, int y2, boolean rtl)
+ @Override
+ void startNativeApplicationImpl(String appParams, String mainLib)
{
- switch (mode & 0xff)
- {
- case CursorHandleNotShown:
- if (m_cursorHandle != null) {
- m_cursorHandle.hide();
- m_cursorHandle = null;
- }
- if (m_rightSelectionHandle != null) {
- m_rightSelectionHandle.hide();
- m_leftSelectionHandle.hide();
- m_rightSelectionHandle = null;
- m_leftSelectionHandle = null;
- }
- if (m_editPopupMenu != null)
- m_editPopupMenu.hide();
- break;
-
- case CursorHandleShowNormal:
- if (m_cursorHandle == null) {
- m_cursorHandle = new CursorHandle(m_activity, m_layout, QtNative.IdCursorHandle,
- android.R.attr.textSelectHandle, false);
- }
- m_cursorHandle.setPosition(x1, y1);
- if (m_rightSelectionHandle != null) {
- m_rightSelectionHandle.hide();
- m_leftSelectionHandle.hide();
- m_rightSelectionHandle = null;
- m_leftSelectionHandle = null;
- }
- break;
-
- case CursorHandleShowSelection:
- if (m_rightSelectionHandle == null) {
- m_leftSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdLeftHandle,
- !rtl ? android.R.attr.textSelectHandleLeft :
- android.R.attr.textSelectHandleRight,
- rtl);
- m_rightSelectionHandle = new CursorHandle(m_activity, m_layout, QtNative.IdRightHandle,
- !rtl ? android.R.attr.textSelectHandleRight :
- android.R.attr.textSelectHandleLeft,
- rtl);
- }
- m_leftSelectionHandle.setPosition(x1,y1);
- m_rightSelectionHandle.setPosition(x2,y2);
- if (m_cursorHandle != null) {
- m_cursorHandle.hide();
- m_cursorHandle = null;
- }
- mode |= CursorHandleShowEdit;
- break;
- }
-
- if (QtNative.hasClipboardText())
- editButtons |= EditContextView.PASTE_BUTTON;
- else
- editButtons &= ~EditContextView.PASTE_BUTTON;
-
- if ((mode & CursorHandleShowEdit) == CursorHandleShowEdit && editButtons != 0) {
- m_editPopupMenu.setPosition(editX, editY, editButtons, m_cursorHandle, m_leftSelectionHandle,
- m_rightSelectionHandle);
- } else {
- if (m_editPopupMenu != null)
- m_editPopupMenu.hide();
- }
+ m_layout.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ QtNative.startApplication(appParams, mainLib);
+ m_layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
}
- public boolean loadApplication(Activity activity, ClassLoader classLoader, Bundle loaderParams)
+ @Override
+ protected void setUpLayout()
{
- /// check parameters integrity
- if (!loaderParams.containsKey(NATIVE_LIBRARIES_KEY)
- || !loaderParams.containsKey(BUNDLED_LIBRARIES_KEY)
- || !loaderParams.containsKey(ENVIRONMENT_VARIABLES_KEY)) {
- return false;
- }
-
- m_activity = activity;
- setActionBarVisibility(false);
- QtNative.setActivity(m_activity, this);
- QtNative.setClassLoader(classLoader);
- if (loaderParams.containsKey(STATIC_INIT_CLASSES_KEY)) {
- for (String className: Objects.requireNonNull(loaderParams.getStringArray(STATIC_INIT_CLASSES_KEY))) {
- if (className.length() == 0)
- continue;
-
- try {
- Class<?> initClass = classLoader.loadClass(className);
- Object staticInitDataObject = initClass.newInstance(); // create an instance
- try {
- Method m = initClass.getMethod("setActivity", Activity.class, Object.class);
- m.invoke(staticInitDataObject, m_activity, this);
- } catch (Exception e) {
- Log.d(QtNative.QtTAG, "Class " + className + " does not implement setActivity method");
- }
-
- // For modules that don't need/have setActivity
- try {
- Method m = initClass.getMethod("setContext", Context.class);
- m.invoke(staticInitDataObject, (Context)m_activity);
- } catch (Exception e) {
- e.printStackTrace();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- QtNative.loadQtLibraries(loaderParams.getStringArrayList(NATIVE_LIBRARIES_KEY));
- ArrayList<String> libraries = loaderParams.getStringArrayList(BUNDLED_LIBRARIES_KEY);
- String nativeLibsDir = QtNativeLibrariesDir.nativeLibrariesDir(m_activity);
- QtNative.loadBundledLibraries(libraries, nativeLibsDir);
- m_mainLib = loaderParams.getString(MAIN_LIBRARY_KEY);
- // older apps provide the main library as the last bundled library; look for this if the main library isn't provided
- if (null == m_mainLib && libraries.size() > 0) {
- m_mainLib = libraries.get(libraries.size() - 1);
- libraries.remove(libraries.size() - 1);
- }
-
- if (loaderParams.containsKey(EXTRACT_STYLE_KEY)) {
- String path = loaderParams.getString(EXTRACT_STYLE_KEY);
- new ExtractStyle(m_activity, path, loaderParams.containsKey(EXTRACT_STYLE_MINIMAL_KEY) &&
- 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);
-
- m_environmentVariables = loaderParams.getString(ENVIRONMENT_VARIABLES_KEY);
- String additionalEnvironmentVariables = "QT_ANDROID_FONTS_MONOSPACE=Droid Sans Mono;Droid Sans;Droid Sans Fallback"
- + "\tQT_ANDROID_FONTS_SERIF=Droid Serif"
- + "\tNECESSITAS_API_LEVEL=" + necessitasApiLevel
- + "\tHOME=" + m_activity.getFilesDir().getAbsolutePath()
- + "\tTMPDIR=" + m_activity.getFilesDir().getAbsolutePath();
-
- additionalEnvironmentVariables += "\tQT_ANDROID_FONTS=Roboto;Droid Sans;Droid Sans Fallback";
-
- additionalEnvironmentVariables += getAppIconSize(activity);
+ int orientation = m_activity.getResources().getConfiguration().orientation;
+ m_layout = new QtRootLayout(m_activity);
- if (m_environmentVariables != null && m_environmentVariables.length() > 0)
- m_environmentVariables = additionalEnvironmentVariables + "\t" + m_environmentVariables;
- else
- m_environmentVariables = additionalEnvironmentVariables;
+ setUpSplashScreen(orientation);
+ m_activity.registerForContextMenu(m_layout);
+ m_activity.setContentView(m_layout,
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ QtDisplayManager.handleOrientationChanges(m_activity, false);
- if (loaderParams.containsKey(APPLICATION_PARAMETERS_KEY))
- m_applicationParameters = loaderParams.getString(APPLICATION_PARAMETERS_KEY);
- else
- m_applicationParameters = "";
+ handleUiModeChange(m_activity.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
- try {
- m_softInputMode = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), 0).softInputMode;
- } catch (Exception e) {
- e.printStackTrace();
- }
+ Display display = (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
+ ? m_activity.getWindowManager().getDefaultDisplay()
+ : m_activity.getDisplay();
+ QtDisplayManager.handleRefreshRateChanged(QtDisplayManager.getRefreshRate(display));
- DisplayManager.DisplayListener displayListener = new DisplayManager.DisplayListener() {
- @Override
- public void onDisplayAdded(int displayId) { }
+ m_layout.getViewTreeObserver().addOnPreDrawListener(() -> {
+ if (!m_inputDelegate.isKeyboardVisible())
+ return true;
- @Override
- public void onDisplayChanged(int displayId) {
- m_currentRotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
- QtNative.handleOrientationChanged(m_currentRotation, m_nativeOrientation);
+ Rect r = new Rect();
+ m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
+ DisplayMetrics metrics = new DisplayMetrics();
+ m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ final int kbHeight = metrics.heightPixels - r.bottom;
+ if (kbHeight < 0) {
+ m_inputDelegate.setKeyboardVisibility(false, System.nanoTime());
+ return true;
}
-
- @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;
- }
-
- public boolean startApplication()
- {
- // start application
- try {
-
- Bundle extras = m_activity.getIntent().getExtras();
- if (extras != null) {
- try {
- final boolean isDebuggable = (m_activity.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
- if (!isDebuggable)
- throw new Exception();
-
- if (extras.containsKey("extraenvvars")) {
- try {
- m_environmentVariables += "\t" + new String(Base64.decode(extras.getString("extraenvvars"), Base64.DEFAULT), "UTF-8");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- if (extras.containsKey("extraappparams")) {
- try {
- m_applicationParameters += "\t" + new String(Base64.decode(extras.getString("extraappparams"), Base64.DEFAULT), "UTF-8");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- } catch (Exception e) {
- Log.e(QtNative.QtTAG, "Not in debug mode! It is not allowed to use " +
- "extra arguments in non-debug mode.");
- // This is not an error, so keep it silent
- // e.printStackTrace();
- }
- } // extras != null
-
- if (null == m_surfaces)
- onCreate(null);
+ final int[] location = new int[2];
+ m_layout.getLocationOnScreen(location);
+ QtInputDelegate.keyboardGeometryChanged(location[0], r.bottom - location[1],
+ r.width(), kbHeight);
return true;
- } catch (Exception e) {
- e.printStackTrace();
- return false;
- }
- }
-
- public void onTerminate()
- {
- QtNative.terminateQt();
- QtNative.m_qtThread.exit();
+ });
+ registerGlobalFocusChangeListener(m_layout);
+ m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_layout));
}
- public void onCreate(Bundle savedInstanceState)
+ @Override
+ protected void setUpSplashScreen(int orientation)
{
- m_quitApp = true;
- Runnable startApplication = null;
- if (null == savedInstanceState) {
- startApplication = new Runnable() {
- @Override
- public void run() {
- try {
- QtNative.startApplication(m_applicationParameters, m_environmentVariables, m_mainLib);
- m_started = true;
- } catch (Exception e) {
- e.printStackTrace();
- m_activity.finish();
- }
- }
- };
- }
- m_layout = new QtLayout(m_activity, startApplication);
-
- int orientation = m_activity.getResources().getConfiguration().orientation;
-
try {
- ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
+ ActivityInfo info = m_activity.getPackageManager().getActivityInfo(
+ m_activity.getComponentName(),
+ PackageManager.GET_META_DATA);
String splashScreenKey = "android.app.splash_screen_drawable_"
+ (orientation == Configuration.ORIENTATION_LANDSCAPE ? "landscape" : "portrait");
@@ -785,337 +157,113 @@ public class QtActivityDelegate
splashScreenKey = "android.app.splash_screen_drawable";
if (info.metaData.containsKey(splashScreenKey)) {
- m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky");
+ 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_splashScreen.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
m_layout.addView(m_splashScreen);
}
} catch (Exception e) {
e.printStackTrace();
}
-
- m_editText = new QtEditText(m_activity, this);
- m_imm = (InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE);
- m_surfaces = new HashMap<Integer, QtSurface>();
- m_nativeViews = new HashMap<Integer, View>();
- m_activity.registerForContextMenu(m_layout);
- m_activity.setContentView(m_layout,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
-
- int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
- boolean rot90 = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
- boolean currentlyLandscape = (orientation == Configuration.ORIENTATION_LANDSCAPE);
- if ((currentlyLandscape && !rot90) || (!currentlyLandscape && rot90))
- m_nativeOrientation = Configuration.ORIENTATION_LANDSCAPE;
- else
- m_nativeOrientation = Configuration.ORIENTATION_PORTRAIT;
-
- QtNative.handleOrientationChanged(rotation, m_nativeOrientation);
- m_currentRotation = rotation;
-
- m_layout.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- if (!m_keyboardIsVisible)
- return true;
-
- Rect r = new Rect();
- m_activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
- DisplayMetrics metrics = new DisplayMetrics();
- m_activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- final int kbHeight = metrics.heightPixels - r.bottom;
- final int[] location = new int[2];
- m_layout.getLocationOnScreen(location);
- QtNative.keyboardGeometryChanged(location[0], r.bottom - location[1],
- r.width(), kbHeight);
- return true;
- }
- });
- m_editPopupMenu = new EditPopupMenu(m_activity, m_layout);
}
- public void hideSplashScreen()
+ @Override
+ protected void hideSplashScreen(final int duration)
{
- hideSplashScreen(0);
- }
+ QtNative.runAction(() -> {
+ if (m_splashScreen == null)
+ return;
- public void hideSplashScreen(final int duration)
- {
- if (m_splashScreen == null)
- return;
+ if (duration <= 0) {
+ m_layout.removeView(m_splashScreen);
+ m_splashScreen = null;
+ return;
+ }
- if (duration <= 0) {
- m_layout.removeView(m_splashScreen);
- m_splashScreen = null;
- return;
- }
+ final Animation fadeOut = new AlphaAnimation(1, 0);
+ fadeOut.setInterpolator(new AccelerateInterpolator());
+ fadeOut.setDuration(duration);
- final Animation fadeOut = new AlphaAnimation(1, 0);
- fadeOut.setInterpolator(new AccelerateInterpolator());
- fadeOut.setDuration(duration);
+ fadeOut.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ hideSplashScreen(0);
+ }
- fadeOut.setAnimationListener(new Animation.AnimationListener() {
- @Override
- public void onAnimationEnd(Animation animation) { hideSplashScreen(0); }
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+ }
- @Override
- public void onAnimationRepeat(Animation animation) {}
+ @Override
+ public void onAnimationStart(Animation animation) {
+ }
+ });
- @Override
- public void onAnimationStart(Animation animation) {}
+ m_splashScreen.startAnimation(fadeOut);
});
-
- m_splashScreen.startAnimation(fadeOut);
- }
-
- public void notifyAccessibilityLocationChange()
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyLocationChange();
- }
-
- public void notifyObjectHide(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectHide(viewId);
- }
-
- public void notifyObjectFocus(int viewId)
- {
- if (m_accessibilityDelegate == null)
- return;
- m_accessibilityDelegate.notifyObjectFocus(viewId);
}
+ @UsedFromNativeCode
public void initializeAccessibility()
{
- m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity, m_layout, this);
- }
-
- public void onWindowFocusChanged(boolean hasFocus) {
- try {
- m_super_onWindowFocusChanged.invoke(m_activity, hasFocus);
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (hasFocus)
- updateFullScreen();
- }
-
- public void onConfigurationChanged(Configuration configuration)
- {
- try {
- m_super_onConfigurationChanged.invoke(m_activity, configuration);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void onDestroy()
- {
- if (m_quitApp) {
- QtNative.terminateQt();
- QtNative.setActivity(null, null);
- QtNative.m_qtThread.exit();
- System.exit(0);
- }
- }
-
- public void onPause()
- {
- if (Build.VERSION.SDK_INT < 24 || !m_activity.isInMultiWindowMode())
- QtNative.setApplicationState(ApplicationInactive);
- }
-
- public void onResume()
- {
- QtNative.setApplicationState(ApplicationActive);
- if (m_started) {
- QtNative.updateWindow();
- updateFullScreen(); // Suspending the app clears the immersive mode, so we need to set it again.
- }
- }
-
- public void onNewIntent(Intent data)
- {
- QtNative.onNewIntent(data);
- }
-
- public void onActivityResult(int requestCode, int resultCode, Intent data)
- {
- try {
- m_super_onActivityResult.invoke(m_activity, requestCode, resultCode, data);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- QtNative.onActivityResult(requestCode, resultCode, data);
- }
-
-
- public void onStop()
- {
- QtNative.setApplicationState(ApplicationSuspended);
- }
-
- public Object onRetainNonConfigurationInstance()
- {
- try {
- m_super_onRetainNonConfigurationInstance.invoke(m_activity);
- } catch (Exception e) {
- e.printStackTrace();
- }
- m_quitApp = false;
- return true;
- }
-
- public void onSaveInstanceState(Bundle outState) {
- try {
- m_super_onSaveInstanceState.invoke(m_activity, outState);
- } catch (Exception e) {
- e.printStackTrace();
- }
- outState.putInt("SystemUiVisibility", m_systemUiVisibility);
- outState.putBoolean("Started", m_started);
- // It should never
- }
-
- public void onRestoreInstanceState(Bundle savedInstanceState)
- {
- try {
- m_super_onRestoreInstanceState.invoke(m_activity, savedInstanceState);
- } catch (Exception e) {
- e.printStackTrace();
- }
- m_started = savedInstanceState.getBoolean("Started");
- // FIXME restore all surfaces
-
- }
-
- public boolean onKeyDown(int keyCode, KeyEvent event)
- {
- if (!m_started)
- return false;
-
- m_metaState = MetaKeyKeyListener.handleKeyDown(m_metaState, keyCode, event);
- int c = event.getUnicodeChar(MetaKeyKeyListener.getMetaState(m_metaState) | event.getMetaState());
- int lc = c;
- m_metaState = MetaKeyKeyListener.adjustMetaAfterKeypress(m_metaState);
-
- if ((c & KeyCharacterMap.COMBINING_ACCENT) != 0) {
- c = c & KeyCharacterMap.COMBINING_ACCENT_MASK;
- int composed = KeyEvent.getDeadChar(m_lastChar, c);
- c = composed;
- }
-
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
- || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
- || keyCode == KeyEvent.KEYCODE_MUTE)
- && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) {
- return false;
- }
-
- m_lastChar = lc;
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- m_backKeyPressedSent = !m_keyboardIsVisible;
- if (!m_backKeyPressedSent)
- return true;
- }
- QtNative.keyDown(keyCode, c, event.getMetaState(), event.getRepeatCount() > 0);
-
- return true;
- }
-
- public boolean onKeyUp(int keyCode, KeyEvent event)
- {
- if (!m_started)
- return false;
-
- if ((keyCode == KeyEvent.KEYCODE_VOLUME_UP
- || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
- || keyCode == KeyEvent.KEYCODE_MUTE)
- && System.getenv("QT_ANDROID_VOLUME_KEYS") == null) {
- return false;
- }
-
- if (keyCode == KeyEvent.KEYCODE_BACK && !m_backKeyPressedSent) {
- hideSoftwareKeyboard();
- setKeyboardVisibility(false, System.nanoTime());
- return true;
- }
-
- m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event);
- QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState(), event.getRepeatCount() > 0);
- return true;
+ QtNative.runAction(() -> {
+ // FIXME make QtAccessibilityDelegate window based
+ if (m_layout != null)
+ m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout);
+ else
+ Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
+ });
}
- public boolean dispatchKeyEvent(KeyEvent event)
+ void handleUiModeChange(int uiMode)
{
- if (m_started
- && event.getAction() == KeyEvent.ACTION_MULTIPLE
- && event.getCharacters() != null
- && event.getCharacters().length() == 1
- && event.getKeyCode() == 0) {
- QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0);
- QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0);
+ // QTBUG-108365
+ if (Build.VERSION.SDK_INT >= 30) {
+ // Since 29 version we are using Theme_DeviceDefault_DayNight
+ Window window = m_activity.getWindow();
+ WindowInsetsController controller = window.getInsetsController();
+ if (controller != null) {
+ // set APPEARANCE_LIGHT_STATUS_BARS if needed
+ int appearanceLight = Color.luminance(window.getStatusBarColor()) > 0.5 ?
+ WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS : 0;
+ controller.setSystemBarsAppearance(appearanceLight,
+ WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS);
+ }
}
-
- if (QtNative.dispatchKeyEvent(event))
- return true;
-
- try {
- return (Boolean) m_super_dispatchKeyEvent.invoke(m_activity, event);
- } catch (Exception e) {
- e.printStackTrace();
+ switch (uiMode) {
+ case Configuration.UI_MODE_NIGHT_NO:
+ ExtractStyle.runIfNeeded(m_activity, false);
+ QtDisplayManager.handleUiDarkModeChanged(0);
+ break;
+ case Configuration.UI_MODE_NIGHT_YES:
+ ExtractStyle.runIfNeeded(m_activity, true);
+ QtDisplayManager.handleUiDarkModeChanged(1);
+ break;
}
- return false;
- }
-
- private boolean m_optionsMenuIsVisible = false;
- public boolean onCreateOptionsMenu(Menu menu)
- {
- menu.clear();
- return true;
- }
- public boolean onPrepareOptionsMenu(Menu menu)
- {
- m_optionsMenuIsVisible = true;
- boolean res = QtNative.onPrepareOptionsMenu(menu);
- setActionBarVisibility(res && menu.size() > 0);
- return res;
- }
-
- public boolean onOptionsItemSelected(MenuItem item)
- {
- return QtNative.onOptionsItemSelected(item.getItemId(), item.isChecked());
}
- public void onOptionsMenuClosed(Menu menu)
+ @UsedFromNativeCode
+ public void resetOptionsMenu()
{
- m_optionsMenuIsVisible = false;
- QtNative.onOptionsMenuClosed(menu);
+ QtNative.runAction(() -> m_activity.invalidateOptionsMenu());
}
- public void resetOptionsMenu()
+ @UsedFromNativeCode
+ public void openOptionsMenu()
{
- m_activity.invalidateOptionsMenu();
+ QtNative.runAction(() -> m_activity.openOptionsMenu());
}
private boolean m_contextMenuVisible = false;
- public void onCreateContextMenu(ContextMenu menu,
- View v,
- ContextMenuInfo menuInfo)
- {
- menu.clearHeader();
- QtNative.onCreateContextMenu(menu);
- m_contextMenuVisible = true;
- }
public void onCreatePopupMenu(Menu menu)
{
@@ -1123,51 +271,35 @@ public class QtActivityDelegate
m_contextMenuVisible = true;
}
- public void onContextMenuClosed(Menu menu)
- {
- if (!m_contextMenuVisible)
- return;
- m_contextMenuVisible = false;
- QtNative.onContextMenuClosed(menu);
- }
-
- public boolean onContextItemSelected(MenuItem item)
- {
- m_contextMenuVisible = false;
- return QtNative.onContextItemSelected(item.getItemId(), item.isChecked());
- }
-
+ @UsedFromNativeCode
+ @Override
public void openContextMenu(final int x, final int y, final int w, final int h)
{
- m_layout.postDelayed(new Runnable() {
- @Override
- public void run() {
- m_layout.setLayoutParams(m_editText, new QtLayout.LayoutParams(w, h, x, y), false);
- PopupMenu popup = new PopupMenu(m_activity, m_editText);
- QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
- popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem menuItem) {
- return QtActivityDelegate.this.onContextItemSelected(menuItem);
- }
- });
- popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
- @Override
- public void onDismiss(PopupMenu popupMenu) {
- QtActivityDelegate.this.onContextMenuClosed(popupMenu.getMenu());
- }
- });
- popup.show();
- }
- }, 100);
- }
-
+ m_layout.postDelayed(() -> {
+ final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText();
+ if (focusedEditText == null) {
+ Log.w(QtTAG, "No focused view when trying to open context menu");
+ return;
+ }
+ m_layout.setLayoutParams(focusedEditText, new QtLayout.LayoutParams(w, h, x, y), false);
+ PopupMenu popup = new PopupMenu(m_activity, focusedEditText);
+ QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
+ popup.setOnMenuItemClickListener(menuItem ->
+ m_activity.onContextItemSelected(menuItem));
+ popup.setOnDismissListener(popupMenu ->
+ m_activity.onContextMenuClosed(popupMenu.getMenu()));
+ popup.show();
+ }, 100);
+ }
+
+ @UsedFromNativeCode
public void closeContextMenu()
{
- m_activity.closeContextMenu();
+ QtNative.runAction(() -> m_activity.closeContextMenu());
}
- private void setActionBarVisibility(boolean visible)
+ @Override
+ void setActionBarVisibility(boolean visible)
{
if (m_activity.getActionBar() == null)
return;
@@ -1177,149 +309,136 @@ public class QtActivityDelegate
m_activity.getActionBar().show();
}
- public void insertNativeView(int id, View view, int x, int y, int w, int h) {
- if (m_dummyView != null) {
- m_layout.removeView(m_dummyView);
- m_dummyView = null;
- }
-
- if (m_nativeViews.containsKey(id))
- m_layout.removeView(m_nativeViews.remove(id));
-
- if (w < 0 || h < 0) {
- view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- } else {
- view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- }
-
- view.setId(id);
- m_layout.addView(view);
- m_nativeViews.put(id, view);
- }
+ @UsedFromNativeCode
+ @Override
+ public void addTopLevelWindow(final QtWindow window)
+ {
+ if (window == null)
+ return;
- public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) {
- if (m_surfaces.size() == 0) {
- TypedValue attr = new TypedValue();
- m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true);
- 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));
- }
- if (m_dummyView != null) {
- m_layout.removeView(m_dummyView);
- m_dummyView = null;
+ QtNative.runAction(()-> {
+ if (m_topLevelWindows.size() == 0) {
+ if (m_dummyView != null) {
+ m_layout.removeView(m_dummyView);
+ m_dummyView = null;
+ }
}
- }
-
- if (m_surfaces.containsKey(id))
- m_layout.removeView(m_surfaces.remove(id));
-
- QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth);
- if (w < 0 || h < 0) {
- surface.setLayoutParams( new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
- } else {
- surface.setLayoutParams( new QtLayout.LayoutParams(w, h, x, y));
- }
- // Native views are always inserted in the end of the stack (i.e., on top).
- // All other views are stacked based on the order they are created.
- final int surfaceCount = getSurfaceCount();
- m_layout.addView(surface, surfaceCount);
+ window.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
- m_surfaces.put(id, surface);
- if (!m_splashScreenSticky)
- hideSplashScreen();
+ m_layout.addView(window, m_topLevelWindows.size());
+ m_topLevelWindows.put(window.getId(), window);
+ if (!m_splashScreenSticky)
+ hideSplashScreen();
+ });
}
- 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));
- } else if (m_nativeViews.containsKey(id)) {
- View view = m_nativeViews.get(id);
- view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
- } else {
- Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
- return;
- }
+ @UsedFromNativeCode
+ @Override
+ void removeTopLevelWindow(final int id)
+ {
+ QtNative.runAction(()-> {
+ if (m_topLevelWindows.containsKey(id)) {
+ QtWindow window = m_topLevelWindows.remove(id);
+ if (m_topLevelWindows.isEmpty()) {
+ // Keep last frame in stack until it is replaced to get correct
+ // shutdown transition
+ m_dummyView = window;
+ } else {
+ m_layout.removeView(window);
+ }
+ }
+ });
}
- public void destroySurface(int id) {
- View view = null;
-
- if (m_surfaces.containsKey(id)) {
- view = m_surfaces.remove(id);
- } else if (m_nativeViews.containsKey(id)) {
- view = m_nativeViews.remove(id);
- } else {
- Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
- }
-
- if (view == null)
- return;
-
- // Keep last frame in stack until it is replaced to get correct
- // shutdown transition
- if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
- m_dummyView = view;
- } else {
- m_layout.removeView(view);
- }
+ @UsedFromNativeCode
+ @Override
+ void bringChildToFront(final int id)
+ {
+ QtNative.runAction(() -> {
+ QtWindow window = m_topLevelWindows.get(id);
+ if (window != null)
+ m_layout.moveChild(window, m_topLevelWindows.size() - 1);
+ });
}
- public int getSurfaceCount()
+ @UsedFromNativeCode
+ @Override
+ void bringChildToBack(int id)
{
- return m_surfaces.size();
+ QtNative.runAction(() -> {
+ QtWindow window = m_topLevelWindows.get(id);
+ if (window != null)
+ m_layout.moveChild(window, 0);
+ });
}
- public void bringChildToFront(int id)
+ @Override
+ QtAccessibilityDelegate createAccessibilityDelegate()
{
- View view = m_surfaces.get(id);
- if (view != null) {
- final int surfaceCount = getSurfaceCount();
- if (surfaceCount > 0)
- m_layout.moveChild(view, surfaceCount - 1);
- return;
- }
+ if (m_layout != null)
+ return new QtAccessibilityDelegate(m_layout);
- view = m_nativeViews.get(id);
- if (view != null)
- m_layout.moveChild(view, -1);
+ Log.w(QtTAG, "Null layout, failed to initialize accessibility delegate.");
+ return null;
}
- public void bringChildToBack(int id)
+ private void setActivityBackgroundDrawable()
{
- View view = m_surfaces.get(id);
- if (view != null) {
- m_layout.moveChild(view, 0);
- return;
+ TypedValue attr = new TypedValue();
+ m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground,
+ attr, true);
+ Drawable backgroundDrawable;
+ if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
+ attr.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ backgroundDrawable = new ColorDrawable(attr.data);
+ } else {
+ backgroundDrawable = m_activity.getResources().
+ getDrawable(attr.resourceId, m_activity.getTheme());
}
- view = m_nativeViews.get(id);
- if (view != null) {
- final int index = getSurfaceCount();
- m_layout.moveChild(view, index);
- }
+ m_activity.getWindow().setBackgroundDrawable(backgroundDrawable);
}
- public boolean dispatchGenericMotionEvent (MotionEvent ev)
+ // TODO: QTBUG-122761 To be removed after QtAndroidAutomotive does not depend on it.
+ @UsedFromNativeCode
+ public void insertNativeView(int id, View view, int x, int y, int w, int h)
{
- if (m_started && QtNative.dispatchGenericMotionEvent(ev))
- return true;
+ QtNative.runAction(()-> {
+ if (m_dummyView != null) {
+ m_layout.removeView(m_dummyView);
+ m_dummyView = null;
+ }
- try {
- return (Boolean) m_super_dispatchGenericMotionEvent.invoke(m_activity, ev);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
+ if (m_nativeViews.containsKey(id))
+ m_layout.removeView(m_nativeViews.remove(id));
+
+ if (w < 0 || h < 0) {
+ view.setLayoutParams(new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
+ } else {
+ view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
+ }
+
+ view.setId(id);
+ m_layout.addView(view);
+ m_nativeViews.put(id, view);
+ });
}
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
+ // TODO: QTBUG-122761 To be removed after QtAndroidAutomotive does not depend on it.
+ @UsedFromNativeCode
+ public void setNativeViewGeometry(int id, int x, int y, int w, int h)
{
- QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults);
+ QtNative.runAction(() -> {
+ if (m_nativeViews.containsKey(id)) {
+ View view = m_nativeViews.get(id);
+ view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
+ } else {
+ Log.e(QtTAG, "View " + id + " not found!");
+ }
+ });
}
}