diff options
Diffstat (limited to 'src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java')
-rw-r--r-- | src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java new file mode 100644 index 0000000000..6fd539d8dd --- /dev/null +++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java @@ -0,0 +1,267 @@ +// 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.pm.ActivityInfo; +import android.content.pm.PackageManager; +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.os.Build; +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.Menu; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowInsetsController; +import android.widget.ImageView; +import android.widget.PopupMenu; + +import java.util.HashMap; + +abstract class QtActivityDelegateBase +{ + protected Activity m_activity; + protected HashMap<Integer, QtWindow> m_topLevelWindows; + protected QtAccessibilityDelegate m_accessibilityDelegate = null; + protected QtDisplayManager m_displayManager = null; + protected QtInputDelegate m_inputDelegate = null; + + private boolean m_membersInitialized = false; + private boolean m_contextMenuVisible = false; + + // Subclass must implement these + abstract void startNativeApplicationImpl(String appParams, String mainLib); + abstract QtAccessibilityDelegate createAccessibilityDelegate(); + abstract QtLayout getQtLayout(); + + // With these we are okay with default implementation doing nothing + void setUpLayout() {} + void setUpSplashScreen(int orientation) {} + void hideSplashScreen(final int duration) {} + void openContextMenu(final int x, final int y, final int w, final int h) {} + void setActionBarVisibility(boolean visible) {} + void addTopLevelWindow(final QtWindow window) {} + void removeTopLevelWindow(final int id) {} + void bringChildToFront(final int id) {} + void bringChildToBack(int id) {} + void setSystemUiVisibility(int systemUiVisibility) {} + + QtActivityDelegateBase(Activity activity) + { + m_activity = activity; + // Set native context + QtNative.setActivity(m_activity); + } + + QtDisplayManager displayManager() { + return m_displayManager; + } + + @UsedFromNativeCode + QtInputDelegate getInputDelegate() { + return m_inputDelegate; + } + + void setContextMenuVisible(boolean contextMenuVisible) + { + m_contextMenuVisible = contextMenuVisible; + } + + boolean isContextMenuVisible() + { + return m_contextMenuVisible; + } + + public boolean updateActivityAfterRestart(Activity activity) { + try { + // set new activity + m_activity = activity; + QtNative.setActivity(m_activity); + + // 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; + } + } + + public void startNativeApplication(String appParams, String mainLib) + { + if (m_membersInitialized) + return; + initMembers(); + startNativeApplicationImpl(appParams, mainLib); + } + + void initMembers() + { + m_membersInitialized = true; + m_topLevelWindows = new HashMap<Integer, QtWindow>(); + + m_displayManager = new QtDisplayManager(m_activity); + m_displayManager.registerDisplayListener(); + + QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener = + () -> m_displayManager.updateFullScreen(); + m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener); + + try { + PackageManager pm = m_activity.getPackageManager(); + ActivityInfo activityInfo = pm.getActivityInfo(m_activity.getComponentName(), 0); + m_inputDelegate.setSoftInputMode(activityInfo.softInputMode); + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + setUpLayout(); + } + + protected void registerGlobalFocusChangeListener(final View view) { + view.getViewTreeObserver().addOnGlobalFocusChangeListener(this::onGlobalFocusChanged); + } + + private void onGlobalFocusChanged(View oldFocus, View newFocus) { + if (newFocus instanceof QtEditText) { + final QtWindow newWindow = (QtWindow) newFocus.getParent(); + QtWindow.windowFocusChanged(true, newWindow.getId()); + m_inputDelegate.setFocusedView((QtEditText) newFocus); + } else { + int id = -1; + if (oldFocus instanceof QtEditText) { + final QtWindow oldWindow = (QtWindow) oldFocus.getParent(); + id = oldWindow.getId(); + } + QtWindow.windowFocusChanged(false, id); + m_inputDelegate.setFocusedView(null); + } + } + + public void hideSplashScreen() + { + hideSplashScreen(0); + } + + @UsedFromNativeCode + public void notifyLocationChange(int viewId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyLocationChange(viewId); + } + + @UsedFromNativeCode + public void notifyObjectHide(int viewId, int parentId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyObjectHide(viewId, parentId); + } + + @UsedFromNativeCode + public void notifyObjectShow(int parentId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyObjectShow(parentId); + } + + @UsedFromNativeCode + public void notifyObjectFocus(int viewId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyObjectFocus(viewId); + } + + @UsedFromNativeCode + public void notifyValueChanged(int viewId, String value) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyValueChanged(viewId, value); + } + + @UsedFromNativeCode + public void notifyScrolledEvent(int viewId) + { + if (m_accessibilityDelegate == null) + return; + m_accessibilityDelegate.notifyScrolledEvent(viewId); + } + + @UsedFromNativeCode + public void initializeAccessibility() + { + QtNative.runAction(() -> { + m_accessibilityDelegate = createAccessibilityDelegate(); + }); + } + + void handleUiModeChange(int uiMode) + { + // 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); + } + } + 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; + } + } + + @UsedFromNativeCode + public void resetOptionsMenu() + { + QtNative.runAction(() -> m_activity.invalidateOptionsMenu()); + } + + @UsedFromNativeCode + public void openOptionsMenu() + { + QtNative.runAction(() -> m_activity.openOptionsMenu()); + } + + public void onCreatePopupMenu(Menu menu) + { + QtNative.fillContextMenu(menu); + m_contextMenuVisible = true; + } + + @UsedFromNativeCode + public void closeContextMenu() + { + QtNative.runAction(() -> m_activity.closeContextMenu()); + } +} |