Android: don't call delegates outside of the Activity

The delegate classes shouldn't be used outside of the Activity/Service
classes, since they're practically private implementation, so don't use
them anywhere outside Activity/Service.

Since Qt Android apps still mainly support having one QtActivity/
QtService, QtNative heavily uses those objects to do various operations.
For that reason, we still need to use the delegate there. The aim is
to change that in future patches and do the operations where they make
more sense for example directly under QtActivityBase/QtActivityDelegate
or Service counterpart.

The QtServiceDelegate is used no where and have no special
implementation, so it's removed here.

Task-number: QTBUG-118077
Change-Id: I5e106318169be19fec8163e8e500ee573af0e1bc
Reviewed-by: Tinja Paavoseppä <tinja.paavoseppa@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Assam Boudjelthia 2023-09-17 23:13:04 +03:00
parent 19baa077d9
commit f5e2302851
15 changed files with 351 additions and 460 deletions

View File

@ -12,7 +12,6 @@ set(java_sources
src/org/qtproject/qt/android/QtActivityBase.java src/org/qtproject/qt/android/QtActivityBase.java
src/org/qtproject/qt/android/QtServiceBase.java src/org/qtproject/qt/android/QtServiceBase.java
src/org/qtproject/qt/android/QtActivityDelegate.java src/org/qtproject/qt/android/QtActivityDelegate.java
src/org/qtproject/qt/android/QtServiceDelegate.java
src/org/qtproject/qt/android/QtInputDelegate.java src/org/qtproject/qt/android/QtInputDelegate.java
src/org/qtproject/qt/android/QtLoader.java src/org/qtproject/qt/android/QtLoader.java
src/org/qtproject/qt/android/QtActivityLoader.java src/org/qtproject/qt/android/QtActivityLoader.java

View File

@ -173,7 +173,7 @@ public class QtActivityBase extends Activity
super.onDestroy(); super.onDestroy();
if (m_delegate.isQuitApp()) { if (m_delegate.isQuitApp()) {
QtNative.terminateQt(); QtNative.terminateQt();
QtNative.setActivity(null, null); QtNative.setActivity(null);
QtNative.m_qtThread.exit(); QtNative.m_qtThread.exit();
System.exit(0); System.exit(0);
} }
@ -325,6 +325,11 @@ public class QtActivityBase extends Activity
QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults); QtNative.sendRequestPermissionsResult(requestCode, permissions, grantResults);
} }
public void hideSplashScreen(final int duration)
{
m_delegate.hideSplashScreen(duration);
}
QtActivityDelegate getActivityDelegate() QtActivityDelegate getActivityDelegate()
{ {
return m_delegate; return m_delegate;

View File

@ -6,7 +6,6 @@
package org.qtproject.qt.android; package org.qtproject.qt.android;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
@ -27,7 +26,6 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.view.WindowInsetsController; import android.view.WindowInsetsController;
import android.view.inputmethod.InputMethodManager;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.PopupMenu; import android.widget.PopupMenu;
@ -56,34 +54,36 @@ public class QtActivityDelegate
private QtAccessibilityDelegate m_accessibilityDelegate = null; private QtAccessibilityDelegate m_accessibilityDelegate = null;
private final QtDisplayManager m_displayManager = new QtDisplayManager(); private final QtDisplayManager m_displayManager = new QtDisplayManager();
private QtInputDelegate.KeyboardVisibilityListener m_keyboardVisibilityListener = private QtInputDelegate m_inputDelegate = null;
new QtInputDelegate.KeyboardVisibilityListener() {
@Override
public void onKeyboardVisibilityChange() {
m_displayManager.updateFullScreen(m_activity);
}
};
private final QtInputDelegate m_inputDelegate = new QtInputDelegate(m_keyboardVisibilityListener);
QtActivityDelegate(Activity activity) QtActivityDelegate(Activity activity)
{ {
m_activity = activity; m_activity = activity;
QtNative.setActivity(m_activity, this); QtNative.setActivity(m_activity);
setActionBarVisibility(false); setActionBarVisibility(false);
m_displayManager.registerDisplayListener(m_activity, m_layout);
QtInputDelegate.KeyboardVisibilityListener keyboardVisibilityListener =
new QtInputDelegate.KeyboardVisibilityListener() {
@Override
public void onKeyboardVisibilityChange() {
m_displayManager.updateFullScreen(m_activity);
}
};
m_inputDelegate = new QtInputDelegate(m_activity, keyboardVisibilityListener);
try { try {
m_inputDelegate.setSoftInputMode(m_activity.getPackageManager() PackageManager pm = m_activity.getPackageManager();
.getActivityInfo(m_activity.getComponentName(), 0).softInputMode); ActivityInfo activityInfo = pm.getActivityInfo(m_activity.getComponentName(), 0);
m_inputDelegate.setSoftInputMode(activityInfo.softInputMode);
} catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
} }
m_displayManager.registerDisplayListener(m_activity, m_layout);
} }
QtDisplayManager displayManager() QtDisplayManager displayManager() {
{
return m_displayManager; return m_displayManager;
} }
@ -147,7 +147,7 @@ public class QtActivityDelegate
try { try {
// set new activity // set new activity
m_activity = activity; m_activity = activity;
QtNative.setActivity(m_activity, this); QtNative.setActivity(m_activity);
// update the new activity content view to old layout // update the new activity content view to old layout
ViewGroup layoutParent = (ViewGroup) m_layout.getParent(); ViewGroup layoutParent = (ViewGroup) m_layout.getParent();
@ -220,8 +220,6 @@ public class QtActivityDelegate
e.printStackTrace(); e.printStackTrace();
} }
m_inputDelegate.setEditText(new QtEditText(m_activity));
m_inputDelegate.setInputMethodManager((InputMethodManager)m_activity.getSystemService(Context.INPUT_METHOD_SERVICE));
m_surfaces = new HashMap<Integer, QtSurface>(); m_surfaces = new HashMap<Integer, QtSurface>();
m_nativeViews = new HashMap<Integer, View>(); m_nativeViews = new HashMap<Integer, View>();
m_activity.registerForContextMenu(m_layout); m_activity.registerForContextMenu(m_layout);
@ -273,31 +271,40 @@ public class QtActivityDelegate
public void hideSplashScreen(final int duration) public void hideSplashScreen(final int duration)
{ {
if (m_splashScreen == null) QtNative.runAction(new Runnable() {
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);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override @Override
public void onAnimationEnd(Animation animation) { hideSplashScreen(0); } public void run() {
if (m_splashScreen == null)
return;
@Override if (duration <= 0) {
public void onAnimationRepeat(Animation animation) {} m_layout.removeView(m_splashScreen);
m_splashScreen = null;
return;
}
@Override final Animation fadeOut = new AlphaAnimation(1, 0);
public void onAnimationStart(Animation animation) {} fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setDuration(duration);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation animation) {
hideSplashScreen(0);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
});
m_splashScreen.startAnimation(fadeOut);
}
}); });
m_splashScreen.startAnimation(fadeOut);
} }
public void notifyLocationChange(int viewId) public void notifyLocationChange(int viewId)
@ -381,7 +388,22 @@ public class QtActivityDelegate
public void resetOptionsMenu() public void resetOptionsMenu()
{ {
m_activity.invalidateOptionsMenu(); QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.invalidateOptionsMenu();
}
});
}
public void openOptionsMenu()
{
QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.openOptionsMenu();
}
});
} }
private boolean m_contextMenuVisible = false; private boolean m_contextMenuVisible = false;
@ -395,31 +417,36 @@ public class QtActivityDelegate
public void openContextMenu(final int x, final int y, final int w, final int h) public void openContextMenu(final int x, final int y, final int w, final int h)
{ {
m_layout.postDelayed(new Runnable() { m_layout.postDelayed(new Runnable() {
@Override @Override
public void run() { public void run() {
m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false); m_layout.setLayoutParams(m_inputDelegate.getQtEditText(), new QtLayout.LayoutParams(w, h, x, y), false);
PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText()); PopupMenu popup = new PopupMenu(m_activity, m_inputDelegate.getQtEditText());
QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu()); QtActivityDelegate.this.onCreatePopupMenu(popup.getMenu());
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override @Override
public boolean onMenuItemClick(MenuItem menuItem) { public boolean onMenuItemClick(MenuItem menuItem) {
return m_activity.onContextItemSelected(menuItem); return m_activity.onContextItemSelected(menuItem);
} }
}); });
popup.setOnDismissListener(new PopupMenu.OnDismissListener() { popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override @Override
public void onDismiss(PopupMenu popupMenu) { public void onDismiss(PopupMenu popupMenu) {
m_activity.onContextMenuClosed(popupMenu.getMenu()); m_activity.onContextMenuClosed(popupMenu.getMenu());
} }
}); });
popup.show(); popup.show();
} }
}, 100); }, 100);
} }
public void closeContextMenu() public void closeContextMenu()
{ {
m_activity.closeContextMenu(); QtNative.runAction(new Runnable() {
@Override
public void run() {
m_activity.closeContextMenu();
}
});
} }
void setActionBarVisibility(boolean visible) void setActionBarVisibility(boolean visible)
@ -433,96 +460,116 @@ public class QtActivityDelegate
} }
public void insertNativeView(int id, View view, int x, int y, int w, int h) { public void insertNativeView(int id, View view, int x, int y, int w, int h) {
if (m_dummyView != null) { QtNative.runAction(new Runnable() {
m_layout.removeView(m_dummyView); @Override
m_dummyView = null; public void run() {
} if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
}
if (m_nativeViews.containsKey(id)) if (m_nativeViews.containsKey(id))
m_layout.removeView(m_nativeViews.remove(id)); m_layout.removeView(m_nativeViews.remove(id));
if (w < 0 || h < 0) { if (w < 0 || h < 0) {
view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)); ViewGroup.LayoutParams.MATCH_PARENT));
} else { } else {
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} }
view.setId(id); view.setId(id);
m_layout.addView(view); m_layout.addView(view);
m_nativeViews.put(id, view); m_nativeViews.put(id, view);
}
});
} }
public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) { public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) {
if (m_surfaces.size() == 0) { QtNative.runAction(new Runnable() {
TypedValue attr = new TypedValue(); @Override
m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true); public void run() {
if (attr.type >= TypedValue.TYPE_FIRST_COLOR_INT && attr.type <= TypedValue.TYPE_LAST_COLOR_INT) { if (m_surfaces.size() == 0) {
m_activity.getWindow().setBackgroundDrawable(new ColorDrawable(attr.data)); TypedValue attr = new TypedValue();
} else { m_activity.getTheme().resolveAttribute(android.R.attr.windowBackground, attr, true);
m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId, m_activity.getTheme())); 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.getTheme()));
}
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);
m_surfaces.put(id, surface);
if (!m_splashScreenSticky)
hideSplashScreen();
} }
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);
m_surfaces.put(id, surface);
if (!m_splashScreenSticky)
hideSplashScreen();
} }
public void setSurfaceGeometry(int id, int x, int y, int w, int h) { public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
if (m_surfaces.containsKey(id)) { QtNative.runAction(new Runnable() {
QtSurface surface = m_surfaces.get(id); @Override
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); public void run() {
} else if (m_nativeViews.containsKey(id)) { if (m_surfaces.containsKey(id)) {
View view = m_nativeViews.get(id); QtSurface surface = m_surfaces.get(id);
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y)); surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} else { } else if (m_nativeViews.containsKey(id)) {
Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); View view = m_nativeViews.get(id);
return; view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
} } else {
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
return;
}
}
});
} }
public void destroySurface(int id) { public void destroySurface(int id) {
View view = null; QtNative.runAction(new Runnable() {
@Override
public void run() {
View view = null;
if (m_surfaces.containsKey(id)) { if (m_surfaces.containsKey(id)) {
view = m_surfaces.remove(id); view = m_surfaces.remove(id);
} else if (m_nativeViews.containsKey(id)) { } else if (m_nativeViews.containsKey(id)) {
view = m_nativeViews.remove(id); view = m_nativeViews.remove(id);
} else { } else {
Log.e(QtNative.QtTAG, "Surface " + id +" not found!"); Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
} }
if (view == null) if (view == null)
return; return;
// Keep last frame in stack until it is replaced to get correct // Keep last frame in stack until it is replaced to get correct
// shutdown transition // shutdown transition
if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) { if (m_surfaces.size() == 0 && m_nativeViews.size() == 0) {
m_dummyView = view; m_dummyView = view;
} else { } else {
m_layout.removeView(view); m_layout.removeView(view);
} }
}
});
} }
public int getSurfaceCount() public int getSurfaceCount()
@ -532,31 +579,41 @@ public class QtActivityDelegate
public void bringChildToFront(int id) public void bringChildToFront(int id)
{ {
View view = m_surfaces.get(id); QtNative.runAction(new Runnable() {
if (view != null) { @Override
final int surfaceCount = getSurfaceCount(); public void run() {
if (surfaceCount > 0) View view = m_surfaces.get(id);
m_layout.moveChild(view, surfaceCount - 1); if (view != null) {
return; final int surfaceCount = getSurfaceCount();
} if (surfaceCount > 0)
m_layout.moveChild(view, surfaceCount - 1);
return;
}
view = m_nativeViews.get(id); view = m_nativeViews.get(id);
if (view != null) if (view != null)
m_layout.moveChild(view, -1); m_layout.moveChild(view, -1);
}
});
} }
public void bringChildToBack(int id) public void bringChildToBack(int id)
{ {
View view = m_surfaces.get(id); QtNative.runAction(new Runnable() {
if (view != null) { @Override
m_layout.moveChild(view, 0); public void run() {
return; View view = m_surfaces.get(id);
} if (view != null) {
m_layout.moveChild(view, 0);
return;
}
view = m_nativeViews.get(id); view = m_nativeViews.get(id);
if (view != null) { if (view != null) {
final int index = getSurfaceCount(); final int index = getSurfaceCount();
m_layout.moveChild(view, index); m_layout.moveChild(view, index);
} }
}
});
} }
} }

View File

@ -10,6 +10,8 @@ import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
public class QtEditText extends View public class QtEditText extends View
{ {
int m_initialCapsMode = 0; int m_initialCapsMode = 0;
@ -17,6 +19,13 @@ public class QtEditText extends View
int m_inputType = InputType.TYPE_CLASS_TEXT; int m_inputType = InputType.TYPE_CLASS_TEXT;
boolean m_optionsChanged = false; boolean m_optionsChanged = false;
private QtInputConnectionListener m_qtInputConnectionListener;
public void setQtInputConnectionListener(QtInputConnectionListener listener)
{
m_qtInputConnectionListener = listener;
}
public void setImeOptions(int m_imeOptions) public void setImeOptions(int m_imeOptions)
{ {
if (m_imeOptions == this.m_imeOptions) if (m_imeOptions == this.m_imeOptions)
@ -56,7 +65,7 @@ public class QtEditText extends View
outAttrs.imeOptions = m_imeOptions; outAttrs.imeOptions = m_imeOptions;
outAttrs.initialCapsMode = m_initialCapsMode; outAttrs.initialCapsMode = m_initialCapsMode;
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI; outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI;
return new QtInputConnection(this); return new QtInputConnection(this, m_qtInputConnectionListener);
} }
// // DEBUG CODE // // DEBUG CODE

View File

@ -51,31 +51,6 @@ class QtNativeInputConnection
static native boolean updateCursorPosition(); static native boolean updateCursorPosition();
} }
class HideKeyboardRunnable implements Runnable {
private long m_hideTimeStamp = System.nanoTime();
@Override
public void run() {
// Check that the keyboard is really no longer there.
Activity activity = QtNative.activity();
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
int screenHeight = 0;
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
screenHeight = metrics.heightPixels;
} else {
final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();
screenHeight = maximumWindowMetrics.getBounds().height();
}
final int kbHeight = screenHeight - r.bottom;
if (kbHeight < 100)
QtNative.activityDelegate().getInputDelegate().setKeyboardVisibility(false, m_hideTimeStamp);
}
}
public class QtInputConnection extends BaseInputConnection public class QtInputConnection extends BaseInputConnection
{ {
private static final int ID_SELECT_ALL = android.R.id.selectAll; private static final int ID_SELECT_ALL = android.R.id.selectAll;
@ -86,21 +61,52 @@ public class QtInputConnection extends BaseInputConnection
private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod;
private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary;
private final QtInputConnectionListener m_qtInputConnectionListener;
class HideKeyboardRunnable implements Runnable {
@Override
public void run() {
// Check that the keyboard is really no longer there.
Activity activity = QtNative.activity();
Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
int screenHeight = 0;
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
screenHeight = metrics.heightPixels;
} else {
final WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();
screenHeight = maximumWindowMetrics.getBounds().height();
}
final int kbHeight = screenHeight - r.bottom;
if (kbHeight < 100)
m_qtInputConnectionListener.onHideKeyboardRunnableDone(false, System.nanoTime());
}
}
public interface QtInputConnectionListener {
void onSetClosing(boolean closing);
void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp);
void onSendKeyEventDefaultCase();
}
private QtEditText m_view = null; private QtEditText m_view = null;
private void setClosing(boolean closing) private void setClosing(boolean closing)
{ {
if (closing) { if (closing)
m_view.postDelayed(new HideKeyboardRunnable(), 100); m_view.postDelayed(new HideKeyboardRunnable(), 100);
} else { else
QtNative.activityDelegate().getInputDelegate().setKeyboardVisibility(true, System.nanoTime()); m_qtInputConnectionListener.onSetClosing(false);
}
} }
public QtInputConnection(QtEditText targetView) public QtInputConnection(QtEditText targetView, QtInputConnectionListener listener)
{ {
super(targetView, true); super(targetView, true);
m_view = targetView; m_view = targetView;
m_qtInputConnectionListener = listener;
} }
@Override @Override
@ -256,7 +262,7 @@ public class QtInputConnection extends BaseInputConnection
break; break;
default: default:
QtNative.activityDelegate().getInputDelegate().hideSoftwareKeyboard(); m_qtInputConnectionListener.onSendKeyEventDefaultCase();
break; break;
} }
} }

View File

@ -4,6 +4,7 @@
package org.qtproject.qt.android; package org.qtproject.qt.android;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -17,6 +18,8 @@ import android.view.MotionEvent;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
public class QtInputDelegate { public class QtInputDelegate {
// keyboard methods // keyboard methods
@ -96,7 +99,7 @@ public class QtInputDelegate {
private int m_lastChar = 0; private int m_lastChar = 0;
private boolean m_backKeyPressedSent = false; private boolean m_backKeyPressedSent = false;
// Note: because of the circular call to updateFullScreen() from QtActivityDelegate, we need // Note: because of the circular call to updateFullScreen() from the delegate, we need
// a listener to be able to do that call from the delegate, because that's where that // a listener to be able to do that call from the delegate, because that's where that
// logic lives // logic lives
public interface KeyboardVisibilityListener { public interface KeyboardVisibilityListener {
@ -105,9 +108,29 @@ public class QtInputDelegate {
private final KeyboardVisibilityListener m_keyboardVisibilityListener; private final KeyboardVisibilityListener m_keyboardVisibilityListener;
QtInputDelegate(KeyboardVisibilityListener listener) QtInputDelegate(Activity activity, KeyboardVisibilityListener listener)
{ {
this.m_keyboardVisibilityListener = listener; this.m_keyboardVisibilityListener = listener;
m_editText = new QtEditText(activity);
m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
QtInputConnectionListener inputConnectionListener = new QtInputConnectionListener() {
@Override
public void onSetClosing(boolean closing) {
if (!closing)
setKeyboardVisibility(true, System.nanoTime());
}
@Override
public void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp) {
setKeyboardVisibility(visibility, hideTimeStamp);
}
@Override
public void onSendKeyEventDefaultCase() {
hideSoftwareKeyboard();
}
};
m_editText.setQtInputConnectionListener(inputConnectionListener);
} }
public boolean isKeyboardVisible() public boolean isKeyboardVisible()
@ -131,16 +154,6 @@ public class QtInputDelegate {
return m_editText; return m_editText;
} }
void setEditText(QtEditText editText)
{
m_editText = editText;
}
void setInputMethodManager(InputMethodManager inputMethodManager)
{
m_imm = inputMethodManager;
}
void setEditPopupMenu(EditPopupMenu editPopupMenu) void setEditPopupMenu(EditPopupMenu editPopupMenu)
{ {
m_editPopupMenu = editPopupMenu; m_editPopupMenu = editPopupMenu;

View File

@ -54,11 +54,10 @@ import android.graphics.Rect;
public class QtNative public class QtNative
{ {
// TODO get rid of the delegation from QtNative, call directly the Activity in c++
private static Activity m_activity = null; private static Activity m_activity = null;
private static boolean m_activityPaused = false; private static boolean m_activityPaused = false;
private static Service m_service = null; private static Service m_service = null;
private static QtActivityDelegate m_activityDelegate = null;
private static QtServiceDelegate m_serviceDelegate = null;
public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations public static Object m_mainActivityMutex = new Object(); // mutex used to synchronize runnable operations
public static final String QtTAG = "Qt JAVA"; // string used for Log.x public static final String QtTAG = "Qt JAVA"; // string used for Log.x
@ -81,8 +80,8 @@ public class QtNative
public static boolean isStarted() public static boolean isStarted()
{ {
boolean hasActivity = m_activity != null && m_activityDelegate != null; boolean hasActivity = m_activity != null;
boolean hasService = m_service != null && m_serviceDelegate != null; boolean hasService = m_service != null;
return m_started && (hasActivity || hasService); return m_started && (hasActivity || hasService);
} }
@ -111,21 +110,6 @@ public class QtNative
} }
} }
public static QtActivityDelegate activityDelegate()
{
synchronized (m_mainActivityMutex) {
return m_activityDelegate;
}
}
public static QtServiceDelegate serviceDelegate()
{
synchronized (m_mainActivityMutex) {
return m_serviceDelegate;
}
}
public static String[] getStringArray(String joinedString) public static String[] getStringArray(String joinedString)
{ {
return joinedString.split(","); return joinedString.split(",");
@ -204,19 +188,17 @@ public class QtNative
return m_qtThread; return m_qtThread;
} }
public static void setActivity(Activity qtMainActivity, QtActivityDelegate qtActivityDelegate) public static void setActivity(Activity qtMainActivity)
{ {
synchronized (m_mainActivityMutex) { synchronized (m_mainActivityMutex) {
m_activity = qtMainActivity; m_activity = qtMainActivity;
m_activityDelegate = qtActivityDelegate;
} }
} }
public static void setService(Service qtMainService, QtServiceDelegate qtServiceDelegate) public static void setService(Service qtMainService)
{ {
synchronized (m_mainActivityMutex) { synchronized (m_mainActivityMutex) {
m_service = qtMainService; m_service = qtMainService;
m_serviceDelegate = qtServiceDelegate;
} }
} }
@ -349,72 +331,6 @@ public class QtNative
return perm; return perm;
} }
// TODO get rid of the delegation from QtNative, call directly the Activity in c++
private static void setSystemUiVisibility(final int systemUiVisibility)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null) {
m_activityDelegate.setSystemUiVisibility(systemUiVisibility);
}
updateWindow();
}
});
}
public static void notifyQtAndroidPluginRunning(final boolean running)
{
if (m_activityDelegate != null)
m_activityDelegate.notifyQtAndroidPluginRunning(running);
}
private static void openContextMenu(final int x, final int y, final int w, final int h)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.openContextMenu(x, y, w, h);
}
});
}
private static void closeContextMenu()
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.closeContextMenu();
}
});
}
private static void resetOptionsMenu()
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.resetOptionsMenu();
}
});
}
private static void openOptionsMenu()
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activity != null)
m_activity.openOptionsMenu();
}
});
}
private static byte[][] getSSLCertificates() private static byte[][] getSSLCertificates()
{ {
ArrayList<byte[]> certificateList = new ArrayList<byte[]>(); ArrayList<byte[]> certificateList = new ArrayList<byte[]>();
@ -442,83 +358,6 @@ public class QtNative
return certificateArray; return certificateArray;
} }
private static void createSurface(final int id, final boolean onTop, final int x, final int y, final int w, final int h, final int imageDepth)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.createSurface(id, onTop, x, y, w, h, imageDepth);
}
});
}
private static void insertNativeView(final int id, final View view, final int x, final int y, final int w, final int h)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.insertNativeView(id, view, x, y, w, h);
}
});
}
private static void setSurfaceGeometry(final int id, final int x, final int y, final int w, final int h)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.setSurfaceGeometry(id, x, y, w, h);
}
});
}
private static void bringChildToFront(final int id)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.bringChildToFront(id);
}
});
}
private static void bringChildToBack(final int id)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.bringChildToBack(id);
}
});
}
private static void destroySurface(final int id)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.destroySurface(id);
}
});
}
private static void hideSplashScreen(final int duration)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
m_activityDelegate.hideSplashScreen(duration);
}
});
}
private static String[] listAssetContent(android.content.res.AssetManager asset, String path) { private static String[] listAssetContent(android.content.res.AssetManager asset, String path) {
String [] list; String [] list;
ArrayList<String> res = new ArrayList<String>(); ArrayList<String> res = new ArrayList<String>();

View File

@ -9,15 +9,11 @@ import android.os.IBinder;
import android.util.Log; import android.util.Log;
public class QtServiceBase extends Service { public class QtServiceBase extends Service {
private QtServiceDelegate m_delegate;
@Override @Override
public void onCreate() public void onCreate()
{ {
super.onCreate(); super.onCreate();
m_delegate = new QtServiceDelegate(this);
// the application has already started, do not reload everything again // the application has already started, do not reload everything again
if (QtNative.isStarted()) { if (QtNative.isStarted()) {
Log.w(QtNative.QtTAG, Log.w(QtNative.QtTAG,
@ -38,7 +34,7 @@ public class QtServiceBase extends Service {
super.onDestroy(); super.onDestroy();
QtNative.quitQtCoreApplication(); QtNative.quitQtCoreApplication();
QtNative.terminateQt(); QtNative.terminateQt();
QtNative.setService(null, null); QtNative.setService(null);
QtNative.m_qtThread.exit(); QtNative.m_qtThread.exit();
System.exit(0); System.exit(0);
} }
@ -49,9 +45,4 @@ public class QtServiceBase extends Service {
return QtNative.onBind(intent); return QtNative.onBind(intent);
} }
} }
QtServiceDelegate getServiceDelegate()
{
return m_delegate;
}
} }

View File

@ -1,20 +0,0 @@
// Copyright (C) 2016 BogDan Vatra <bogdan@kde.org>
// Copyright (C) 2023 The Qt Company Ltd.
// 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.Service;
public class QtServiceDelegate
{
private Service m_service = null;
QtServiceDelegate(Service service)
{
m_service = service;
// Set native context
QtNative.setService(m_service, this);
}
}

View File

@ -94,8 +94,7 @@ int QNativeInterface::QAndroidApplication::sdkVersion()
*/ */
void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration) void QNativeInterface::QAndroidApplication::hideSplashScreen(int duration)
{ {
QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative", QtAndroidPrivate::activity().callMethod<void>("hideSplashScreen", duration);
"hideSplashScreen", "(I)V", duration);
} }
/*! /*!

View File

@ -45,9 +45,6 @@ static jmethodID m_loadClassMethodID = nullptr;
static AAssetManager *m_assetManager = nullptr; static AAssetManager *m_assetManager = nullptr;
static jobject m_assets = nullptr; static jobject m_assets = nullptr;
static jobject m_resourcesObj = nullptr; static jobject m_resourcesObj = nullptr;
static jmethodID m_createSurfaceMethodID = nullptr;
static jmethodID m_setSurfaceGeometryMethodID = nullptr;
static jmethodID m_destroySurfaceMethodID = nullptr;
static QtJniTypes::QtActivityDelegate m_activityDelegate = nullptr; static QtJniTypes::QtActivityDelegate m_activityDelegate = nullptr;
static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr; static QtJniTypes::QtInputDelegate m_inputDelegate = nullptr;
@ -165,7 +162,7 @@ namespace QtAndroid
// TODO move calls from here to where they logically belong // TODO move calls from here to where they logically belong
void setSystemUiVisibility(SystemUiVisibility uiVisibility) void setSystemUiVisibility(SystemUiVisibility uiVisibility)
{ {
QJniObject::callStaticMethod<void>(m_applicationClass, "setSystemUiVisibility", "(I)V", jint(uiVisibility)); qtActivityDelegate().callMethod<void>("setSystemUiVisibility", jint(uiVisibility));
} }
// FIXME: avoid direct access to QtActivityDelegate // FIXME: avoid direct access to QtActivityDelegate
@ -218,7 +215,7 @@ namespace QtAndroid
void notifyQtAndroidPluginRunning(bool running) void notifyQtAndroidPluginRunning(bool running)
{ {
QJniObject::callStaticMethod<void>(m_applicationClass, "notifyQtAndroidPluginRunning","(Z)V", running); qtActivityDelegate().callMethod<void>("notifyQtAndroidPluginRunning", running);
} }
jobject createBitmap(QImage img, JNIEnv *env) jobject createBitmap(QImage img, JNIEnv *env)
@ -338,12 +335,8 @@ namespace QtAndroid
w = std::max(geometry.width(), 1); w = std::max(geometry.width(), 1);
h = std::max(geometry.height(), 1); h = std::max(geometry.height(), 1);
} }
env->CallStaticVoidMethod(m_applicationClass, qtActivityDelegate().callMethod<void>("createSurface", surfaceId, jboolean(onTop),
m_createSurfaceMethodID, x, y, w, h, imageDepth);
surfaceId,
jboolean(onTop),
x, y, w, h,
imageDepth);
return surfaceId; return surfaceId;
} }
@ -358,9 +351,7 @@ namespace QtAndroid
if (!geometry.isNull()) if (!geometry.isNull())
geometry.getRect(&x, &y, &w, &h); geometry.getRect(&x, &y, &w, &h);
QJniObject::callStaticMethod<void>(m_applicationClass, qtActivityDelegate().callMethod<void>("insertNativeView",
"insertNativeView",
"(ILandroid/view/View;IIII)V",
surfaceId, surfaceId,
view, view,
x, x,
@ -395,10 +386,7 @@ namespace QtAndroid
w = geometry.width(); w = geometry.width();
h = geometry.height(); h = geometry.height();
} }
env->CallStaticVoidMethod(m_applicationClass, qtActivityDelegate().callMethod<void>("setSurfaceGeometry", surfaceId, x, y, w, h);
m_setSurfaceGeometryMethodID,
surfaceId,
x, y, w, h);
} }
@ -414,11 +402,7 @@ namespace QtAndroid
m_surfaces.erase(it); m_surfaces.erase(it);
} }
QJniEnvironment env; qtActivityDelegate().callMethod<void>("destroySurface", surfaceId);
if (env.jniEnv())
env->CallStaticVoidMethod(m_applicationClass,
m_destroySurfaceMethodID,
surfaceId);
} }
void bringChildToFront(int surfaceId) void bringChildToFront(int surfaceId)
@ -426,10 +410,7 @@ namespace QtAndroid
if (surfaceId == -1) if (surfaceId == -1)
return; return;
QJniObject::callStaticMethod<void>(m_applicationClass, qtActivityDelegate().callMethod<void>("bringChildToFront", surfaceId);
"bringChildToFront",
"(I)V",
surfaceId);
} }
void bringChildToBack(int surfaceId) void bringChildToBack(int surfaceId)
@ -437,10 +418,7 @@ namespace QtAndroid
if (surfaceId == -1) if (surfaceId == -1)
return; return;
QJniObject::callStaticMethod<void>(m_applicationClass, qtActivityDelegate().callMethod<void>("bringChildToBack", surfaceId);
"bringChildToBack",
"(I)V",
surfaceId);
} }
bool blockEventLoopsWhenSuspended() bool blockEventLoopsWhenSuspended()
@ -893,10 +871,6 @@ static bool registerNatives(QJniEnvironment &env)
return JNI_FALSE; return JNI_FALSE;
} }
GET_AND_CHECK_STATIC_METHOD(m_createSurfaceMethodID, m_applicationClass, "createSurface", "(IZIIIII)V");
GET_AND_CHECK_STATIC_METHOD(m_setSurfaceGeometryMethodID, m_applicationClass, "setSurfaceGeometry", "(IIIII)V");
GET_AND_CHECK_STATIC_METHOD(m_destroySurfaceMethodID, m_applicationClass, "destroySurface", "(I)V");
jmethodID methodID; jmethodID methodID;
GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;"); GET_AND_CHECK_STATIC_METHOD(methodID, m_applicationClass, "activity", "()Landroid/app/Activity;");
jobject contextObject = env->CallStaticObjectMethod(m_applicationClass, methodID); jobject contextObject = env->CallStaticObjectMethod(m_applicationClass, methodID);

View File

@ -31,8 +31,6 @@ namespace QtAndroidMenu
static QWindow *activeTopLevelWindow = nullptr; static QWindow *activeTopLevelWindow = nullptr;
Q_CONSTINIT static QRecursiveMutex menuBarMutex; Q_CONSTINIT static QRecursiveMutex menuBarMutex;
static jmethodID openContextMenuMethodID = 0;
static jmethodID clearMenuMethodID = 0; static jmethodID clearMenuMethodID = 0;
static jmethodID addMenuItemMethodID = 0; static jmethodID addMenuItemMethodID = 0;
static int menuNoneValue = 0; static int menuNoneValue = 0;
@ -46,29 +44,31 @@ namespace QtAndroidMenu
void resetMenuBar() void resetMenuBar()
{ {
QJniObject::callStaticMethod<void>(applicationClass(), "resetOptionsMenu"); qtActivityDelegate().callMethod<void>("resetOptionsMenu");
} }
void openOptionsMenu() void openOptionsMenu()
{ {
QJniObject::callStaticMethod<void>(applicationClass(), "openOptionsMenu"); qtActivityDelegate().callMethod<void>("openOptionsMenu");
} }
void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env) void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect)
{ {
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (visibleMenu) if (visibleMenu)
pendingContextMenus.append(visibleMenu); pendingContextMenus.append(visibleMenu);
visibleMenu = menu; visibleMenu = menu;
menu->aboutToShow(); menu->aboutToShow();
env->CallStaticVoidMethod(applicationClass(), openContextMenuMethodID, anchorRect.x(), anchorRect.y(), anchorRect.width(), anchorRect.height()); qtActivityDelegate().callMethod<void>("openContextMenu",
anchorRect.x(), anchorRect.y(),
anchorRect.width(), anchorRect.height());
} }
void hideContextMenu(QAndroidPlatformMenu *menu) void hideContextMenu(QAndroidPlatformMenu *menu)
{ {
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (visibleMenu == menu) { if (visibleMenu == menu) {
QJniObject::callStaticMethod<void>(applicationClass(), "closeContextMenu"); qtActivityDelegate().callMethod<void>("closeContextMenu");
pendingContextMenus.clear(); pendingContextMenus.clear();
} else { } else {
pendingContextMenus.removeOne(menu); pendingContextMenus.removeOne(menu);
@ -211,8 +211,10 @@ namespace QtAndroidMenu
return order; return order;
} }
static jboolean onPrepareOptionsMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) static jboolean onPrepareOptionsMenu(JNIEnv *env, jobject thiz, jobject menu)
{ {
Q_UNUSED(thiz)
env->CallVoidMethod(menu, clearMenuMethodID); env->CallVoidMethod(menu, clearMenuMethodID);
QMutexLocker lock(&menuBarMutex); QMutexLocker lock(&menuBarMutex);
if (!visibleMenuBar) if (!visibleMenuBar)
@ -249,8 +251,11 @@ namespace QtAndroidMenu
return order ? JNI_TRUE : JNI_FALSE; return order ? JNI_TRUE : JNI_FALSE;
} }
static jboolean onOptionsItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked) static jboolean onOptionsItemSelected(JNIEnv *env, jobject thiz, jint menuId, jboolean checked)
{ {
Q_UNUSED(env)
Q_UNUSED(thiz)
QMutexLocker lock(&menuBarMutex); QMutexLocker lock(&menuBarMutex);
if (!visibleMenuBar) if (!visibleMenuBar)
return JNI_FALSE; return JNI_FALSE;
@ -260,7 +265,7 @@ namespace QtAndroidMenu
QAndroidPlatformMenuItem *item = static_cast<QAndroidPlatformMenuItem *>(menus.front()->menuItemForId(menuId)); QAndroidPlatformMenuItem *item = static_cast<QAndroidPlatformMenuItem *>(menus.front()->menuItemForId(menuId));
if (item) { if (item) {
if (item->menu()) { if (item->menu()) {
showContextMenu(item->menu(), QRect(), env); showContextMenu(item->menu(), QRect());
} else { } else {
if (item->isCheckable()) if (item->isCheckable())
item->setChecked(checked); item->setChecked(checked);
@ -270,18 +275,23 @@ namespace QtAndroidMenu
} else { } else {
QAndroidPlatformMenu *menu = static_cast<QAndroidPlatformMenu *>(visibleMenuBar->menuForId(menuId)); QAndroidPlatformMenu *menu = static_cast<QAndroidPlatformMenu *>(visibleMenuBar->menuForId(menuId));
if (menu) if (menu)
showContextMenu(menu, QRect(), env); showContextMenu(menu, QRect());
} }
return JNI_TRUE; return JNI_TRUE;
} }
static void onOptionsMenuClosed(JNIEnv */*env*/, jobject /*thiz*/, jobject /*menu*/) static void onOptionsMenuClosed(JNIEnv *env, jobject thiz, jobject menu)
{ {
Q_UNUSED(env)
Q_UNUSED(thiz)
Q_UNUSED(menu)
} }
static void onCreateContextMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) static void onCreateContextMenu(JNIEnv *env, jobject thiz, jobject menu)
{ {
Q_UNUSED(thiz)
env->CallVoidMethod(menu, clearMenuMethodID); env->CallVoidMethod(menu, clearMenuMethodID);
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (!visibleMenu) if (!visibleMenu)
@ -295,8 +305,9 @@ namespace QtAndroidMenu
addAllMenuItemsToMenu(env, menu, visibleMenu); addAllMenuItemsToMenu(env, menu, visibleMenu);
} }
static void fillContextMenu(JNIEnv *env, jobject /*thiz*/, jobject menu) static void fillContextMenu(JNIEnv *env, jobject thiz, jobject menu)
{ {
Q_UNUSED(thiz)
env->CallVoidMethod(menu, clearMenuMethodID); env->CallVoidMethod(menu, clearMenuMethodID);
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (!visibleMenu) if (!visibleMenu)
@ -305,13 +316,16 @@ namespace QtAndroidMenu
addAllMenuItemsToMenu(env, menu, visibleMenu); addAllMenuItemsToMenu(env, menu, visibleMenu);
} }
static jboolean onContextItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked) static jboolean onContextItemSelected(JNIEnv *env, jobject thiz, jint menuId, jboolean checked)
{ {
Q_UNUSED(env)
Q_UNUSED(thiz)
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
QAndroidPlatformMenuItem * item = static_cast<QAndroidPlatformMenuItem *>(visibleMenu->menuItemForId(menuId)); QAndroidPlatformMenuItem * item = static_cast<QAndroidPlatformMenuItem *>(visibleMenu->menuItemForId(menuId));
if (item) { if (item) {
if (item->menu()) { if (item->menu()) {
showContextMenu(item->menu(), QRect(), env); showContextMenu(item->menu(), QRect());
} else { } else {
if (item->isCheckable()) if (item->isCheckable())
item->setChecked(checked); item->setChecked(checked);
@ -328,8 +342,12 @@ namespace QtAndroidMenu
return JNI_TRUE; return JNI_TRUE;
} }
static void onContextMenuClosed(JNIEnv *env, jobject /*thiz*/, jobject /*menu*/) static void onContextMenuClosed(JNIEnv *env, jobject thiz, jobject menu)
{ {
Q_UNUSED(env)
Q_UNUSED(thiz)
Q_UNUSED(menu)
QMutexLocker lock(&visibleMenuMutex); QMutexLocker lock(&visibleMenuMutex);
if (!visibleMenu) if (!visibleMenu)
return; return;
@ -337,7 +355,7 @@ namespace QtAndroidMenu
visibleMenu->aboutToHide(); visibleMenu->aboutToHide();
visibleMenu = 0; visibleMenu = 0;
if (!pendingContextMenus.empty()) if (!pendingContextMenus.empty())
showContextMenu(pendingContextMenus.takeLast(), QRect(), env); showContextMenu(pendingContextMenus.takeLast(), QRect());
} }
static JNINativeMethod methods[] = { static JNINativeMethod methods[] = {
@ -387,8 +405,6 @@ namespace QtAndroidMenu
return false; return false;
} }
GET_AND_CHECK_STATIC_METHOD(openContextMenuMethodID, appClass, "openContextMenu", "(IIII)V");
jclass clazz; jclass clazz;
FIND_AND_CHECK_CLASS("android/view/Menu"); FIND_AND_CHECK_CLASS("android/view/Menu");
GET_AND_CHECK_METHOD(clearMenuMethodID, clazz, "clear", "()V"); GET_AND_CHECK_METHOD(clearMenuMethodID, clazz, "clear", "()V");

View File

@ -21,7 +21,7 @@ namespace QtAndroidMenu
{ {
// Menu support // Menu support
void openOptionsMenu(); void openOptionsMenu();
void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect, JNIEnv *env); void showContextMenu(QAndroidPlatformMenu *menu, const QRect &anchorRect);
void hideContextMenu(QAndroidPlatformMenu *menu); void hideContextMenu(QAndroidPlatformMenu *menu);
void syncMenu(QAndroidPlatformMenu *menu); void syncMenu(QAndroidPlatformMenu *menu);
void androidPlatformMenuDestroyed(QAndroidPlatformMenu *menu); void androidPlatformMenuDestroyed(QAndroidPlatformMenu *menu);

View File

@ -119,7 +119,7 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t
Q_UNUSED(parentWindow); Q_UNUSED(parentWindow);
Q_UNUSED(item); Q_UNUSED(item);
setVisible(true); setVisible(true);
QtAndroidMenu::showContextMenu(this, targetRect, QJniEnvironment().jniEnv()); QtAndroidMenu::showContextMenu(this, targetRect);
} }
QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const

View File

@ -199,11 +199,14 @@ void tst_Android::testRunOnAndroidMainThread()
} }
} }
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
void setSystemUiVisibility(int visibility) void setSystemUiVisibility(int visibility)
{ {
QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] { QNativeInterface::QAndroidApplication::runOnAndroidMainThread([visibility] {
QJniObject::callStaticMethod<void>("org/qtproject/qt/android/QtNative", auto context = QNativeInterface::QAndroidApplication::context();
"setSystemUiVisibility", "(I)V", visibility); auto activityDelegate = context.callMethod<QtJniTypes::QtActivityDelegate>("getActivityDelegate");
activityDelegate.callMethod<void>("setSystemUiVisibility", jint(visibility));
}).waitForFinished(); }).waitForFinished();
} }