Android: Make QtLayout per window instead of per screen
Each QAndroidPlatformWindow has its own QtLayout, instead of one for the whole app/screen. This paves the way for addition of child windows. Task-number: QTBUG-116187 Change-Id: I36c68cea1a5f27ded3696bcfc2fbc04d9a8ce79e Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
parent
0bfec6cd11
commit
0a92d881bb
@ -29,6 +29,7 @@ set(java_sources
|
|||||||
src/org/qtproject/qt/android/QtClipboardManager.java
|
src/org/qtproject/qt/android/QtClipboardManager.java
|
||||||
src/org/qtproject/qt/android/QtDisplayManager.java
|
src/org/qtproject/qt/android/QtDisplayManager.java
|
||||||
src/org/qtproject/qt/android/UsedFromNativeCode.java
|
src/org/qtproject/qt/android/UsedFromNativeCode.java
|
||||||
|
src/org/qtproject/qt/android/QtWindow.java
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
|
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
|
||||||
|
@ -36,9 +36,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
|
|
||||||
private View m_view = null;
|
private View m_view = null;
|
||||||
private final AccessibilityManager m_manager;
|
private final AccessibilityManager m_manager;
|
||||||
private final QtActivityDelegate m_activityDelegate;
|
private final QtLayout m_layout;
|
||||||
private final Activity m_activity;
|
|
||||||
private final ViewGroup m_layout;
|
|
||||||
|
|
||||||
// The accessible object that currently has the "accessibility focus"
|
// The accessible object that currently has the "accessibility focus"
|
||||||
// usually indicated by a yellow rectangle on screen.
|
// usually indicated by a yellow rectangle on screen.
|
||||||
@ -62,13 +60,11 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public QtAccessibilityDelegate(Activity activity, ViewGroup layout, QtActivityDelegate activityDelegate)
|
public QtAccessibilityDelegate(QtLayout layout)
|
||||||
{
|
{
|
||||||
m_activity = activity;
|
|
||||||
m_layout = layout;
|
m_layout = layout;
|
||||||
m_activityDelegate = activityDelegate;
|
|
||||||
|
|
||||||
m_manager = (AccessibilityManager) m_activity.getSystemService(Context.ACCESSIBILITY_SERVICE);
|
m_manager = (AccessibilityManager) m_layout.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
|
||||||
if (m_manager != null) {
|
if (m_manager != null) {
|
||||||
AccessibilityManagerListener accServiceListener = new AccessibilityManagerListener();
|
AccessibilityManagerListener accServiceListener = new AccessibilityManagerListener();
|
||||||
if (!m_manager.addAccessibilityStateChangeListener(accServiceListener))
|
if (!m_manager.addAccessibilityStateChangeListener(accServiceListener))
|
||||||
@ -89,7 +85,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
try {
|
try {
|
||||||
View view = m_view;
|
View view = m_view;
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
view = new View(m_activity);
|
view = new View(m_layout.getContext());
|
||||||
view.setId(View.NO_ID);
|
view.setId(View.NO_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +101,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
// if all is fine, add it to the layout
|
// if all is fine, add it to the layout
|
||||||
if (m_view == null) {
|
if (m_view == null) {
|
||||||
//m_layout.addAccessibilityView(view);
|
//m_layout.addAccessibilityView(view);
|
||||||
m_layout.addView(view, m_activityDelegate.getSurfaceCount(),
|
m_layout.addView(view, m_layout.getChildCount(),
|
||||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||||
}
|
}
|
||||||
m_view = view;
|
m_view = view;
|
||||||
@ -289,7 +285,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_activityDelegate.getSurfaceCount() == 0)
|
if (m_layout.getChildCount() == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
|
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
|
||||||
@ -356,7 +352,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
// Spit out the entire hierarchy for debugging purposes
|
// Spit out the entire hierarchy for debugging purposes
|
||||||
// dumpNodes(-1);
|
// dumpNodes(-1);
|
||||||
|
|
||||||
if (m_activityDelegate.getSurfaceCount() != 0) {
|
if (m_layout.getChildCount() == 0) {
|
||||||
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
|
int[] ids = QtNativeAccessibility.childIdListForAccessibleObject(-1);
|
||||||
for (int id : ids)
|
for (int id : ids)
|
||||||
result.addChild(m_view, id);
|
result.addChild(m_view, id);
|
||||||
@ -388,7 +384,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
node.setClassName(m_view.getClass().getName() + DEFAULT_CLASS_NAME);
|
||||||
node.setPackageName(m_view.getContext().getPackageName());
|
node.setPackageName(m_view.getContext().getPackageName());
|
||||||
|
|
||||||
if (m_activityDelegate.getSurfaceCount() == 0 || !QtNativeAccessibility.populateNode(virtualViewId, node)) {
|
if (m_layout.getChildCount() == 0 || !QtNativeAccessibility.populateNode(virtualViewId, node)) {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +435,7 @@ class QtAccessibilityDelegate extends View.AccessibilityDelegate
|
|||||||
@Override
|
@Override
|
||||||
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
|
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId)
|
||||||
{
|
{
|
||||||
if (virtualViewId == View.NO_ID || m_activityDelegate.getSurfaceCount() == 0) {
|
if (virtualViewId == View.NO_ID || m_layout.getChildCount() == 0) {
|
||||||
return getNodeForView();
|
return getNodeForView();
|
||||||
}
|
}
|
||||||
return getNodeForVirtualViewId(virtualViewId);
|
return getNodeForVirtualViewId(virtualViewId);
|
||||||
|
@ -11,6 +11,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
@ -36,9 +37,8 @@ class QtActivityDelegate
|
|||||||
{
|
{
|
||||||
private Activity m_activity;
|
private Activity m_activity;
|
||||||
|
|
||||||
private HashMap<Integer, QtSurface> m_surfaces = null;
|
|
||||||
private HashMap<Integer, View> m_nativeViews = null;
|
|
||||||
private QtLayout m_layout = null;
|
private QtLayout m_layout = null;
|
||||||
|
private HashMap<Integer, QtWindow> m_topLevelWindows;
|
||||||
private ImageView m_splashScreen = null;
|
private ImageView m_splashScreen = null;
|
||||||
private boolean m_splashScreenSticky = false;
|
private boolean m_splashScreenSticky = false;
|
||||||
|
|
||||||
@ -48,6 +48,7 @@ class QtActivityDelegate
|
|||||||
private QtDisplayManager m_displayManager = null;
|
private QtDisplayManager m_displayManager = null;
|
||||||
|
|
||||||
private QtInputDelegate m_inputDelegate = null;
|
private QtInputDelegate m_inputDelegate = null;
|
||||||
|
private boolean m_membersInitialized = false;
|
||||||
|
|
||||||
QtActivityDelegate(Activity activity)
|
QtActivityDelegate(Activity activity)
|
||||||
{
|
{
|
||||||
@ -55,6 +56,7 @@ class QtActivityDelegate
|
|||||||
QtNative.setActivity(m_activity);
|
QtNative.setActivity(m_activity);
|
||||||
|
|
||||||
setActionBarVisibility(false);
|
setActionBarVisibility(false);
|
||||||
|
setActivityBackgroundDrawable();
|
||||||
}
|
}
|
||||||
|
|
||||||
QtDisplayManager displayManager() {
|
QtDisplayManager displayManager() {
|
||||||
@ -116,7 +118,7 @@ class QtActivityDelegate
|
|||||||
|
|
||||||
public void startNativeApplication(String appParams, String mainLib)
|
public void startNativeApplication(String appParams, String mainLib)
|
||||||
{
|
{
|
||||||
if (m_surfaces != null)
|
if (m_membersInitialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
initMembers();
|
initMembers();
|
||||||
@ -134,6 +136,8 @@ class QtActivityDelegate
|
|||||||
private void initMembers()
|
private void initMembers()
|
||||||
{
|
{
|
||||||
m_layout = new QtLayout(m_activity);
|
m_layout = new QtLayout(m_activity);
|
||||||
|
m_membersInitialized = true;
|
||||||
|
m_topLevelWindows = new HashMap<Integer, QtWindow>();
|
||||||
|
|
||||||
m_displayManager = new QtDisplayManager(m_activity);
|
m_displayManager = new QtDisplayManager(m_activity);
|
||||||
m_displayManager.registerDisplayListener();
|
m_displayManager.registerDisplayListener();
|
||||||
@ -173,8 +177,6 @@ class QtActivityDelegate
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_surfaces = new HashMap<>();
|
|
||||||
m_nativeViews = new HashMap<>();
|
|
||||||
m_activity.registerForContextMenu(m_layout);
|
m_activity.registerForContextMenu(m_layout);
|
||||||
m_activity.setContentView(m_layout,
|
m_activity.setContentView(m_layout,
|
||||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
@ -293,9 +295,7 @@ class QtActivityDelegate
|
|||||||
@UsedFromNativeCode
|
@UsedFromNativeCode
|
||||||
public void initializeAccessibility()
|
public void initializeAccessibility()
|
||||||
{
|
{
|
||||||
final QtActivityDelegate currentDelegate = this;
|
QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_layout));
|
||||||
QtNative.runAction(() -> m_accessibilityDelegate = new QtAccessibilityDelegate(m_activity,
|
|
||||||
m_layout, currentDelegate));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleUiModeChange(int uiMode)
|
void handleUiModeChange(int uiMode)
|
||||||
@ -377,135 +377,52 @@ class QtActivityDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
@UsedFromNativeCode
|
@UsedFromNativeCode
|
||||||
public void insertNativeView(int id, View view, int x, int y, int w, int h) {
|
public void addTopLevelWindow(final QtWindow window)
|
||||||
QtNative.runAction(() -> {
|
{
|
||||||
if (m_dummyView != null) {
|
QtNative.runAction(()-> {
|
||||||
m_layout.removeView(m_dummyView);
|
if (m_topLevelWindows.size() == 0) {
|
||||||
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
|
|
||||||
public void createSurface(int id, boolean onTop, int x, int y, int w, int h, int imageDepth) {
|
|
||||||
QtNative.runAction(() -> {
|
|
||||||
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, m_activity.getTheme()));
|
|
||||||
}
|
|
||||||
if (m_dummyView != null) {
|
if (m_dummyView != null) {
|
||||||
m_layout.removeView(m_dummyView);
|
m_layout.removeView(m_dummyView);
|
||||||
m_dummyView = null;
|
m_dummyView = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_surfaces.containsKey(id))
|
window.setLayoutParams(new ViewGroup.LayoutParams(
|
||||||
m_layout.removeView(m_surfaces.remove(id));
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT));
|
||||||
|
|
||||||
QtSurface surface = new QtSurface(m_activity, id, onTop, imageDepth);
|
m_layout.addView(window, m_topLevelWindows.size());
|
||||||
if (w < 0 || h < 0) {
|
m_topLevelWindows.put(window.getId(), window);
|
||||||
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)
|
if (!m_splashScreenSticky)
|
||||||
hideSplashScreen();
|
hideSplashScreen();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@UsedFromNativeCode
|
@UsedFromNativeCode
|
||||||
public void setSurfaceGeometry(int id, int x, int y, int w, int h) {
|
public void removeTopLevelWindow(final int id)
|
||||||
QtNative.runAction(() -> {
|
{
|
||||||
if (m_surfaces.containsKey(id)) {
|
QtNative.runAction(()-> {
|
||||||
QtSurface surface = m_surfaces.get(id);
|
if (m_topLevelWindows.containsKey(id)) {
|
||||||
if (surface != null)
|
QtWindow window = m_topLevelWindows.remove(id);
|
||||||
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
if (m_topLevelWindows.isEmpty()) {
|
||||||
else
|
// Keep last frame in stack until it is replaced to get correct
|
||||||
Log.e(QtNative.QtTAG, "setSurfaceGeometry(): surface is null!");
|
// shutdown transition
|
||||||
} else if (m_nativeViews.containsKey(id)) {
|
m_dummyView = window;
|
||||||
View view = m_nativeViews.get(id);
|
} else {
|
||||||
if (view != null)
|
m_layout.removeView(window);
|
||||||
view.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
}
|
||||||
else
|
|
||||||
Log.e(QtNative.QtTAG, "setSurfaceGeometry(): view is null!");
|
|
||||||
} else {
|
|
||||||
Log.e(QtNative.QtTAG, "Surface " + id + " not found!");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@UsedFromNativeCode
|
@UsedFromNativeCode
|
||||||
public void destroySurface(int id) {
|
public void bringChildToFront(final int id)
|
||||||
QtNative.runAction(() -> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSurfaceCount()
|
|
||||||
{
|
|
||||||
return m_surfaces.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@UsedFromNativeCode
|
|
||||||
public void bringChildToFront(int id)
|
|
||||||
{
|
{
|
||||||
QtNative.runAction(() -> {
|
QtNative.runAction(() -> {
|
||||||
View view = m_surfaces.get(id);
|
QtWindow window = m_topLevelWindows.get(id);
|
||||||
if (view != null) {
|
if (window != null) {
|
||||||
final int surfaceCount = getSurfaceCount();
|
m_layout.moveChild(window, m_topLevelWindows.size() - 1);
|
||||||
if (surfaceCount > 0)
|
|
||||||
m_layout.moveChild(view, surfaceCount - 1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view = m_nativeViews.get(id);
|
|
||||||
if (view != null)
|
|
||||||
m_layout.moveChild(view, -1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,17 +430,26 @@ class QtActivityDelegate
|
|||||||
public void bringChildToBack(int id)
|
public void bringChildToBack(int id)
|
||||||
{
|
{
|
||||||
QtNative.runAction(() -> {
|
QtNative.runAction(() -> {
|
||||||
View view = m_surfaces.get(id);
|
QtWindow window = m_topLevelWindows.get(id);
|
||||||
if (view != null) {
|
if (window != null)
|
||||||
m_layout.moveChild(view, 0);
|
m_layout.moveChild(window, 0);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
view = m_nativeViews.get(id);
|
|
||||||
if (view != null) {
|
|
||||||
final int index = getSurfaceCount();
|
|
||||||
m_layout.moveChild(view, index);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setActivityBackgroundDrawable()
|
||||||
|
{
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activity.getWindow().setBackgroundDrawable(backgroundDrawable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import android.content.Context;
|
|||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.Surface;
|
||||||
import android.view.SurfaceHolder;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.SurfaceView;
|
import android.view.SurfaceView;
|
||||||
|
|
||||||
@ -16,24 +17,33 @@ import android.view.SurfaceView;
|
|||||||
class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
||||||
{
|
{
|
||||||
private final GestureDetector m_gestureDetector;
|
private final GestureDetector m_gestureDetector;
|
||||||
|
private Object m_accessibilityDelegate = null;
|
||||||
|
private SurfaceChangedCallback m_surfaceCallback;
|
||||||
|
private final int m_windowId;
|
||||||
|
|
||||||
public QtSurface(Context context, int id, boolean onTop, int imageDepth)
|
interface SurfaceChangedCallback {
|
||||||
|
void onSurfaceChanged(Surface surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
public QtSurface(Context context, SurfaceChangedCallback surfaceCallback, int id, boolean onTop,
|
||||||
|
int imageDepth)
|
||||||
{
|
{
|
||||||
super(context);
|
super(context);
|
||||||
setFocusable(false);
|
setFocusable(false);
|
||||||
setFocusableInTouchMode(false);
|
setFocusableInTouchMode(false);
|
||||||
setZOrderMediaOverlay(onTop);
|
setZOrderMediaOverlay(onTop);
|
||||||
|
m_surfaceCallback = surfaceCallback;
|
||||||
getHolder().addCallback(this);
|
getHolder().addCallback(this);
|
||||||
if (imageDepth == 16)
|
if (imageDepth == 16)
|
||||||
getHolder().setFormat(PixelFormat.RGB_565);
|
getHolder().setFormat(PixelFormat.RGB_565);
|
||||||
else
|
else
|
||||||
getHolder().setFormat(PixelFormat.RGBA_8888);
|
getHolder().setFormat(PixelFormat.RGBA_8888);
|
||||||
|
|
||||||
setId(id);
|
m_windowId = id;
|
||||||
m_gestureDetector =
|
m_gestureDetector =
|
||||||
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||||
public void onLongPress(MotionEvent event) {
|
public void onLongPress(MotionEvent event) {
|
||||||
QtInputDelegate.longPress(getId(), (int) event.getX(), (int) event.getY());
|
QtInputDelegate.longPress(m_windowId, (int) event.getX(), (int) event.getY());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_gestureDetector.setIsLongpressEnabled(true);
|
m_gestureDetector.setIsLongpressEnabled(true);
|
||||||
@ -49,14 +59,15 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
{
|
{
|
||||||
if (width < 1 || height < 1)
|
if (width < 1 || height < 1)
|
||||||
return;
|
return;
|
||||||
|
if (m_surfaceCallback != null)
|
||||||
QtNative.setSurface(getId(), holder.getSurface());
|
m_surfaceCallback.onSurfaceChanged(holder.getSurface());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void surfaceDestroyed(SurfaceHolder holder)
|
public void surfaceDestroyed(SurfaceHolder holder)
|
||||||
{
|
{
|
||||||
QtNative.setSurface(getId(), null);
|
if (m_surfaceCallback != null)
|
||||||
|
m_surfaceCallback.onSurfaceChanged(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -67,7 +78,7 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
// In case when Surface is moved, we should also add this move to event position
|
// In case when Surface is moved, we should also add this move to event position
|
||||||
event.setLocation(event.getX() + getX(), event.getY() + getY());
|
event.setLocation(event.getX() + getX(), event.getY() + getY());
|
||||||
|
|
||||||
QtInputDelegate.sendTouchEvent(event, getId());
|
QtInputDelegate.sendTouchEvent(event, m_windowId);
|
||||||
m_gestureDetector.onTouchEvent(event);
|
m_gestureDetector.onTouchEvent(event);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -75,13 +86,13 @@ class QtSurface extends SurfaceView implements SurfaceHolder.Callback
|
|||||||
@Override
|
@Override
|
||||||
public boolean onTrackballEvent(MotionEvent event)
|
public boolean onTrackballEvent(MotionEvent event)
|
||||||
{
|
{
|
||||||
QtInputDelegate.sendTrackballEvent(event, getId());
|
QtInputDelegate.sendTrackballEvent(event, m_windowId);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onGenericMotionEvent(MotionEvent event)
|
public boolean onGenericMotionEvent(MotionEvent event)
|
||||||
{
|
{
|
||||||
return QtInputDelegate.sendGenericMotionEvent(event, getId());
|
return QtInputDelegate.sendGenericMotionEvent(event, m_windowId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
114
src/android/jar/src/org/qtproject/qt/android/QtWindow.java
Normal file
114
src/android/jar/src/org/qtproject/qt/android/QtWindow.java
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// 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.content.Context;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class QtWindow extends QtLayout implements QtSurface.SurfaceChangedCallback {
|
||||||
|
private final static String TAG = "QtWindow";
|
||||||
|
|
||||||
|
private QtSurface m_surface;
|
||||||
|
private View m_nativeView;
|
||||||
|
private Handler m_androidHandler;
|
||||||
|
|
||||||
|
private static native void setSurface(int windowId, Surface surface);
|
||||||
|
|
||||||
|
public QtWindow(Context context)
|
||||||
|
{
|
||||||
|
super(context);
|
||||||
|
setId(View.generateViewId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceChanged(Surface surface)
|
||||||
|
{
|
||||||
|
setSurface(getId(), surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createSurface(final boolean onTop,
|
||||||
|
final int x, final int y, final int w, final int h,
|
||||||
|
final int imageDepth)
|
||||||
|
{
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (m_surface != null)
|
||||||
|
removeView(m_surface);
|
||||||
|
|
||||||
|
QtSurface surface = new QtSurface(getContext(),
|
||||||
|
QtWindow.this, QtWindow.this.getId(),
|
||||||
|
onTop, imageDepth);
|
||||||
|
surface.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
||||||
|
|
||||||
|
addView(surface, 0);
|
||||||
|
m_surface = surface;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroySurface()
|
||||||
|
{
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (m_surface != null) {
|
||||||
|
removeView(m_surface);
|
||||||
|
m_surface = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSurfaceGeometry(final int x, final int y, final int w, final int h)
|
||||||
|
{
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
QtLayout.LayoutParams lp = new QtLayout.LayoutParams(w, h, x, y);
|
||||||
|
if (m_surface != null)
|
||||||
|
m_surface.setLayoutParams(lp);
|
||||||
|
else if (m_nativeView != null)
|
||||||
|
m_nativeView.setLayoutParams(lp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNativeView(final View view,
|
||||||
|
final int x, final int y, final int w, final int h)
|
||||||
|
{
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (m_nativeView != null)
|
||||||
|
removeView(m_nativeView);
|
||||||
|
|
||||||
|
m_nativeView = view;
|
||||||
|
m_nativeView.setLayoutParams(new QtLayout.LayoutParams(w, h, x, y));
|
||||||
|
|
||||||
|
addView(m_nativeView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNativeView()
|
||||||
|
{
|
||||||
|
QtNative.runAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (m_nativeView != null) {
|
||||||
|
removeView(m_nativeView);
|
||||||
|
m_nativeView = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -70,10 +70,6 @@ static void *m_mainLibraryHnd = nullptr;
|
|||||||
static QList<QByteArray> m_applicationParams;
|
static QList<QByteArray> m_applicationParams;
|
||||||
static sem_t m_exitSemaphore, m_terminateSemaphore;
|
static sem_t m_exitSemaphore, m_terminateSemaphore;
|
||||||
|
|
||||||
QHash<int, QAndroidPlatformWindow *> m_surfaces;
|
|
||||||
|
|
||||||
Q_CONSTINIT static QBasicMutex m_surfacesMutex;
|
|
||||||
|
|
||||||
|
|
||||||
static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr;
|
static QAndroidPlatformIntegration *m_androidPlatformIntegration = nullptr;
|
||||||
|
|
||||||
@ -319,56 +315,6 @@ namespace QtAndroid
|
|||||||
return manufacturer + u' ' + model;
|
return manufacturer + u' ' + model;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint generateViewId()
|
|
||||||
{
|
|
||||||
return QJniObject::callStaticMethod<jint>("android/view/View", "generateViewId", "()I");
|
|
||||||
}
|
|
||||||
|
|
||||||
int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth)
|
|
||||||
{
|
|
||||||
QJniEnvironment env;
|
|
||||||
if (!env.jniEnv())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
m_surfacesMutex.lock();
|
|
||||||
jint surfaceId = generateViewId();
|
|
||||||
m_surfaces[surfaceId] = window;
|
|
||||||
m_surfacesMutex.unlock();
|
|
||||||
|
|
||||||
jint x = 0, y = 0, w = -1, h = -1;
|
|
||||||
if (!geometry.isNull()) {
|
|
||||||
x = geometry.x();
|
|
||||||
y = geometry.y();
|
|
||||||
w = std::max(geometry.width(), 1);
|
|
||||||
h = std::max(geometry.height(), 1);
|
|
||||||
}
|
|
||||||
qtActivityDelegate().callMethod<void>("createSurface", surfaceId, jboolean(onTop),
|
|
||||||
x, y, w, h, imageDepth);
|
|
||||||
return surfaceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
int insertNativeView(QtJniTypes::View view, const QRect &geometry)
|
|
||||||
{
|
|
||||||
m_surfacesMutex.lock();
|
|
||||||
jint surfaceId = generateViewId();
|
|
||||||
m_surfaces[surfaceId] = nullptr; // dummy
|
|
||||||
m_surfacesMutex.unlock();
|
|
||||||
|
|
||||||
jint x = 0, y = 0, w = -1, h = -1;
|
|
||||||
if (!geometry.isNull())
|
|
||||||
geometry.getRect(&x, &y, &w, &h);
|
|
||||||
|
|
||||||
qtActivityDelegate().callMethod<void>("insertNativeView",
|
|
||||||
surfaceId,
|
|
||||||
view,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
qMax(w, 1),
|
|
||||||
qMax(h, 1));
|
|
||||||
|
|
||||||
return surfaceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setViewVisibility(jobject view, bool visible)
|
void setViewVisibility(jobject view, bool visible)
|
||||||
{
|
{
|
||||||
QJniObject::callStaticMethod<void>(m_applicationClass,
|
QJniObject::callStaticMethod<void>(m_applicationClass,
|
||||||
@ -378,56 +324,6 @@ namespace QtAndroid
|
|||||||
visible);
|
visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSurfaceGeometry(int surfaceId, const QRect &geometry)
|
|
||||||
{
|
|
||||||
if (surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QJniEnvironment env;
|
|
||||||
if (!env.jniEnv())
|
|
||||||
return;
|
|
||||||
jint x = 0, y = 0, w = -1, h = -1;
|
|
||||||
if (!geometry.isNull()) {
|
|
||||||
x = geometry.x();
|
|
||||||
y = geometry.y();
|
|
||||||
w = geometry.width();
|
|
||||||
h = geometry.height();
|
|
||||||
}
|
|
||||||
qtActivityDelegate().callMethod<void>("setSurfaceGeometry", surfaceId, x, y, w, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void destroySurface(int surfaceId)
|
|
||||||
{
|
|
||||||
if (surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
{
|
|
||||||
QMutexLocker lock(&m_surfacesMutex);
|
|
||||||
const auto &it = m_surfaces.find(surfaceId);
|
|
||||||
if (it != m_surfaces.end())
|
|
||||||
m_surfaces.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
qtActivityDelegate().callMethod<void>("destroySurface", surfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bringChildToFront(int surfaceId)
|
|
||||||
{
|
|
||||||
if (surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qtActivityDelegate().callMethod<void>("bringChildToFront", surfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bringChildToBack(int surfaceId)
|
|
||||||
{
|
|
||||||
if (surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
qtActivityDelegate().callMethod<void>("bringChildToBack", surfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool blockEventLoopsWhenSuspended()
|
bool blockEventLoopsWhenSuspended()
|
||||||
{
|
{
|
||||||
static bool block = qEnvironmentVariableIntValue("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED");
|
static bool block = qEnvironmentVariableIntValue("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED");
|
||||||
@ -595,21 +491,6 @@ static void terminateQt(JNIEnv *env, jclass /*clazz*/)
|
|||||||
sem_post(&m_exitSemaphore);
|
sem_post(&m_exitSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setSurface(JNIEnv *env, jobject thiz, jint id, jobject jSurface)
|
|
||||||
{
|
|
||||||
Q_UNUSED(env);
|
|
||||||
Q_UNUSED(thiz);
|
|
||||||
|
|
||||||
QMutexLocker lock(&m_surfacesMutex);
|
|
||||||
const auto &it = m_surfaces.find(id);
|
|
||||||
if (it == m_surfaces.end())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto surfaceClient = it.value();
|
|
||||||
if (surfaceClient)
|
|
||||||
surfaceClient->onSurfaceChanged(jSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWidthPixels,
|
static void setDisplayMetrics(JNIEnv * /*env*/, jclass /*clazz*/, jint screenWidthPixels,
|
||||||
jint screenHeightPixels, jint availableLeftPixels,
|
jint screenHeightPixels, jint availableLeftPixels,
|
||||||
jint availableTopPixels, jint availableWidthPixels,
|
jint availableTopPixels, jint availableWidthPixels,
|
||||||
@ -802,7 +683,6 @@ static JNINativeMethod methods[] = {
|
|||||||
{ "quitQtCoreApplication", "()V", (void *)quitQtCoreApplication },
|
{ "quitQtCoreApplication", "()V", (void *)quitQtCoreApplication },
|
||||||
{ "terminateQt", "()V", (void *)terminateQt },
|
{ "terminateQt", "()V", (void *)terminateQt },
|
||||||
{ "waitForServiceSetup", "()V", (void *)waitForServiceSetup },
|
{ "waitForServiceSetup", "()V", (void *)waitForServiceSetup },
|
||||||
{ "setSurface", "(ILjava/lang/Object;)V", (void *)setSurface },
|
|
||||||
{ "updateWindow", "()V", (void *)updateWindow },
|
{ "updateWindow", "()V", (void *)updateWindow },
|
||||||
{ "updateApplicationState", "(I)V", (void *)updateApplicationState },
|
{ "updateApplicationState", "(I)V", (void *)updateApplicationState },
|
||||||
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
|
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
|
||||||
@ -948,7 +828,8 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/)
|
|||||||
|| !QtAndroidMenu::registerNatives(env)
|
|| !QtAndroidMenu::registerNatives(env)
|
||||||
|| !QtAndroidAccessibility::registerNatives(env)
|
|| !QtAndroidAccessibility::registerNatives(env)
|
||||||
|| !QtAndroidDialogHelpers::registerNatives(env)
|
|| !QtAndroidDialogHelpers::registerNatives(env)
|
||||||
|| !QAndroidPlatformClipboard::registerNatives(env)) {
|
|| !QAndroidPlatformClipboard::registerNatives(env)
|
||||||
|
|| !QAndroidPlatformWindow::registerNatives(env)) {
|
||||||
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
__android_log_print(ANDROID_LOG_FATAL, "Qt", "registerNatives failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ class QBasicMutex;
|
|||||||
|
|
||||||
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
|
Q_DECLARE_JNI_CLASS(QtActivityDelegate, "org/qtproject/qt/android/QtActivityDelegate")
|
||||||
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
|
Q_DECLARE_JNI_CLASS(QtInputDelegate, "org/qtproject/qt/android/QtInputDelegate")
|
||||||
Q_DECLARE_JNI_CLASS(View, "android/view/View");
|
|
||||||
|
|
||||||
namespace QtAndroid
|
namespace QtAndroid
|
||||||
{
|
{
|
||||||
@ -36,14 +35,7 @@ namespace QtAndroid
|
|||||||
QAndroidPlatformIntegration *androidPlatformIntegration();
|
QAndroidPlatformIntegration *androidPlatformIntegration();
|
||||||
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
void setAndroidPlatformIntegration(QAndroidPlatformIntegration *androidPlatformIntegration);
|
||||||
void setQtThread(QThread *thread);
|
void setQtThread(QThread *thread);
|
||||||
|
|
||||||
int createSurface(QAndroidPlatformWindow *window, const QRect &geometry, bool onTop, int imageDepth);
|
|
||||||
int insertNativeView(QtJniTypes::View view, const QRect &geometry);
|
|
||||||
void setViewVisibility(jobject view, bool visible);
|
void setViewVisibility(jobject view, bool visible);
|
||||||
void setSurfaceGeometry(int surfaceId, const QRect &geometry);
|
|
||||||
void destroySurface(int surfaceId);
|
|
||||||
void bringChildToFront(int surfaceId);
|
|
||||||
void bringChildToBack(int surfaceId);
|
|
||||||
|
|
||||||
QWindow *topLevelWindowAt(const QPoint &globalPos);
|
QWindow *topLevelWindowAt(const QPoint &globalPos);
|
||||||
int availableWidthPixels();
|
int availableWidthPixels();
|
||||||
|
@ -6,12 +6,12 @@
|
|||||||
#include <QtCore/qvariant.h>
|
#include <QtCore/qvariant.h>
|
||||||
#include <qpa/qwindowsysteminterface.h>
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
#include <QtCore/private/qjnihelpers_p.h>
|
#include <QtCore/private/qjnihelpers_p.h>
|
||||||
|
#include <QtCore/qjnitypes.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle)
|
QAndroidPlatformForeignWindow::QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle)
|
||||||
: QAndroidPlatformWindow(window),
|
: QAndroidPlatformWindow(window), m_view(nullptr), m_nativeViewInserted(false)
|
||||||
m_surfaceId(-1)
|
|
||||||
{
|
{
|
||||||
m_view = reinterpret_cast<jobject>(nativeHandle);
|
m_view = reinterpret_cast<jobject>(nativeHandle);
|
||||||
if (m_view.isValid())
|
if (m_view.isValid())
|
||||||
@ -22,34 +22,17 @@ QAndroidPlatformForeignWindow::~QAndroidPlatformForeignWindow()
|
|||||||
{
|
{
|
||||||
if (m_view.isValid())
|
if (m_view.isValid())
|
||||||
QtAndroid::setViewVisibility(m_view.object(), false);
|
QtAndroid::setViewVisibility(m_view.object(), false);
|
||||||
if (m_surfaceId != -1)
|
|
||||||
QtAndroid::destroySurface(m_surfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QAndroidPlatformForeignWindow::lower()
|
m_nativeQtWindow.callMethod<void>("removeNativeView");
|
||||||
{
|
|
||||||
if (m_surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QAndroidPlatformWindow::lower();
|
|
||||||
QtAndroid::bringChildToBack(m_surfaceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QAndroidPlatformForeignWindow::raise()
|
|
||||||
{
|
|
||||||
if (m_surfaceId == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QAndroidPlatformWindow::raise();
|
|
||||||
QtAndroid::bringChildToFront(m_surfaceId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
|
void QAndroidPlatformForeignWindow::setGeometry(const QRect &rect)
|
||||||
{
|
{
|
||||||
QAndroidPlatformWindow::setGeometry(rect);
|
QAndroidPlatformWindow::setGeometry(rect);
|
||||||
|
|
||||||
if (m_surfaceId != -1)
|
if (m_nativeViewInserted)
|
||||||
QtAndroid::setSurfaceGeometry(m_surfaceId, rect);
|
setSurfaceGeometry(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformForeignWindow::setVisible(bool visible)
|
void QAndroidPlatformForeignWindow::setVisible(bool visible)
|
||||||
@ -60,22 +43,21 @@ void QAndroidPlatformForeignWindow::setVisible(bool visible)
|
|||||||
QtAndroid::setViewVisibility(m_view.object(), visible);
|
QtAndroid::setViewVisibility(m_view.object(), visible);
|
||||||
|
|
||||||
QAndroidPlatformWindow::setVisible(visible);
|
QAndroidPlatformWindow::setVisible(visible);
|
||||||
if (!visible && m_surfaceId != -1) {
|
if (!visible && m_nativeViewInserted) {
|
||||||
QtAndroid::destroySurface(m_surfaceId);
|
m_nativeQtWindow.callMethod<void>("removeNativeView");
|
||||||
m_surfaceId = -1;
|
m_nativeViewInserted = false;
|
||||||
} else if (m_surfaceId == -1) {
|
} else if (!m_nativeViewInserted) {
|
||||||
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
addViewToWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
|
void QAndroidPlatformForeignWindow::applicationStateChanged(Qt::ApplicationState state)
|
||||||
{
|
{
|
||||||
if (state <= Qt::ApplicationHidden
|
if (state <= Qt::ApplicationHidden && m_nativeViewInserted) {
|
||||||
&& m_surfaceId != -1) {
|
m_nativeQtWindow.callMethod<void>("removeNativeView");
|
||||||
QtAndroid::destroySurface(m_surfaceId);
|
m_nativeViewInserted = false;
|
||||||
m_surfaceId = -1;
|
} else if (m_view.isValid() && !m_nativeViewInserted){
|
||||||
} else if (m_view.isValid() && m_surfaceId == -1){
|
addViewToWindow();
|
||||||
m_surfaceId = QtAndroid::insertNativeView(m_view.object(), geometry());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QAndroidPlatformWindow::applicationStateChanged(state);
|
QAndroidPlatformWindow::applicationStateChanged(state);
|
||||||
@ -86,4 +68,14 @@ void QAndroidPlatformForeignWindow::setParent(const QPlatformWindow *window)
|
|||||||
Q_UNUSED(window);
|
Q_UNUSED(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformForeignWindow::addViewToWindow()
|
||||||
|
{
|
||||||
|
jint x = 0, y = 0, w = -1, h = -1;
|
||||||
|
if (!geometry().isNull())
|
||||||
|
geometry().getRect(&x, &y, &w, &h);
|
||||||
|
|
||||||
|
m_nativeQtWindow.callMethod<void>("setNativeView", m_view, x, y, qMax(w, 1), qMax(h, 1));
|
||||||
|
m_nativeViewInserted = true;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
Q_DECLARE_JNI_CLASS(View, "android/view/View")
|
||||||
|
|
||||||
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
|
class QAndroidPlatformForeignWindow : public QAndroidPlatformWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle);
|
explicit QAndroidPlatformForeignWindow(QWindow *window, WId nativeHandle);
|
||||||
~QAndroidPlatformForeignWindow();
|
~QAndroidPlatformForeignWindow();
|
||||||
void lower() override;
|
|
||||||
void raise() override;
|
|
||||||
void setGeometry(const QRect &rect) override;
|
void setGeometry(const QRect &rect) override;
|
||||||
void setVisible(bool visible) override;
|
void setVisible(bool visible) override;
|
||||||
void applicationStateChanged(Qt::ApplicationState state) override;
|
void applicationStateChanged(Qt::ApplicationState state) override;
|
||||||
@ -24,8 +24,10 @@ public:
|
|||||||
bool isForeignWindow() const override { return true; }
|
bool isForeignWindow() const override { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_surfaceId;
|
void addViewToWindow();
|
||||||
QJniObject m_view;
|
|
||||||
|
QtJniTypes::View m_view;
|
||||||
|
bool m_nativeViewInserted;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -58,12 +58,14 @@ void QAndroidPlatformOpenGLWindow::setGeometry(const QRect &rect)
|
|||||||
|
|
||||||
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
||||||
{
|
{
|
||||||
if (QAndroidEventDispatcherStopper::stopped() || QGuiApplication::applicationState() == Qt::ApplicationSuspended)
|
if (QAndroidEventDispatcherStopper::stopped() ||
|
||||||
|
QGuiApplication::applicationState() == Qt::ApplicationSuspended || !window()->isTopLevel()) {
|
||||||
return m_eglSurface;
|
return m_eglSurface;
|
||||||
|
}
|
||||||
|
|
||||||
QMutexLocker lock(&m_surfaceMutex);
|
QMutexLocker lock(&m_surfaceMutex);
|
||||||
|
|
||||||
if (m_nativeSurfaceId == -1) {
|
if (!m_surfaceCreated) {
|
||||||
AndroidDeadlockProtector protector;
|
AndroidDeadlockProtector protector;
|
||||||
if (!protector.acquire())
|
if (!protector.acquire())
|
||||||
return m_eglSurface;
|
return m_eglSurface;
|
||||||
@ -83,7 +85,7 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
|
|||||||
bool QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
|
bool QAndroidPlatformOpenGLWindow::checkNativeSurface(EGLConfig config)
|
||||||
{
|
{
|
||||||
QMutexLocker lock(&m_surfaceMutex);
|
QMutexLocker lock(&m_surfaceMutex);
|
||||||
if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
|
if (!m_surfaceCreated || !m_androidSurfaceObject.isValid())
|
||||||
return false; // makeCurrent is NOT needed.
|
return false; // makeCurrent is NOT needed.
|
||||||
|
|
||||||
createEgl(config);
|
createEgl(config);
|
||||||
|
@ -132,16 +132,16 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindow *QAndroidPlatformScreen::topWindow() const
|
QWindow *QAndroidPlatformScreen::topVisibleWindow() const
|
||||||
{
|
{
|
||||||
for (QAndroidPlatformWindow *w : m_windowStack) {
|
for (QAndroidPlatformWindow *w : m_windowStack) {
|
||||||
if (w->window()->type() == Qt::Window ||
|
Qt::WindowType type = w->window()->type();
|
||||||
w->window()->type() == Qt::Popup ||
|
if (w->window()->isVisible() &&
|
||||||
w->window()->type() == Qt::Dialog) {
|
(type == Qt::Window || type == Qt::Popup || type == Qt::Dialog)) {
|
||||||
return w->window();
|
return w->window();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
|
QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
|
||||||
@ -162,37 +162,34 @@ void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_windowStack.prepend(window);
|
m_windowStack.prepend(window);
|
||||||
|
QtAndroid::qtActivityDelegate().callMethod<void>("addTopLevelWindow", window->nativeWindow());
|
||||||
|
|
||||||
QWindow *w = topWindow();
|
if (window->window()->isVisible())
|
||||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
topVisibleWindowChanged();
|
||||||
topWindowChanged(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::removeWindow(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
if (window->parent() && window->isRaster())
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_windowStack.removeOne(window);
|
m_windowStack.removeOne(window);
|
||||||
|
|
||||||
if (m_windowStack.contains(window))
|
if (m_windowStack.contains(window))
|
||||||
qWarning() << "Failed to remove window";
|
qWarning() << "Failed to remove window";
|
||||||
|
|
||||||
QWindow *w = topWindow();
|
QtAndroid::qtActivityDelegate().callMethod<void>("removeTopLevelWindow", window->nativeViewId());
|
||||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
|
||||||
topWindowChanged(w);
|
topVisibleWindowChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::raise(QAndroidPlatformWindow *window)
|
||||||
{
|
{
|
||||||
int index = m_windowStack.indexOf(window);
|
int index = m_windowStack.indexOf(window);
|
||||||
if (index <= 0)
|
if (index < 0)
|
||||||
return;
|
return;
|
||||||
m_windowStack.move(index, 0);
|
if (index > 0) {
|
||||||
|
m_windowStack.move(index, 0);
|
||||||
QWindow *w = topWindow();
|
QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToFront", window->nativeViewId());
|
||||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
}
|
||||||
topWindowChanged(w);
|
topVisibleWindowChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
||||||
@ -201,10 +198,9 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
|
|||||||
if (index == -1 || index == (m_windowStack.size() - 1))
|
if (index == -1 || index == (m_windowStack.size() - 1))
|
||||||
return;
|
return;
|
||||||
m_windowStack.move(index, m_windowStack.size() - 1);
|
m_windowStack.move(index, m_windowStack.size() - 1);
|
||||||
|
QtAndroid::qtActivityDelegate().callMethod<void>("bringChildToBack", window->nativeViewId());
|
||||||
|
|
||||||
QWindow *w = topWindow();
|
topVisibleWindowChanged();
|
||||||
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
|
||||||
topWindowChanged(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
|
void QAndroidPlatformScreen::setPhysicalSize(const QSize &size)
|
||||||
@ -284,13 +280,14 @@ void QAndroidPlatformScreen::applicationStateChanged(Qt::ApplicationState state)
|
|||||||
w->applicationStateChanged(state);
|
w->applicationStateChanged(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformScreen::topWindowChanged(QWindow *w)
|
void QAndroidPlatformScreen::topVisibleWindowChanged()
|
||||||
{
|
{
|
||||||
|
QWindow *w = topVisibleWindow();
|
||||||
|
QWindowSystemInterface::handleFocusWindowChanged(w, Qt::ActiveWindowFocusReason);
|
||||||
QtAndroidMenu::setActiveTopLevelWindow(w);
|
QtAndroidMenu::setActiveTopLevelWindow(w);
|
||||||
|
if (w && w->handle()) {
|
||||||
if (w != 0) {
|
|
||||||
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
|
QAndroidPlatformWindow *platformWindow = static_cast<QAndroidPlatformWindow *>(w->handle());
|
||||||
if (platformWindow != 0)
|
if (platformWindow)
|
||||||
platformWindow->updateSystemUiVisibility();
|
platformWindow->updateSystemUiVisibility();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ public:
|
|||||||
int currentMode() const override { return m_currentMode; }
|
int currentMode() const override { return m_currentMode; }
|
||||||
int preferredMode() const override { return m_currentMode; }
|
int preferredMode() const override { return m_currentMode; }
|
||||||
qreal refreshRate() const override { return m_refreshRate; }
|
qreal refreshRate() const override { return m_refreshRate; }
|
||||||
inline QWindow *topWindow() const;
|
inline QWindow *topVisibleWindow() const;
|
||||||
QWindow *topLevelAt(const QPoint & p) const override;
|
QWindow *topLevelAt(const QPoint & p) const override;
|
||||||
|
|
||||||
void addWindow(QAndroidPlatformWindow *window);
|
void addWindow(QAndroidPlatformWindow *window);
|
||||||
@ -45,7 +45,7 @@ public:
|
|||||||
void raise(QAndroidPlatformWindow *window);
|
void raise(QAndroidPlatformWindow *window);
|
||||||
void lower(QAndroidPlatformWindow *window);
|
void lower(QAndroidPlatformWindow *window);
|
||||||
|
|
||||||
void topWindowChanged(QWindow *w);
|
void topVisibleWindowChanged();
|
||||||
int displayId() const override;
|
int displayId() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -60,7 +60,6 @@ public slots:
|
|||||||
protected:
|
protected:
|
||||||
typedef QList<QAndroidPlatformWindow *> WindowStackType;
|
typedef QList<QAndroidPlatformWindow *> WindowStackType;
|
||||||
WindowStackType m_windowStack;
|
WindowStackType m_windowStack;
|
||||||
|
|
||||||
QRect m_availableGeometry;
|
QRect m_availableGeometry;
|
||||||
int m_depth;
|
int m_depth;
|
||||||
QImage::Format m_format;
|
QImage::Format m_format;
|
||||||
|
@ -94,7 +94,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
|
|||||||
clearSurface();
|
clearSurface();
|
||||||
|
|
||||||
QMutexLocker lock(&m_surfaceMutex);
|
QMutexLocker lock(&m_surfaceMutex);
|
||||||
if (m_nativeSurfaceId == -1) {
|
if (!m_surfaceCreated) {
|
||||||
AndroidDeadlockProtector protector;
|
AndroidDeadlockProtector protector;
|
||||||
if (!protector.acquire())
|
if (!protector.acquire())
|
||||||
return &m_vkSurface;
|
return &m_vkSurface;
|
||||||
@ -102,7 +102,7 @@ VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
|
|||||||
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
m_surfaceWaitCondition.wait(&m_surfaceMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
|
if (!m_surfaceCreated || !m_androidSurfaceObject.isValid())
|
||||||
return &m_vkSurface;
|
return &m_vkSurface;
|
||||||
|
|
||||||
QJniEnvironment env;
|
QJniEnvironment env;
|
||||||
|
@ -14,11 +14,15 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
|
||||||
|
|
||||||
Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
|
Q_CONSTINIT static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
|
||||||
|
|
||||||
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
|
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
|
||||||
: QPlatformWindow(window), m_androidSurfaceObject(nullptr)
|
: QPlatformWindow(window), m_nativeQtWindow(QNativeInterface::QAndroidApplication::context()),
|
||||||
|
m_androidSurfaceObject(nullptr)
|
||||||
{
|
{
|
||||||
|
m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
|
||||||
m_windowFlags = Qt::Widget;
|
m_windowFlags = Qt::Widget;
|
||||||
m_windowState = Qt::WindowNoState;
|
m_windowState = Qt::WindowNoState;
|
||||||
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
|
// the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
|
||||||
@ -44,8 +48,15 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
|
|||||||
if (requestedNativeGeometry != finalNativeGeometry)
|
if (requestedNativeGeometry != finalNativeGeometry)
|
||||||
setGeometry(finalNativeGeometry);
|
setGeometry(finalNativeGeometry);
|
||||||
}
|
}
|
||||||
|
platformScreen()->addWindow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QAndroidPlatformWindow::~QAndroidPlatformWindow()
|
||||||
|
{
|
||||||
|
platformScreen()->removeWindow(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void QAndroidPlatformWindow::lower()
|
void QAndroidPlatformWindow::lower()
|
||||||
{
|
{
|
||||||
platformScreen()->lower(this);
|
platformScreen()->lower(this);
|
||||||
@ -76,23 +87,19 @@ void QAndroidPlatformWindow::setGeometry(const QRect &rect)
|
|||||||
|
|
||||||
void QAndroidPlatformWindow::setVisible(bool visible)
|
void QAndroidPlatformWindow::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (visible)
|
|
||||||
updateSystemUiVisibility();
|
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
updateSystemUiVisibility();
|
||||||
if ((m_windowState & Qt::WindowFullScreen)
|
if ((m_windowState & Qt::WindowFullScreen)
|
||||||
|| ((m_windowState & Qt::WindowMaximized) && (window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint))) {
|
|| ((m_windowState & Qt::WindowMaximized) && (window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint))) {
|
||||||
setGeometry(platformScreen()->geometry());
|
setGeometry(platformScreen()->geometry());
|
||||||
} else if (m_windowState & Qt::WindowMaximized) {
|
} else if (m_windowState & Qt::WindowMaximized) {
|
||||||
setGeometry(platformScreen()->availableGeometry());
|
setGeometry(platformScreen()->availableGeometry());
|
||||||
}
|
}
|
||||||
|
requestActivateWindow();
|
||||||
|
} else if (window() == qGuiApp->focusWindow()) {
|
||||||
|
platformScreen()->topVisibleWindowChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visible)
|
|
||||||
platformScreen()->addWindow(this);
|
|
||||||
else
|
|
||||||
platformScreen()->removeWindow(this);
|
|
||||||
|
|
||||||
QRect availableGeometry = screen()->availableGeometry();
|
QRect availableGeometry = screen()->availableGeometry();
|
||||||
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
|
if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
|
||||||
QPlatformWindow::setVisible(visible);
|
QPlatformWindow::setVisible(visible);
|
||||||
@ -125,7 +132,14 @@ Qt::WindowFlags QAndroidPlatformWindow::windowFlags() const
|
|||||||
|
|
||||||
void QAndroidPlatformWindow::setParent(const QPlatformWindow *window)
|
void QAndroidPlatformWindow::setParent(const QPlatformWindow *window)
|
||||||
{
|
{
|
||||||
Q_UNUSED(window);
|
// even though we do not yet support child windows properly, any windows getting a parent
|
||||||
|
// should be removed from screen's window stack which is only for top level windows,
|
||||||
|
// and respectively any window becoming top level should go in there
|
||||||
|
if (window) {
|
||||||
|
platformScreen()->removeWindow(this);
|
||||||
|
} else {
|
||||||
|
platformScreen()->addWindow(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QAndroidPlatformScreen *QAndroidPlatformWindow::platformScreen() const
|
QAndroidPlatformScreen *QAndroidPlatformWindow::platformScreen() const
|
||||||
@ -140,7 +154,8 @@ void QAndroidPlatformWindow::propagateSizeHints()
|
|||||||
|
|
||||||
void QAndroidPlatformWindow::requestActivateWindow()
|
void QAndroidPlatformWindow::requestActivateWindow()
|
||||||
{
|
{
|
||||||
platformScreen()->topWindowChanged(window());
|
if (!blockedByModal())
|
||||||
|
raise();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformWindow::updateSystemUiVisibility()
|
void QAndroidPlatformWindow::updateSystemUiVisibility()
|
||||||
@ -176,25 +191,62 @@ void QAndroidPlatformWindow::applicationStateChanged(Qt::ApplicationState)
|
|||||||
|
|
||||||
void QAndroidPlatformWindow::createSurface()
|
void QAndroidPlatformWindow::createSurface()
|
||||||
{
|
{
|
||||||
|
const QRect rect = geometry();
|
||||||
|
jint x = 0, y = 0, w = -1, h = -1;
|
||||||
|
if (!rect.isNull()) {
|
||||||
|
x = rect.x();
|
||||||
|
y = rect.y();
|
||||||
|
w = std::max(rect.width(), 1);
|
||||||
|
h = std::max(rect.height(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
|
||||||
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
|
|
||||||
|
m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32);
|
||||||
|
m_surfaceCreated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformWindow::destroySurface()
|
void QAndroidPlatformWindow::destroySurface()
|
||||||
{
|
{
|
||||||
if (m_nativeSurfaceId != -1) {
|
if (m_surfaceCreated) {
|
||||||
QtAndroid::destroySurface(m_nativeSurfaceId);
|
m_nativeQtWindow.callMethod<void>("destroySurface");
|
||||||
m_nativeSurfaceId = -1;
|
m_surfaceCreated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &rect)
|
void QAndroidPlatformWindow::setSurfaceGeometry(const QRect &geometry)
|
||||||
{
|
{
|
||||||
if (m_nativeSurfaceId != -1)
|
if (!m_surfaceCreated)
|
||||||
QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
|
return;
|
||||||
|
|
||||||
|
jint x = 0;
|
||||||
|
jint y = 0;
|
||||||
|
jint w = -1;
|
||||||
|
jint h = -1;
|
||||||
|
if (!geometry.isNull()) {
|
||||||
|
x = geometry.x();
|
||||||
|
y = geometry.y();
|
||||||
|
w = geometry.width();
|
||||||
|
h = geometry.height();
|
||||||
|
}
|
||||||
|
m_nativeQtWindow.callMethod<void>("setSurfaceGeometry", x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformWindow::sendExpose()
|
void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
|
||||||
|
{
|
||||||
|
lockSurface();
|
||||||
|
m_androidSurfaceObject = surface;
|
||||||
|
if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into
|
||||||
|
m_surfaceWaitCondition.wakeOne();
|
||||||
|
unlockSurface();
|
||||||
|
|
||||||
|
if (m_androidSurfaceObject.isValid()) {
|
||||||
|
// repaint the window, when we have a valid surface
|
||||||
|
sendExpose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QAndroidPlatformWindow::sendExpose() const
|
||||||
{
|
{
|
||||||
QRect availableGeometry = screen()->availableGeometry();
|
QRect availableGeometry = screen()->availableGeometry();
|
||||||
if (!geometry().isNull() && !availableGeometry.isNull()) {
|
if (!geometry().isNull() && !availableGeometry.isNull()) {
|
||||||
@ -203,15 +255,41 @@ void QAndroidPlatformWindow::sendExpose()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
|
bool QAndroidPlatformWindow::blockedByModal() const
|
||||||
{
|
{
|
||||||
lockSurface();
|
QWindow *modalWindow = QGuiApplication::modalWindow();
|
||||||
m_androidSurfaceObject = surface;
|
return modalWindow && modalWindow != window();
|
||||||
if (m_androidSurfaceObject.isValid())
|
}
|
||||||
m_surfaceWaitCondition.wakeOne();
|
|
||||||
unlockSurface();
|
void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId,
|
||||||
if (m_androidSurfaceObject.isValid())
|
QtJniTypes::Surface surface)
|
||||||
sendExpose();
|
{
|
||||||
|
Q_UNUSED(env)
|
||||||
|
Q_UNUSED(object)
|
||||||
|
|
||||||
|
if (!qGuiApp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const QList<QWindow*> windows = qGuiApp->allWindows();
|
||||||
|
for (QWindow * window : windows) {
|
||||||
|
if (!window->handle())
|
||||||
|
continue;
|
||||||
|
QAndroidPlatformWindow *platformWindow =
|
||||||
|
static_cast<QAndroidPlatformWindow *>(window->handle());
|
||||||
|
if (platformWindow->nativeViewId() == windowId)
|
||||||
|
platformWindow->onSurfaceChanged(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QAndroidPlatformWindow::registerNatives(QJniEnvironment &env)
|
||||||
|
{
|
||||||
|
if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),
|
||||||
|
{Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow)})) {
|
||||||
|
qCCritical(lcQpaWindow) << "RegisterNatives failed for"
|
||||||
|
<< QtJniTypes::Traits<QtJniTypes::QtWindow>::className();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
|
||||||
|
Q_DECLARE_JNI_CLASS(QtWindow, "org/qtproject/qt/android/QtWindow")
|
||||||
Q_DECLARE_JNI_CLASS(Surface, "android/view/Surface")
|
Q_DECLARE_JNI_CLASS(Surface, "android/view/Surface")
|
||||||
|
|
||||||
class QAndroidPlatformScreen;
|
class QAndroidPlatformScreen;
|
||||||
@ -25,7 +27,7 @@ class QAndroidPlatformWindow: public QPlatformWindow
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit QAndroidPlatformWindow(QWindow *window);
|
explicit QAndroidPlatformWindow(QWindow *window);
|
||||||
|
~QAndroidPlatformWindow();
|
||||||
void lower() override;
|
void lower() override;
|
||||||
void raise() override;
|
void raise() override;
|
||||||
|
|
||||||
@ -49,9 +51,12 @@ public:
|
|||||||
void updateSystemUiVisibility();
|
void updateSystemUiVisibility();
|
||||||
inline bool isRaster() const { return m_isRaster; }
|
inline bool isRaster() const { return m_isRaster; }
|
||||||
bool isExposed() const override;
|
bool isExposed() const override;
|
||||||
|
QtJniTypes::QtWindow nativeWindow() const { return m_nativeQtWindow; }
|
||||||
|
|
||||||
virtual void applicationStateChanged(Qt::ApplicationState);
|
virtual void applicationStateChanged(Qt::ApplicationState);
|
||||||
|
int nativeViewId() const { return m_nativeViewId; }
|
||||||
|
|
||||||
|
static bool registerNatives(QJniEnvironment &env);
|
||||||
void onSurfaceChanged(QtJniTypes::Surface surface);
|
void onSurfaceChanged(QtJniTypes::Surface surface);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -60,20 +65,27 @@ protected:
|
|||||||
void unlockSurface() { m_surfaceMutex.unlock(); }
|
void unlockSurface() { m_surfaceMutex.unlock(); }
|
||||||
void createSurface();
|
void createSurface();
|
||||||
void destroySurface();
|
void destroySurface();
|
||||||
void setSurfaceGeometry(const QRect &rect);
|
void setSurfaceGeometry(const QRect &geometry);
|
||||||
void sendExpose();
|
void sendExpose() const;
|
||||||
|
bool blockedByModal() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
Qt::WindowFlags m_windowFlags;
|
Qt::WindowFlags m_windowFlags;
|
||||||
Qt::WindowStates m_windowState;
|
Qt::WindowStates m_windowState;
|
||||||
bool m_isRaster;
|
bool m_isRaster;
|
||||||
|
|
||||||
WId m_windowId;
|
WId m_windowId;
|
||||||
|
|
||||||
|
QtJniTypes::QtWindow m_nativeQtWindow;
|
||||||
// The Android Surface, accessed from multiple threads, guarded by m_surfaceMutex
|
// The Android Surface, accessed from multiple threads, guarded by m_surfaceMutex
|
||||||
QtJniTypes::Surface m_androidSurfaceObject;
|
QtJniTypes::Surface m_androidSurfaceObject;
|
||||||
QWaitCondition m_surfaceWaitCondition;
|
QWaitCondition m_surfaceWaitCondition;
|
||||||
int m_nativeSurfaceId = -1;
|
int m_nativeViewId = -1;
|
||||||
|
bool m_surfaceCreated = false;
|
||||||
QMutex m_surfaceMutex;
|
QMutex m_surfaceMutex;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void setSurface(JNIEnv *env, jobject obj, jint windowId, QtJniTypes::Surface surface);
|
||||||
|
Q_DECLARE_JNI_NATIVE_METHOD_IN_CURRENT_SCOPE(setSurface)
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user