Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
QtEmbeddedDelegate.java
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4package org.qtproject.qt.android;
5
7
8import android.app.Activity;
9import android.app.Application;
10import android.content.Context;
11import android.content.res.Resources;
12import android.os.Build;
13import android.os.Bundle;
14import android.os.Handler;
15import android.os.Looper;
16import android.util.DisplayMetrics;
17import android.util.Log;
18import android.view.Menu;
19import android.view.View;
20import android.view.ViewGroup;
21import android.widget.PopupMenu;
22
23import java.util.ArrayList;
24import java.util.HashMap;
25
26class QtEmbeddedDelegate extends QtActivityDelegateBase
27 implements QtNative.AppStateDetailsListener, QtEmbeddedViewInterface, QtWindowInterface,
28 QtMenuInterface, QtLayoutInterface
29{
30 private static final String QtTAG = "QtEmbeddedDelegate";
31 // TODO simplistic implementation with one QtView, expand to support multiple views QTBUG-117649
32 private QtView m_view;
33 private QtNative.ApplicationStateDetails m_stateDetails;
34 private boolean m_windowLoaded = false;
35 private boolean m_backendsRegistered = false;
36
37 public QtEmbeddedDelegate(Activity context) {
38 super(context);
39
40 m_stateDetails = QtNative.getStateDetails();
41 QtNative.registerAppStateListener(this);
42
43 m_activity.getApplication().registerActivityLifecycleCallbacks(
44 new Application.ActivityLifecycleCallbacks() {
45 @Override
46 public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
47
48 @Override
49 public void onActivityStarted(Activity activity) {}
50
51 @Override
52 public void onActivityResumed(Activity activity) {
53 if (m_activity == activity && m_stateDetails.isStarted) {
54 QtNative.setApplicationState(ApplicationActive);
55 QtNative.updateWindow();
56 }
57 }
58
59 @Override
60 public void onActivityPaused(Activity activity) {
61 if (m_activity == activity && m_stateDetails.isStarted) {
62 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N ||
63 !activity.isInMultiWindowMode()) {
64 QtNative.setApplicationState(ApplicationInactive);
65 }
66 }
67 }
68
69 @Override
70 public void onActivityStopped(Activity activity) {
71 if (m_activity == activity && m_stateDetails.isStarted) {
72 QtNative.setApplicationState(ApplicationSuspended);
73 }
74 }
75
76 @Override
77 public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
78
79 @Override
80 public void onActivityDestroyed(Activity activity) {
81 if (m_activity == activity && m_stateDetails.isStarted) {
82 m_activity.getApplication().unregisterActivityLifecycleCallbacks(this);
83 QtNative.unregisterAppStateListener(QtEmbeddedDelegate.this);
84 QtEmbeddedViewInterfaceFactory.remove(m_activity);
85 QtNative.terminateQt();
86 QtNative.setActivity(null);
87 QtNative.getQtThread().exit();
88 }
89 }
90 });
91 }
92
93 @Override
94 public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
95 synchronized (this) {
96 m_stateDetails = details;
97 if (details.isStarted && !m_backendsRegistered) {
98 m_backendsRegistered = true;
99 BackendRegister.registerBackend(QtWindowInterface.class, (QtWindowInterface)this);
100 BackendRegister.registerBackend(QtMenuInterface.class, (QtMenuInterface)this);
101 BackendRegister.registerBackend(QtLayoutInterface.class, (QtLayoutInterface)this);
102 } else if (!details.isStarted && m_backendsRegistered) {
103 m_backendsRegistered = false;
104 BackendRegister.unregisterBackend(QtWindowInterface.class);
105 BackendRegister.unregisterBackend(QtMenuInterface.class);
106 BackendRegister.unregisterBackend(QtLayoutInterface.class);
107 }
108 }
109 }
110
111 @Override
112 public void onNativePluginIntegrationReadyChanged(boolean ready)
113 {
114 synchronized (this) {
115 if (ready) {
116 QtNative.runAction(() -> {
117 DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
118 QtDisplayManager.setApplicationDisplayMetrics(m_activity, metrics.widthPixels,
119 metrics.heightPixels);
120
121 });
123 }
124 }
125 }
126
127 @Override
128 void startNativeApplicationImpl(String appParams, String mainLib)
129 {
130 QtNative.startApplication(appParams, mainLib);
131 }
132
133 @Override
134 public QtLayout getQtLayout()
135 {
136 // TODO verify if returning m_view here works, this is used by the androidjniinput
137 // when e.g. showing a keyboard, so depends on getting the keyboard focus working
138 // QTBUG-118873
139 if (m_view == null)
140 return null;
141 return m_view.getQtWindow();
142 }
143
144 // QtEmbeddedViewInterface implementation begin
145 @Override
146 public void startQtApplication(String appParams, String mainLib)
147 {
148 super.startNativeApplication(appParams, mainLib);
149 }
150
151 @Override
152 public void queueLoadWindow()
153 {
154 synchronized (this) {
155 if (m_stateDetails.nativePluginIntegrationReady)
157 }
158 }
159
160 @Override
161 public void setView(QtView view)
162 {
163 m_view = view;
164 updateInputDelegate();
165 if (m_view != null)
166 registerGlobalFocusChangeListener(m_view);
167 }
168 // QtEmbeddedViewInterface implementation end
169
170 private void updateInputDelegate() {
171 if (m_view == null) {
172 m_inputDelegate.setEditPopupMenu(null);
173 return;
174 }
175 m_inputDelegate.setEditPopupMenu(new EditPopupMenu(m_activity, m_view));
176 }
177
178 private void createRootWindow() {
179 if (m_view != null && !m_windowLoaded) {
180 QtView.createRootWindow(m_view, m_view.getLeft(), m_view.getTop(), m_view.getWidth(),
181 m_view.getHeight());
182 m_windowLoaded = true;
183 }
184 }
185
186 // QtMenuInterface implementation begin
187 @Override
188 public void resetOptionsMenu() { QtNative.runAction(() -> m_activity.invalidateOptionsMenu()); }
189
190 @Override
191 public void openOptionsMenu() { QtNative.runAction(() -> m_activity.openOptionsMenu()); }
192
193 @Override
194 public void closeContextMenu() { QtNative.runAction(() -> m_activity.closeContextMenu()); }
195
196 @Override
197 public void openContextMenu(final int x, final int y, final int w, final int h)
198 {
199 QtLayout layout = getQtLayout();
200 layout.postDelayed(() -> {
201 final QtEditText focusedEditText = m_inputDelegate.getCurrentQtEditText();
202 if (focusedEditText == null) {
203 Log.w(QtTAG, "No focused view when trying to open context menu");
204 return;
205 }
206 layout.setLayoutParams(focusedEditText, new QtLayout.LayoutParams(w, h, x, y), false);
207 PopupMenu popup = new PopupMenu(m_activity, focusedEditText);
208 QtNative.fillContextMenu(popup.getMenu());
209 popup.setOnMenuItemClickListener(menuItem ->
210 m_activity.onContextItemSelected(menuItem));
211 popup.setOnDismissListener(popupMenu ->
212 m_activity.onContextMenuClosed(popupMenu.getMenu()));
213 popup.show();
214 }, 100);
215 }
216 // QtMenuInterface implementation end
217}
static void startQtApplication(JNIEnv *, jclass)
Q_CORE_EXPORT QtJniTypes::Activity activity()
void createRootWindow(JNIEnv *, jclass, QtJniTypes::View rootView, jint x, jint y, jint width, jint height)
static void * context
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLint y
GLfloat GLfloat GLfloat GLfloat h
QVBoxLayout * layout
QQuickView * view
[0]