summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/iaccessible2/REUSE.toml2
-rw-r--r--src/3rdparty/libpsl/REUSE.toml2
-rw-r--r--src/android/jar/CMakeLists.txt1
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java18
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java21
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java20
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java271
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java5
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtLoader.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtNative.java5
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindowInsetsController.java358
-rw-r--r--src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java1
-rw-r--r--src/corelib/global/qnumeric.h49
-rw-r--r--src/corelib/kernel/qwinregistry.cpp1
-rw-r--r--src/corelib/kernel/qwinregistry_p.h6
-rw-r--r--src/corelib/serialization/qcborarray.cpp1
-rw-r--r--src/corelib/serialization/qcborcommon_p.h1
-rw-r--r--src/corelib/serialization/qcbormap.cpp1
-rw-r--r--src/corelib/serialization/qcborstream.h1
-rw-r--r--src/corelib/serialization/qjsonparser_p.h1
-rw-r--r--src/corelib/serialization/qjsonwriter_p.h1
-rw-r--r--src/gui/accessible/linux/qspiaccessiblebridge.cpp6
-rw-r--r--src/gui/accessible/qaccessible.cpp1
-rw-r--r--src/gui/accessible/qaccessible_base.h1
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp4
-rw-r--r--src/gui/image/qiconloader.cpp13
-rw-r--r--src/gui/kernel/qplatformwindow_p.h12
-rw-r--r--src/gui/painting/qpainter.cpp33
-rw-r--r--src/gui/painting/qpainter_p.h3
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp3
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp73
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp3
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp6
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp16
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm8
-rw-r--r--src/plugins/platforms/ios/quiaccessibilityelement.mm5
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp36
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.h1
-rw-r--r--src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp195
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow.cpp24
-rw-r--r--src/plugins/platforms/wayland/qwaylandwindow_p.h10
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp5
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp1
-rw-r--r--src/tools/moc/moc.cpp6
-rw-r--r--src/tools/moc/moc.h1
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp3
-rw-r--r--src/widgets/kernel/qapplication.cpp29
-rw-r--r--src/widgets/kernel/qtooltip.cpp13
-rw-r--r--src/widgets/kernel/qwidget.cpp19
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp4
-rw-r--r--src/widgets/util/qcompleter.cpp15
-rw-r--r--src/widgets/widgets/qcombobox.cpp14
-rw-r--r--src/widgets/widgets/qmenu.cpp19
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp21
-rw-r--r--tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp6
-rw-r--r--tests/auto/tools/moc/allmocs_baseline_in.json9
-rw-r--r--tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp25
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp2
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp3
-rw-r--r--tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp74
-rw-r--r--util/unicode/main.cpp2
-rw-r--r--util/xkbdatagen/main.cpp3
63 files changed, 974 insertions, 523 deletions
diff --git a/src/3rdparty/iaccessible2/REUSE.toml b/src/3rdparty/iaccessible2/REUSE.toml
index f4d00d7f4f1..24da6e46400 100644
--- a/src/3rdparty/iaccessible2/REUSE.toml
+++ b/src/3rdparty/iaccessible2/REUSE.toml
@@ -5,5 +5,5 @@ path = ["**"]
precedence = "closest"
SPDX-FileCopyrightText = ["Copyright (c) 2000, 2006 Sun Microsystems, Inc.",
"Copyright (c) 2006 IBM Corporation",
- "Copyright (c) 2007, 2010, 2012, 2013 Linux Foundation\nIAccessible2 is a trademark of the Linux Foundation. The IAccessible2 mark may be used in accordance with the Linux Foundation Trademark Policy to indicate compliance with the IAccessible2 specification."]
+ "Copyright (c) 2007, 2010, 2012, 2013 Linux Foundation IAccessible2 is a trademark of the Linux Foundation. The IAccessible2 mark may be used in accordance with the Linux Foundation Trademark Policy to indicate compliance with the IAccessible2 specification."]
SPDX-License-Identifier = "BSD-3-Clause"
diff --git a/src/3rdparty/libpsl/REUSE.toml b/src/3rdparty/libpsl/REUSE.toml
index 6c911a98dfe..7b63d4ed725 100644
--- a/src/3rdparty/libpsl/REUSE.toml
+++ b/src/3rdparty/libpsl/REUSE.toml
@@ -10,6 +10,6 @@ SPDX-License-Identifier = "BSD-3-Clause"
[[annotations]]
path = ["psl_data.cpp"]
precedence = "closest"
-SPDX-FileCopyrightText = ["The list was originally provided by Jo Hermans <[email protected]>.\nIt is now maintained on github (https://github.com/publicsuffix/list)."]
+SPDX-FileCopyrightText = ["The list was originally provided by Jo Hermans <[email protected]>.It is now maintained on github (https://github.com/publicsuffix/list)."]
SPDX-License-Identifier = "MPL-2.0"
diff --git a/src/android/jar/CMakeLists.txt b/src/android/jar/CMakeLists.txt
index b073dbea0ea..e0a675ab463 100644
--- a/src/android/jar/CMakeLists.txt
+++ b/src/android/jar/CMakeLists.txt
@@ -53,6 +53,7 @@ set(java_sources
src/org/qtproject/qt/android/BackgroundActionsTracker.java
src/org/qtproject/qt/android/QtApkFileEngine.java
src/org/qtproject/qt/android/QtContentFileEngine.java
+ src/org/qtproject/qt/android/QtWindowInsetsController.java
)
qt_internal_add_jar(Qt${QtBase_VERSION_MAJOR}Android
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
index aca9e3d3c11..78763e65905 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityBase.java
@@ -102,9 +102,11 @@ public class QtActivityBase extends Activity
requestWindowFeature(Window.FEATURE_ACTION_BAR);
if (!m_isCustomThemeSet) {
- setTheme(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ?
- android.R.style.Theme_DeviceDefault_DayNight :
- android.R.style.Theme_Holo_Light);
+ @SuppressWarnings("deprecation")
+ int themeId = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
+ ? android.R.style.Theme_DeviceDefault_DayNight
+ : android.R.style.Theme_Holo_Light;
+ setTheme(themeId);
}
if (QtNative.getStateDetails().isStarted) {
@@ -168,7 +170,7 @@ public class QtActivityBase extends Activity
m_delegate.displayManager().registerDisplayListener();
QtWindow.updateWindows();
// Suspending the app clears the immersive mode, so we need to set it again.
- m_delegate.displayManager().reinstateFullScreen();
+ QtWindowInsetsController.restoreFullScreenVisibility(this);
}
}
@@ -311,9 +313,7 @@ public class QtActivityBase extends Activity
return;
QtNative.setStarted(savedInstanceState.getBoolean("Started"));
- boolean isFullScreen = savedInstanceState.getBoolean("isFullScreen");
- boolean expandedToCutout = savedInstanceState.getBoolean("expandedToCutout");
- m_delegate.displayManager().setSystemUiVisibility(isFullScreen, expandedToCutout);
+ QtWindowInsetsController.restoreFullScreenVisibility(this);
// FIXME restore all surfaces
}
@@ -329,8 +329,6 @@ public class QtActivityBase extends Activity
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
- outState.putBoolean("isFullScreen", m_delegate.displayManager().isFullScreen());
- outState.putBoolean("expandedToCutout", m_delegate.displayManager().expandedToCutout());
outState.putBoolean("Started", QtNative.getStateDetails().isStarted);
}
@@ -339,7 +337,7 @@ public class QtActivityBase extends Activity
{
super.onWindowFocusChanged(hasFocus);
if (hasFocus)
- m_delegate.displayManager().reinstateFullScreen();
+ QtWindowInsetsController.restoreFullScreenVisibility(this);
}
@Override
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
index 118845efcec..aa2964c3ae9 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegate.java
@@ -86,21 +86,6 @@ class QtActivityDelegate extends QtActivityDelegateBase
}
@Override
- public void setSystemUiVisibility(boolean isFullScreen, boolean expandedToCutout)
- {
- if (m_layout == null)
- return;
-
- QtNative.runAction(() -> {
- if (m_layout != null) {
- m_displayManager.setSystemUiVisibility(isFullScreen, expandedToCutout);
- QtWindow.updateWindows();
- }
- });
- }
-
-
- @Override
final public void onAppStateDetailsChanged(QtNative.ApplicationStateDetails details) {
if (details.isStarted)
registerBackends();
@@ -138,9 +123,9 @@ class QtActivityDelegate extends QtActivityDelegateBase
int orientation = m_activity.getResources().getConfiguration().orientation;
setUpSplashScreen(orientation);
m_activity.registerForContextMenu(m_layout);
- m_activity.setContentView(m_layout,
- new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
+ ViewGroup.LayoutParams rootParams = new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+ m_activity.setContentView(m_layout, rootParams);
handleUiModeChange();
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
index 35f519ca9a4..7f6163f164d 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtActivityDelegateBase.java
@@ -46,7 +46,9 @@ abstract class QtActivityDelegateBase
m_activity = activity;
QtNative.setActivity(m_activity);
m_displayManager = new QtDisplayManager(m_activity);
- m_inputDelegate = new QtInputDelegate(m_displayManager::reinstateFullScreen);
+ m_inputDelegate = new QtInputDelegate(() -> {
+ QtWindowInsetsController.restoreFullScreenVisibility(m_activity);
+ });
m_accessibilityDelegate = new QtAccessibilityDelegate();
}
@@ -105,20 +107,20 @@ abstract class QtActivityDelegateBase
Configuration config = resources.getConfiguration();
int uiMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK;
- if (m_displayManager.decorFitsSystemWindows()) {
+ if (QtWindowInsetsController.decorFitsSystemWindows(m_activity)) {
Window window = m_activity.getWindow();
- QtDisplayManager.enableSystemBarsBackgroundDrawing(window);
- int status = QtDisplayManager.getThemeDefaultStatusBarColor(m_activity);
- QtDisplayManager.setStatusBarColor(window, status);
- int nav = QtDisplayManager.getThemeDefaultNavigationBarColor(m_activity);
- QtDisplayManager.setNavigationBarColor(window, nav);
+ QtWindowInsetsController.enableSystemBarsBackgroundDrawing(window);
+ int status = QtWindowInsetsController.getThemeDefaultStatusBarColor(m_activity);
+ QtWindowInsetsController.setStatusBarColor(window, status);
+ int nav = QtWindowInsetsController.getThemeDefaultNavigationBarColor(m_activity);
+ QtWindowInsetsController.setNavigationBarColor(window, nav);
}
// Don't override color scheme if the app has it set explicitly.
if (canOverrideColorSchemeHint()) {
boolean isLight = uiMode == Configuration.UI_MODE_NIGHT_NO;
- QtDisplayManager.setStatusBarColorHint(m_activity, isLight);
- QtDisplayManager.setNavigationBarColorHint(m_activity, isLight);
+ QtWindowInsetsController.setStatusBarColorHint(m_activity, isLight);
+ QtWindowInsetsController.setNavigationBarColorHint(m_activity, isLight);
}
switch (uiMode) {
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
index 8736dfab771..2cabb951813 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtDisplayManager.java
@@ -7,7 +7,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.Build;
@@ -15,22 +14,13 @@ import android.util.DisplayMetrics;
import android.util.Size;
import android.view.Display;
import android.view.Surface;
-import android.view.View;
-import android.view.WindowInsets;
import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
import android.view.WindowMetrics;
-import android.view.WindowInsetsController;
-import android.view.Window;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import android.graphics.Color;
-import android.util.TypedValue;
-import android.content.res.Resources.Theme;
-
import android.util.Log;
class QtDisplayManager
@@ -47,9 +37,6 @@ class QtDisplayManager
static native void handleScreenDensityChanged(double density);
// screen methods
- private boolean m_isFullScreen = false;
- private boolean m_expandedToCutout = false;
-
private static int m_previousRotation = -1;
private final DisplayManager.DisplayListener m_displayListener;
@@ -136,264 +123,6 @@ class QtDisplayManager
}
@SuppressWarnings("deprecation")
- void setSystemUiVisibilityPreAndroidR(View decorView)
- {
- int systemUiVisibility;
-
- if (m_isFullScreen || m_expandedToCutout) {
- systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
- if (m_isFullScreen) {
- systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
- | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
- }
- } else {
- systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
- }
-
- decorView.setSystemUiVisibility(systemUiVisibility);
- }
-
- void setSystemUiVisibility(boolean isFullScreen, boolean expandedToCutout)
- {
- if (m_isFullScreen == isFullScreen && m_expandedToCutout == expandedToCutout)
- return;
-
- m_isFullScreen = isFullScreen;
- m_expandedToCutout = expandedToCutout;
-
- Window window = m_activity.getWindow();
- View decorView = window.getDecorView();
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- int cutoutMode;
- if (m_isFullScreen || m_expandedToCutout) {
- window.setDecorFitsSystemWindows(false);
- cutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
- } else {
- window.setDecorFitsSystemWindows(true);
- cutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
- }
- LayoutParams layoutParams = window.getAttributes();
- layoutParams.layoutInDisplayCutoutMode = cutoutMode;
- window.setAttributes(layoutParams);
-
- final WindowInsetsController insetsControl = window.getInsetsController();
- if (insetsControl != null) {
- int sysBarsBehavior;
- if (m_isFullScreen) {
- insetsControl.hide(WindowInsets.Type.systemBars());
- sysBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
- } else {
- insetsControl.show(WindowInsets.Type.systemBars());
- sysBarsBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
- }
- insetsControl.setSystemBarsBehavior(sysBarsBehavior);
- }
- } else {
- setSystemUiVisibilityPreAndroidR(decorView);
- }
-
- if (!isFullScreen && !edgeToEdgeEnabled(m_activity)) {
- // These are needed to operate on system bar colors
- window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
-
- // Handle transparent status and navigation bars
- if (m_expandedToCutout) {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
- window.setStatusBarColor(Color.TRANSPARENT);
- window.setNavigationBarColor(Color.TRANSPARENT);
- } else {
- // Android 9 and prior doesn't add the semi-transparent bars
- // to avoid low contrast system icons, so try to mimick it
- // by taking the current color and only increase the opacity.
- int statusBarColor = window.getStatusBarColor();
- int transparentStatusBar = statusBarColor & 0x00FFFFFF;
- window.setStatusBarColor(transparentStatusBar);
-
- int navigationBarColor = window.getNavigationBarColor();
- int semiTransparentNavigationBar = navigationBarColor & 0x7FFFFFFF;
- window.setNavigationBarColor(semiTransparentNavigationBar);
- }
- } else {
- // Restore theme's system bars colors
- Theme theme = m_activity.getTheme();
- TypedValue typedValue = new TypedValue();
-
- theme.resolveAttribute(android.R.attr.statusBarColor, typedValue, true);
- int defaultStatusBarColor = typedValue.data;
- window.setStatusBarColor(defaultStatusBarColor);
-
- theme.resolveAttribute(android.R.attr.navigationBarColor, typedValue, true);
- int defaultNavigationBarColor = typedValue.data;
- window.setNavigationBarColor(defaultNavigationBarColor);
- }
- }
-
- decorView.post(() -> decorView.requestApplyInsets());
- }
-
- private static boolean edgeToEdgeEnabled(Activity activity) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return true;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return false;
- int[] attrs = new int[] { android.R.attr.windowOptOutEdgeToEdgeEnforcement };
- TypedArray ta = activity.getTheme().obtainStyledAttributes(attrs);
- try {
- return !ta.getBoolean(0, false);
- } finally {
- ta.recycle();
- }
- }
-
- boolean isFullScreen()
- {
- return m_isFullScreen;
- }
-
- boolean expandedToCutout()
- {
- return m_expandedToCutout;
- }
-
- boolean decorFitsSystemWindows()
- {
- return !isFullScreen() && !expandedToCutout();
- }
-
- void reinstateFullScreen()
- {
- if (m_isFullScreen) {
- m_isFullScreen = false;
- setSystemUiVisibility(true, m_expandedToCutout);
- }
- }
-
- /*
- * Convenience method to call deprecated API prior to Android R (30).
- */
- @SuppressWarnings ("deprecation")
- private static void setSystemUiVisibility(View decorView, int flags)
- {
- decorView.setSystemUiVisibility(flags);
- }
-
- /*
- * Set the status bar color scheme hint so that the system decides how to color the icons.
- */
- @UsedFromNativeCode
- static void setStatusBarColorHint(Activity activity, boolean isLight)
- {
- Window window = activity.getWindow();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- WindowInsetsController controller = window.getInsetsController();
- if (controller != null) {
- int lightStatusBarMask = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
- int appearance = isLight ? lightStatusBarMask : 0;
- controller.setSystemBarsAppearance(appearance, lightStatusBarMask);
- }
- } else {
- @SuppressWarnings("deprecation")
- int currentFlags = window.getDecorView().getSystemUiVisibility();
- @SuppressWarnings("deprecation")
- int lightStatusBarMask = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- int appearance = isLight
- ? currentFlags | lightStatusBarMask
- : currentFlags & ~lightStatusBarMask;
- setSystemUiVisibility(window.getDecorView(), appearance);
- }
- }
-
- /*
- * Set the navigation bar color scheme hint so that the system decides how to color the icons.
- */
- @UsedFromNativeCode
- static void setNavigationBarColorHint(Activity activity, boolean isLight)
- {
- Window window = activity.getWindow();
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
- WindowInsetsController controller = window.getInsetsController();
- if (controller != null) {
- int lightNavigationBarMask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
- int appearance = isLight ? lightNavigationBarMask : 0;
- controller.setSystemBarsAppearance(appearance, lightNavigationBarMask);
- }
- } else {
- @SuppressWarnings("deprecation")
- int currentFlags = window.getDecorView().getSystemUiVisibility();
- @SuppressWarnings("deprecation")
- int lightNavigationBarMask = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
- int appearance = isLight
- ? currentFlags | lightNavigationBarMask
- : currentFlags & ~lightNavigationBarMask;
- setSystemUiVisibility(window.getDecorView(), appearance);
- }
- }
-
- static int resolveColorAttribute(Activity activity, int attribute)
- {
- Theme theme = activity.getTheme();
- Resources resources = activity.getResources();
- TypedValue tv = new TypedValue();
-
- if (theme.resolveAttribute(attribute, tv, true)) {
- if (tv.resourceId != 0)
- return resources.getColor(tv.resourceId, theme);
- if (tv.type >= TypedValue.TYPE_FIRST_COLOR_INT && tv.type <= TypedValue.TYPE_LAST_COLOR_INT)
- return tv.data;
- }
-
- return -1;
- }
-
- @SuppressWarnings("deprecation")
- static int getThemeDefaultStatusBarColor(Activity activity)
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return -1;
- return resolveColorAttribute(activity, android.R.attr.statusBarColor);
- }
-
- @SuppressWarnings("deprecation")
- static int getThemeDefaultNavigationBarColor(Activity activity)
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return -1;
- return resolveColorAttribute(activity, android.R.attr.navigationBarColor);
- }
-
- static void enableSystemBarsBackgroundDrawing(Window window)
- {
- // These are needed to operate on system bar colors
- window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
- @SuppressWarnings("deprecation")
- final int translucentFlags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
- | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
- window.clearFlags(translucentFlags);
- }
-
- @SuppressWarnings("deprecation")
- static void setStatusBarColor(Window window, int color)
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return;
- window.setStatusBarColor(color);
- }
-
- @SuppressWarnings("deprecation")
- static void setNavigationBarColor(Window window, int color)
- {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
- return;
- window.setNavigationBarColor(color);
- }
-
- @SuppressWarnings("deprecation")
static Display getDisplay(Context context)
{
Activity activity = (Activity) context;
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
index ca271c5dd62..e0c6c00a8fd 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtInputDelegate.java
@@ -9,6 +9,7 @@ import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.ResultReceiver;
import android.text.method.MetaKeyKeyListener;
import android.util.DisplayMetrics;
@@ -166,7 +167,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
} else {
if (m_imm == null)
return;
- m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
+ m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler(Looper.getMainLooper())) {
@Override
@SuppressWarnings("fallthrough")
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -278,7 +279,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
activity.getWindow().getInsetsController().hide(Type.ime());
} else {
m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
- new ResultReceiver(new Handler()) {
+ new ResultReceiver(new Handler(Looper.getMainLooper())) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java
index 8fd0213eb91..6d7c0624272 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtLoader.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtLoader.java
@@ -345,7 +345,7 @@ abstract class QtLoader {
if (metadata == null || !metadata.containsKey(key))
return "";
- return String.valueOf(metadata.get(key));
+ return String.valueOf(metadata.getString(key));
}
@SuppressLint("DiscouragedApi")
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtNative.java b/src/android/jar/src/org/qtproject/qt/android/QtNative.java
index 080bb787a2d..7e4632f6792 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtNative.java
@@ -361,8 +361,11 @@ public class QtNative
if (m_stateDetails.isStarted)
return;
+ getQtThread().run(() -> initAndroidQpaPlugin());
final String qtParams = mainLib + " " + params;
getQtThread().post(() -> { startQtNativeApplication(qtParams); });
+ waitForServiceSetup();
+ setStarted(true);
}
@UsedFromNativeCode
@@ -428,7 +431,9 @@ public class QtNative
}
// application methods
+ static native boolean initAndroidQpaPlugin();
static native void startQtNativeApplication(String params);
+ static native void waitForServiceSetup();
static native void terminateQtNativeApplication();
static native boolean updateNativeActivity();
// application methods
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindowInsetsController.java b/src/android/jar/src/org/qtproject/qt/android/QtWindowInsetsController.java
new file mode 100644
index 00000000000..a3d0a0df8e5
--- /dev/null
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindowInsetsController.java
@@ -0,0 +1,358 @@
+// Copyright (C) 2025 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.Activity;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowInsetsController;
+import android.view.Window;
+
+import android.graphics.Color;
+import android.util.TypedValue;
+import android.content.res.Resources.Theme;
+
+class QtWindowInsetsController
+{
+ /*
+ * Convenience method to call deprecated API prior to Android R (30).
+ */
+ @SuppressWarnings ("deprecation")
+ private static void setDecorFitsSystemWindows(Window window, boolean enable)
+ {
+ final int sdk = Build.VERSION.SDK_INT;
+ if (sdk < Build.VERSION_CODES.R || sdk > Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return;
+ window.setDecorFitsSystemWindows(enable);
+ }
+
+ private static void useCutoutShortEdges(Window window, boolean enabled)
+ {
+ if (window == null)
+ return;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ WindowManager.LayoutParams layoutParams = window.getAttributes();
+ layoutParams.layoutInDisplayCutoutMode = enabled
+ ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
+ : WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
+ window.setAttributes(layoutParams);
+ }
+ }
+
+ @UsedFromNativeCode
+ static void showNormal(Activity activity)
+ {
+ Window window = activity.getWindow();
+ if (window == null)
+ return;
+
+ final View decor = window.getDecorView();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ setDecorFitsSystemWindows(window, true);
+ WindowInsetsController ctrl = window.getInsetsController();
+ if (ctrl != null) {
+ ctrl.show(WindowInsets.Type.systemBars());
+ ctrl.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
+ }
+ } else {
+ @SuppressWarnings("deprecation")
+ int flags = View.SYSTEM_UI_FLAG_VISIBLE; // clear all flags
+ setSystemUiVisibility(decor, flags);
+ }
+
+ setTransparentSystemBars(activity, false);
+ useCutoutShortEdges(window, false);
+
+ decor.post(() -> decor.requestApplyInsets());
+ }
+
+ /*
+ * Make system bars transparent for Andorid versions prior to Android 15.
+ */
+ @SuppressWarnings("deprecation")
+ private static void setTransparentSystemBars(Activity activity, boolean transparent)
+ {
+ Window window = activity.getWindow();
+ if (window == null)
+ return;
+
+ if (edgeToEdgeEnabled(activity))
+ return;
+
+ // These are needed to operate on system bar colors
+ window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+
+ if (transparent) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ window.setStatusBarColor(Color.TRANSPARENT);
+ window.setNavigationBarColor(Color.TRANSPARENT);
+ } else {
+ // Android 9 and prior doesn't add the semi-transparent bars
+ // to avoid low contrast system icons, so try to mimick it
+ // by taking the current color and only increase the opacity.
+ int statusBarColor = window.getStatusBarColor();
+ int transparentStatusBar = statusBarColor & 0x00FFFFFF;
+ window.setStatusBarColor(transparentStatusBar);
+
+ int navigationBarColor = window.getNavigationBarColor();
+ int semiTransparentNavigationBar = navigationBarColor & 0x7FFFFFFF;
+ window.setNavigationBarColor(semiTransparentNavigationBar);
+ }
+ } else {
+ // Restore theme's system bars colors
+ int defaultStatusBarColor = getThemeDefaultStatusBarColor(activity);
+ window.setStatusBarColor(defaultStatusBarColor);
+
+ int defaultNavigationBarColor = getThemeDefaultNavigationBarColor(activity);
+ window.setNavigationBarColor(defaultNavigationBarColor);
+ }
+ }
+
+ @UsedFromNativeCode
+ static void showExpanded(Activity activity)
+ {
+ Window window = activity.getWindow();
+ if (window == null)
+ return;
+
+ final View decor = window.getDecorView();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ setDecorFitsSystemWindows(window, false);
+ WindowInsetsController ctrl = window.getInsetsController();
+ if (ctrl != null) {
+ ctrl.show(WindowInsets.Type.systemBars());
+ ctrl.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_DEFAULT);
+ }
+ } else {
+ @SuppressWarnings("deprecation")
+ int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ setSystemUiVisibility(decor, flags);
+ }
+
+ setTransparentSystemBars(activity, true);
+ useCutoutShortEdges(window, true);
+
+ decor.post(() -> decor.requestApplyInsets());
+ }
+
+ @UsedFromNativeCode
+ public static void showFullScreen(Activity activity)
+ {
+ Window window = activity.getWindow();
+ if (window == null)
+ return;
+
+ final View decor = window.getDecorView();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ setDecorFitsSystemWindows(window, false);
+ WindowInsetsController ctrl = window.getInsetsController();
+ if (ctrl != null) {
+ ctrl.hide(WindowInsets.Type.systemBars());
+ ctrl.setSystemBarsBehavior(
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
+ }
+ } else {
+ @SuppressWarnings("deprecation")
+ int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ setSystemUiVisibility(decor, flags);
+ }
+
+ useCutoutShortEdges(window, true);
+
+ decor.post(() -> decor.requestApplyInsets());
+ }
+
+ private static boolean edgeToEdgeEnabled(Activity activity) {
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return true;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return false;
+ int[] attrs = new int[] { android.R.attr.windowOptOutEdgeToEdgeEnforcement };
+ TypedArray ta = activity.getTheme().obtainStyledAttributes(attrs);
+ try {
+ return !ta.getBoolean(0, false);
+ } finally {
+ ta.recycle();
+ }
+ }
+
+ static boolean isFullScreen(Activity activity)
+ {
+ Window window = activity.getWindow();
+ if (window == null)
+ return false;
+
+ final View decor = window.getDecorView();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
+ if (insets != null)
+ return !insets.isVisible(WindowInsets.Type.statusBars());
+ } else {
+ @SuppressWarnings("deprecation")
+ int flags = decor.getSystemUiVisibility();
+ @SuppressWarnings("deprecation")
+ int immersiveMask = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+ return (flags & immersiveMask) == immersiveMask;
+ }
+
+ return false;
+ }
+
+ static boolean isExpandedClientArea(Activity activity)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return edgeToEdgeEnabled(activity);
+
+ @SuppressWarnings("deprecation")
+ int statusBarColor = activity.getWindow().getStatusBarColor();
+ // If the status bar is not fully opaque assume we have expanded client
+ // area and we're drawing under it.
+ int statusBarAlpha = statusBarColor >>> 24;
+ return statusBarAlpha != 0xFF;
+ }
+
+ static boolean decorFitsSystemWindows(Activity activity)
+ {
+ return !isFullScreen(activity) && !isExpandedClientArea(activity);
+ }
+
+ static void restoreFullScreenVisibility(Activity activity)
+ {
+ if (isFullScreen(activity))
+ showFullScreen(activity);
+ }
+
+ /*
+ * Convenience method to call deprecated API prior to Android R (30).
+ */
+ @SuppressWarnings ("deprecation")
+ private static void setSystemUiVisibility(View decorView, int flags)
+ {
+ decorView.setSystemUiVisibility(flags);
+ }
+
+ /*
+ * Set the status bar color scheme hint so that the system decides how to color the icons.
+ */
+ @UsedFromNativeCode
+ static void setStatusBarColorHint(Activity activity, boolean isLight)
+ {
+ Window window = activity.getWindow();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ WindowInsetsController controller = window.getInsetsController();
+ if (controller != null) {
+ int lightStatusBarMask = WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+ int appearance = isLight ? lightStatusBarMask : 0;
+ controller.setSystemBarsAppearance(appearance, lightStatusBarMask);
+ }
+ } else {
+ @SuppressWarnings("deprecation")
+ int currentFlags = window.getDecorView().getSystemUiVisibility();
+ @SuppressWarnings("deprecation")
+ int lightStatusBarMask = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+ int appearance = isLight
+ ? currentFlags | lightStatusBarMask
+ : currentFlags & ~lightStatusBarMask;
+ setSystemUiVisibility(window.getDecorView(), appearance);
+ }
+ }
+
+ /*
+ * Set the navigation bar color scheme hint so that the system decides how to color the icons.
+ */
+ @UsedFromNativeCode
+ static void setNavigationBarColorHint(Activity activity, boolean isLight)
+ {
+ Window window = activity.getWindow();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ WindowInsetsController controller = window.getInsetsController();
+ if (controller != null) {
+ int lightNavigationBarMask = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+ int appearance = isLight ? lightNavigationBarMask : 0;
+ controller.setSystemBarsAppearance(appearance, lightNavigationBarMask);
+ }
+ } else {
+ @SuppressWarnings("deprecation")
+ int currentFlags = window.getDecorView().getSystemUiVisibility();
+ @SuppressWarnings("deprecation")
+ int lightNavigationBarMask = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+ int appearance = isLight
+ ? currentFlags | lightNavigationBarMask
+ : currentFlags & ~lightNavigationBarMask;
+ setSystemUiVisibility(window.getDecorView(), appearance);
+ }
+ }
+
+ private static int resolveColorAttribute(Activity activity, int attribute)
+ {
+ Theme theme = activity.getTheme();
+ Resources resources = activity.getResources();
+ TypedValue tv = new TypedValue();
+
+ if (theme.resolveAttribute(attribute, tv, true)) {
+ if (tv.resourceId != 0)
+ return resources.getColor(tv.resourceId, theme);
+ if (tv.type >= TypedValue.TYPE_FIRST_COLOR_INT && tv.type <= TypedValue.TYPE_LAST_COLOR_INT)
+ return tv.data;
+ }
+
+ return -1;
+ }
+
+ @SuppressWarnings("deprecation")
+ static int getThemeDefaultStatusBarColor(Activity activity)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return -1;
+ return resolveColorAttribute(activity, android.R.attr.statusBarColor);
+ }
+
+ @SuppressWarnings("deprecation")
+ static int getThemeDefaultNavigationBarColor(Activity activity)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return -1;
+ return resolveColorAttribute(activity, android.R.attr.navigationBarColor);
+ }
+
+ static void enableSystemBarsBackgroundDrawing(Window window)
+ {
+ // These are needed to operate on system bar colors
+ window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
+ @SuppressWarnings("deprecation")
+ final int translucentFlags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+ window.clearFlags(translucentFlags);
+ }
+
+ @SuppressWarnings("deprecation")
+ static void setStatusBarColor(Window window, int color)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return;
+ window.setStatusBarColor(color);
+ }
+
+ @SuppressWarnings("deprecation")
+ static void setNavigationBarColor(Window window, int color)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
+ return;
+ window.setNavigationBarColor(color);
+ }
+}
diff --git a/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
index d42b3e6821e..1cd36f06f5c 100644
--- a/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
+++ b/src/android/jar/src/org/qtproject/qt/android/QtWindowInterface.java
@@ -7,5 +7,4 @@ interface QtWindowInterface {
default void removeTopLevelWindow(final int id) { }
default void bringChildToFront(final int id) { }
default void bringChildToBack(int id) { }
- default void setSystemUiVisibility(boolean isFullScreen, boolean expandedToCutout) { }
}
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
index bc2bbf9e53e..723a462bae1 100644
--- a/src/corelib/global/qnumeric.h
+++ b/src/corelib/global/qnumeric.h
@@ -20,6 +20,18 @@
#include <limits>
#include <QtCore/q20type_traits.h>
+#if __has_include(<stdckdint.h>)
+// This was added by C23 and C++26, defining __STDC_VERSION_STDCKDINT_H__ when
+// usable. Its provided functions are in the global namespace even in C++ (not
+// std::) because they are sometimes macros.
+# include <QtCore/qstdlibdetection.h>
+# if defined(Q_CC_GNU_ONLY) && (defined(Q_STL_LIBCPP) || Q_CC_GNU_ONLY < 1500)
+// broken - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121811
+# else
+# include <stdckdint.h>
+# endif
+#endif
+
// min() and max() may be #defined by windows.h if that is included before, but we need them
// for std::numeric_limits below. You should not use the min() and max() macros, so we just #undef.
#ifdef min
@@ -263,7 +275,10 @@ constexpr inline
typename std::enable_if_t<std::is_unsigned_v<T>, bool>
qAddOverflow(T v1, T v2, T *r)
{
-#if defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+#if defined(__STDC_VERSION_STDCKDINT_H__)
+ return ckd_add(r, v1, v2);
+#elif defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
return __builtin_add_overflow(v1, v2, r);
#else
if (q20::is_constant_evaluated())
@@ -285,7 +300,7 @@ qAddOverflow(T v1, T v2, T *r)
}
# endif // defined(Q_HAVE_ADDCARRY)
return QtPrivate::qAddOverflowGeneric(v1, v2, r);
-#endif // defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+#endif
}
template <typename T>
@@ -293,7 +308,10 @@ constexpr inline
typename std::enable_if_t<std::is_signed_v<T>, bool>
qAddOverflow(T v1, T v2, T *r)
{
-#if defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+#if defined(__STDC_VERSION_STDCKDINT_H__)
+ return ckd_add(r, v1, v2);
+#elif defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
return __builtin_add_overflow(v1, v2, r);
#else
// Here's how we calculate the overflow:
@@ -314,7 +332,7 @@ qAddOverflow(T v1, T v2, T *r)
// (x ^ z) & (y ^ z) is negative if x and z have different signs
// AND y and z have different signs
return ((v1 ^ *r) & (v2 ^ *r)) < 0;
-#endif // defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+#endif
}
template <typename T>
@@ -322,13 +340,16 @@ constexpr inline
typename std::enable_if_t<std::is_unsigned_v<T>, bool>
qSubOverflow(T v1, T v2, T *r)
{
-#if defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+#if defined(__STDC_VERSION_STDCKDINT_H__)
+ return ckd_sub(r, v1, v2);
+#elif defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
return __builtin_sub_overflow(v1, v2, r);
#else
// unsigned subtractions are well-defined
*r = v1 - v2;
return v1 < v2;
-#endif // defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+#endif
}
template <typename T>
@@ -336,7 +357,10 @@ constexpr inline
typename std::enable_if_t<std::is_signed_v<T>, bool>
qSubOverflow(T v1, T v2, T *r)
{
-#if defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+#if defined(__STDC_VERSION_STDCKDINT_H__)
+ return ckd_sub(r, v1, v2);
+#elif defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
return __builtin_sub_overflow(v1, v2, r);
#else
// See above for explanation. This is the same with some signs reversed.
@@ -347,7 +371,7 @@ qSubOverflow(T v1, T v2, T *r)
*r = T(U(v1) - U(v2));
return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
-#endif // defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+#endif
}
template <typename T>
@@ -355,7 +379,10 @@ constexpr inline
typename std::enable_if_t<std::is_unsigned_v<T> || std::is_signed_v<T>, bool>
qMulOverflow(T v1, T v2, T *r)
{
-#if defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+#if defined(__STDC_VERSION_STDCKDINT_H__)
+ return ckd_mul(r, v1, v2);
+#elif defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
# if defined(Q_INTRINSIC_MUL_OVERFLOW64)
return __builtin_mul_overflow(v1, v2, r);
# else
@@ -388,7 +415,7 @@ qMulOverflow(T v1, T v2, T *r)
# endif // defined(Q_INTRINSIC_MUL_OVERFLOW64)
return QtPrivate::qMulOverflowGeneric(v1, v2, r);
-#endif // defined(Q_NUMERIC_USE_GCC_OVERFLOW_BUILTINS)
+#endif
}
#undef Q_HAVE_ADDCARRY
@@ -421,6 +448,8 @@ template <auto V2, typename T> constexpr bool qSubOverflow(T v1, T *r)
template <typename T, T V2> constexpr bool qMulOverflow(T v1, std::integral_constant<T, V2>, T *r)
{
+ static_assert(!std::is_same_v<T, char>, "Template must be an integral other than plain 'char'");
+
// Runtime detection for anything smaller than or equal to a register
// width, as most architectures' multiplication instructions actually
// produce a result twice as wide as the input registers, allowing us to
diff --git a/src/corelib/kernel/qwinregistry.cpp b/src/corelib/kernel/qwinregistry.cpp
index 9740edbf299..fb315cacb7e 100644
--- a/src/corelib/kernel/qwinregistry.cpp
+++ b/src/corelib/kernel/qwinregistry.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2019 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
+// Qt-Security score:critical reason:data-parser
#define UMDF_USING_NTSTATUS // Avoid ntstatus redefinitions
diff --git a/src/corelib/kernel/qwinregistry_p.h b/src/corelib/kernel/qwinregistry_p.h
index 5643a35363b..fd6d6dc853f 100644
--- a/src/corelib/kernel/qwinregistry_p.h
+++ b/src/corelib/kernel/qwinregistry_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2019 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
+// Qt-Security score:significant reason:trivial-impl-only
#ifndef QWINREGISTRY_H
#define QWINREGISTRY_H
@@ -41,12 +42,17 @@ public:
~QWinRegistryKey();
QWinRegistryKey(QWinRegistryKey &&other) noexcept
+#if 1 // QTBUG-140725
+ = delete;
+ void operator=(QWinRegistryKey &&) = delete;
+#else
: m_key(std::exchange(other.m_key, nullptr)) {}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QWinRegistryKey)
void swap(QWinRegistryKey &other) noexcept
{
qt_ptr_swap(m_key, other.m_key);
}
+#endif
[[nodiscard]] bool isValid() const { return m_key != nullptr; }
diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp
index 9a566b999b4..de6edcb75e6 100644
--- a/src/corelib/serialization/qcborarray.cpp
+++ b/src/corelib/serialization/qcborarray.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2018 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcborarray.h"
#include "qcborvalue_p.h"
diff --git a/src/corelib/serialization/qcborcommon_p.h b/src/corelib/serialization/qcborcommon_p.h
index b80451be4bc..66c95ee887f 100644
--- a/src/corelib/serialization/qcborcommon_p.h
+++ b/src/corelib/serialization/qcborcommon_p.h
@@ -1,6 +1,7 @@
// Copyright (C) 2018 Intel Corporation.
// Copyright (C) 2019 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
+// Qt-Security score:critical reason:data-parser
#ifndef QCBORCOMMON_P_H
#define QCBORCOMMON_P_H
diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp
index 32d6d563ac4..9c17e07b70b 100644
--- a/src/corelib/serialization/qcbormap.cpp
+++ b/src/corelib/serialization/qcbormap.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2018 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:critical reason:data-parser
#include "qcbormap.h"
#include "qcborvalue_p.h"
diff --git a/src/corelib/serialization/qcborstream.h b/src/corelib/serialization/qcborstream.h
index 7850d266639..e51296f3cca 100644
--- a/src/corelib/serialization/qcborstream.h
+++ b/src/corelib/serialization/qcborstream.h
@@ -1,6 +1,7 @@
// Copyright (C) 2019 The Qt Company Ltd.
// Copyright (C) 2018 Intel Corporation.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+// Qt-Security score:significant reason:header-decls-only
#ifndef QCBORSTREAM_H
#define QCBORSTREAM_H
diff --git a/src/corelib/serialization/qjsonparser_p.h b/src/corelib/serialization/qjsonparser_p.h
index 6b70af38152..8951bb3129b 100644
--- a/src/corelib/serialization/qjsonparser_p.h
+++ b/src/corelib/serialization/qjsonparser_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 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
+// Qt-Security score:significant reason:header-decls-only
#ifndef QJSONPARSER_P_H
#define QJSONPARSER_P_H
diff --git a/src/corelib/serialization/qjsonwriter_p.h b/src/corelib/serialization/qjsonwriter_p.h
index 446ed906e21..10b89f3c106 100644
--- a/src/corelib/serialization/qjsonwriter_p.h
+++ b/src/corelib/serialization/qjsonwriter_p.h
@@ -1,5 +1,6 @@
// Copyright (C) 2016 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
+// Qt-Security score:significant reason:header-decls-only
#ifndef QJSONWRITER_P_H
#define QJSONWRITER_P_H
diff --git a/src/gui/accessible/linux/qspiaccessiblebridge.cpp b/src/gui/accessible/linux/qspiaccessiblebridge.cpp
index 1ee1a435ca5..11b3bc57471 100644
--- a/src/gui/accessible/linux/qspiaccessiblebridge.cpp
+++ b/src/gui/accessible/linux/qspiaccessiblebridge.cpp
@@ -184,6 +184,12 @@ static RoleMapping map[] = {
//: Role of an accessible object
{ QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "check box") },
//: Role of an accessible object
+#if ATSPI_ROLE_COUNT >= 132
+ { QAccessible::Switch, ATSPI_ROLE_SWITCH, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "switch") },
+#else
+ { QAccessible::Switch, ATSPI_ROLE_CHECK_BOX, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "check box") },
+#endif
+ //: Role of an accessible object
{ QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "radio button") },
//: Role of an accessible object
{ QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "combo box") },
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 97f7eb94e2a..eeb06c535b8 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -342,6 +342,7 @@ Q_STATIC_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value Splitter A splitter distributing available space between its child widgets.
\value StaticText Static text, such as labels for other widgets.
\value StatusBar A status bar.
+ \value [since 6.11] Switch A switch that can be toggled on or off.
\value Table A table representing data in a grid of rows and columns.
\value Terminal A terminal or command line interface.
\value TitleBar The title bar caption of a window.
diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h
index 0a1a305b76d..31b97880ffc 100644
--- a/src/gui/accessible/qaccessible_base.h
+++ b/src/gui/accessible/qaccessible_base.h
@@ -267,6 +267,7 @@ public:
WebDocument = 0x00000084,
Section = 0x00000085,
Notification = 0x00000086,
+ Switch = 0x00000087,
// IAccessible2 roles
// IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index 5c723cdb289..9edb0dff4fd 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -119,14 +119,14 @@ QWindow *QAccessibleApplication::window() const
return nullptr;
}
-// all toplevel windows except popups and the desktop
+// all toplevel windows except popups
static QObjectList topLevelObjects()
{
QObjectList list;
const QWindowList tlw(QGuiApplication::topLevelWindows());
for (int i = 0; i < tlw.size(); ++i) {
QWindow *w = tlw.at(i);
- if (w->type() != Qt::Popup && w->type()) {
+ if (w->type() != Qt::Popup) {
if (QAccessibleInterface *root = w->accessibleRoot()) {
if (root->object())
list.append(root->object());
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 8e21c92f9b3..8f29fb503b0 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -352,8 +352,8 @@ QIconTheme::QIconTheme(const QString &themeName)
QFile themeIndex;
const QStringList iconDirs = QIcon::themeSearchPaths();
- for ( int i = 0 ; i < iconDirs.size() ; ++i) {
- QDir iconDir(iconDirs[i]);
+ for (const auto &dirName : iconDirs) {
+ QDir iconDir(dirName);
QString themeDir = iconDir.path() + u'/' + themeName;
QFileInfo themeDirInfo(themeDir);
@@ -479,7 +479,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
const QString pngIconName = iconNameFallback + ".png"_L1;
// Add all relevant files
- for (int i = 0; i < contentDirs.size(); ++i) {
+ for (qsizetype i = 0; i < contentDirs.size(); ++i) {
QList<QIconDirInfo> subDirs = theme.keyList();
// Try to reduce the amount of subDirs by looking in the GTK+ cache in order to save
@@ -504,8 +504,7 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
}
QString contentDir = contentDirs.at(i) + u'/';
- for (int j = 0; j < subDirs.size() ; ++j) {
- const QIconDirInfo &dirInfo = subDirs.at(j);
+ for (const auto &dirInfo : std::as_const(subDirs)) {
if (searchingGenericFallback &&
(dirInfo.context == QIconDirInfo::Applications ||
dirInfo.context == QIconDirInfo::MimeTypes))
@@ -544,9 +543,9 @@ QThemeIconInfo QIconLoader::findIconHelper(const QString &themeName,
<< "skipping visited" << visited;
// Search recursively through inherited themes
- for (int i = 0 ; i < parents.size() ; ++i) {
+ for (const auto &parent : parents) {
- const QString parentTheme = parents.at(i).trimmed();
+ const QString parentTheme = parent.trimmed();
if (!visited.contains(parentTheme)) // guard against recursion
info = findIconHelper(parentTheme, iconName, visited, QIconLoader::NoFallBack);
diff --git a/src/gui/kernel/qplatformwindow_p.h b/src/gui/kernel/qplatformwindow_p.h
index c446ac760c0..24c0fd7c431 100644
--- a/src/gui/kernel/qplatformwindow_p.h
+++ b/src/gui/kernel/qplatformwindow_p.h
@@ -125,6 +125,14 @@ struct Q_GUI_EXPORT QWaylandWindow : public QObject
public:
QT_DECLARE_NATIVE_INTERFACE(QWaylandWindow, 1, QWindow)
+ enum WindowType {
+ Default,
+ ToolTip,
+ ComboBox,
+ Menu,
+ SubMenu,
+ };
+
virtual wl_surface *surface() const = 0;
virtual void setCustomMargins(const QMargins &margins) = 0;
virtual void requestXdgActivationToken(uint serial) = 0;
@@ -136,6 +144,10 @@ public:
return role ? *role : nullptr;
}
virtual void setSessionRestoreId(const QString &role) = 0;
+
+ virtual void setExtendedWindowType(WindowType windowType) = 0;
+ virtual void setParentControlGeometry(const QRect &parentAnchor) = 0;
+
Q_SIGNALS:
void surfaceCreated();
void surfaceDestroyed();
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 3b64a8ecf73..a3f9f069b69 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -1527,14 +1527,14 @@ void QPainterPrivate::initFrom(const QPaintDevice *device)
Q_Q(QPainter);
device->initPainter(q);
+}
- if (extended) {
- extended->penChanged();
- } else if (engine) {
- engine->setDirty(QPaintEngine::DirtyPen);
- engine->setDirty(QPaintEngine::DirtyBrush);
- engine->setDirty(QPaintEngine::DirtyFont);
- }
+void QPainterPrivate::setEngineDirtyFlags(QSpan<const QPaintEngine::DirtyFlags> flags)
+{
+ if (!engine)
+ return;
+ for (const QPaintEngine::DirtyFlags f : flags)
+ engine->setDirty(f);
}
/*!
@@ -1801,14 +1801,16 @@ bool QPainter::begin(QPaintDevice *pd)
d->engine->setActive(begun);
}
- // Copy painter properties from original paint device,
- // required for QPixmap::grabWidget()
- if (d->original_device->devType() == QInternal::Widget) {
+ switch (d->original_device->devType()) {
+ case QInternal::Widget:
d->initFrom(d->original_device);
- } else {
+ break;
+
+ default:
d->state->layoutDirection = Qt::LayoutDirectionAuto;
// make sure we have a font compatible with the paintdevice
d->state->deviceFont = d->state->font = QFont(d->state->deviceFont, device());
+ break;
}
QRect systemRect = d->engine->systemRect();
@@ -1834,6 +1836,15 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->emulationSpecifier = 0;
+ switch (d->original_device->devType()) {
+ case QInternal::Widget:
+ // for widgets we've aleady initialized the painter above
+ break;
+ default:
+ d->initFrom(d->original_device);
+ break;
+ }
+
return true;
}
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index dd4653a5788..a6f93134ca0 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -15,6 +15,7 @@
// We mean it.
//
+#include <QtCore/qspan.h>
#include <QtCore/qvarlengtharray.h>
#include <QtGui/private/qtguiglobal_p.h>
#include "QtGui/qbrush.h"
@@ -242,6 +243,8 @@ public:
std::unique_ptr<QEmulationPaintEngine> emulationEngine;
QPaintEngineEx *extended = nullptr;
QBrush colorBrush; // for fill with solid color
+
+ Q_GUI_EXPORT void setEngineDirtyFlags(QSpan<const QPaintEngine::DirtyFlags>);
};
Q_GUI_EXPORT void qt_draw_helper(QPainterPrivate *p, const QPainterPath &path, QPainterPrivate::DrawOperation operation);
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index a1edf49da12..028ae6d682a 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -470,7 +470,6 @@ namespace QtAndroidAccessibility
case QAccessible::Role::Link:
{
if (state.checkable)
- // There is also a android.widget.Switch for which we have no match.
return QStringLiteral("android.widget.ToggleButton");
return QStringLiteral("android.widget.Button");
}
@@ -478,6 +477,8 @@ namespace QtAndroidAccessibility
// As of android/accessibility/utils/Role.java::getRole a CheckBox
// is NOT android.widget.CheckBox
return QStringLiteral("android.widget.CompoundButton");
+ case QAccessible::Role::Switch:
+ return QStringLiteral("android.widget.Switch");
case QAccessible::Role::Clock:
return QStringLiteral("android.widget.TextClock");
case QAccessible::Role::ComboBox:
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index 8c5335d9c31..9059fab757b 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -359,20 +359,41 @@ namespace QtAndroid
static bool initJavaReferences(QJniEnvironment &env);
-static void initializeBackends()
+static bool initAndroidQpaPlugin(JNIEnv *jenv, jobject object)
{
+ Q_UNUSED(jenv)
+ Q_UNUSED(object)
+
+ // Init all the Java refs, if they haven't already been initialized. They get initialized
+ // when the library is loaded, but in case Qt is terminated, they are cleared, and in case
+ // Qt is then started again JNI_OnLoad will not be called again, since the library is already
+ // loaded - in that case we need to init again here, hence the check.
+ // TODO QTBUG-130614 QtCore also inits some Java references in qjnihelpers - we probably
+ // want to reset those, too.
+ QJniEnvironment qEnv;
+ if (!qEnv.isValid()) {
+ qCritical() << "Failed to initialize the JNI Environment";
+ return false;
+ }
+
+ if (!initJavaReferences(qEnv))
+ return false;
+
+ m_androidPlatformIntegration = nullptr;
+
// File engine handler instantiation registers the handler
m_androidAssetsFileEngineHandler = new AndroidAssetsFileEngineHandler();
m_androidContentFileEngineHandler = new AndroidContentFileEngineHandler();
m_androidApkFileEngineHandler = new QAndroidApkFileEngineHandler();
m_backendRegister = new AndroidBackendRegister();
-}
-static bool initCleanupHandshakeSemaphores()
-{
- return sem_init(&m_exitSemaphore, 0, 0) != -1
- && sem_init(&m_stopQtSemaphore, 0, 0) != -1;
+ if (sem_init(&m_exitSemaphore, 0, 0) == -1 && sem_init(&m_stopQtSemaphore, 0, 0) == -1) {
+ qCritical() << "Failed to init Qt application cleanup semaphores";
+ return false;
+ }
+
+ return true;
}
static void startQtNativeApplication(JNIEnv *jenv, jobject object, jstring paramsString)
@@ -391,23 +412,6 @@ static void startQtNativeApplication(JNIEnv *jenv, jobject object, jstring param
vm->AttachCurrentThread(&env, &args);
}
- // Init all the Java refs, if they haven't already been initialized. They get initialized
- // when the library is loaded, but in case Qt is terminated, they are cleared, and in case
- // Qt is then started again JNI_OnLoad will not be called again, since the library is already
- // loaded - in that case we need to init again here, hence the check.
- // TODO QTBUG-130614 QtCore also inits some Java references in qjnihelpers - we probably
- // want to reset those, too.
- QJniEnvironment qEnv;
- if (!qEnv.isValid()) {
- qCritical() << "Failed to initialize the JNI Environment";
- return;
- }
- if (!initJavaReferences(qEnv))
- return;
-
- m_androidPlatformIntegration = nullptr;
- initializeBackends();
-
const QStringList argsList = QProcess::splitCommand(QJniObject(paramsString).toString());
const int argc = argsList.size();
QVarLengthArray<char *> argv(argc + 1);
@@ -444,11 +448,6 @@ static void startQtNativeApplication(JNIEnv *jenv, jobject object, jstring param
return;
}
- if (!initCleanupHandshakeSemaphores()) {
- qCritical() << "Failed to init Qt application cleanup semaphores";
- return;
- }
-
// Register type for invokeMethod() calls.
qRegisterMetaType<Qt::ScreenOrientation>("Qt::ScreenOrientation");
@@ -458,13 +457,6 @@ static void startQtNativeApplication(JNIEnv *jenv, jobject object, jstring param
startQtAndroidPluginCalled.fetchAndAddRelease(1);
- QtNative::callStaticMethod("setStarted", true);
-
- // The service must wait until the QCoreApplication starts,
- // otherwise onBind will be called too early.
- if (QtAndroidPrivate::service().isValid() && QtAndroid::isQtApplication())
- QtAndroidPrivate::waitForServiceSetup();
-
const int ret = m_main(argc, argv.data());
qInfo() << "main() returned" << ret;
@@ -540,6 +532,15 @@ static void clearJavaReferences(JNIEnv *env)
}
}
+static void waitForServiceSetup(JNIEnv *env, jclass /*clazz*/)
+{
+ Q_UNUSED(env);
+ // The service must wait until the QCoreApplication starts otherwise onBind will be
+ // called too early
+ if (QtAndroidPrivate::service().isValid() && QtAndroid::isQtApplication())
+ QtAndroidPrivate::waitForServiceSetup();
+}
+
static void terminateQtNativeApplication(JNIEnv *env, jclass /*clazz*/)
{
// QAndroidEventDispatcherStopper is stopped when the user uses the task manager
@@ -730,8 +731,10 @@ static jobject onBind(JNIEnv */*env*/, jclass /*cls*/, jobject intent)
}
static JNINativeMethod methods[] = {
+ { "initAndroidQpaPlugin", "()Z", (void *)initAndroidQpaPlugin },
{ "startQtNativeApplication", "(Ljava/lang/String;)V", (void *)startQtNativeApplication },
{ "terminateQtNativeApplication", "()V", (void *)terminateQtNativeApplication },
+ { "waitForServiceSetup", "()V", (void *)waitForServiceSetup },
{ "updateApplicationState", "(I)V", (void *)updateApplicationState },
{ "onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult },
{ "onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent },
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index ecbbddb2e36..1d755139b46 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -82,9 +82,6 @@ static bool hasValidFocusObject()
if (!m_androidInputContext)
return false;
- if (!m_androidInputContext->isInputPanelVisible())
- return false;
-
const auto focusObject = m_androidInputContext->focusObject();
if (!focusObject)
return false;
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index 822a5357107..0d8673aac03 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -27,7 +27,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus")
-Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtDisplayManager")
+Q_DECLARE_JNI_CLASS(QtWindowInsetsController, "org/qtproject/qt/android/QtWindowInsetsController")
using namespace Qt::StringLiterals;
@@ -448,9 +448,9 @@ void QAndroidPlatformTheme::requestColorScheme(Qt::ColorScheme scheme)
const auto iface = qGuiApp->nativeInterface<QNativeInterface::QAndroidApplication>();
iface->runOnAndroidMainThread([=]() {
bool isLight = scheme == Qt::ColorScheme::Light;
- QtJniTypes::QtDisplayManager::callStaticMethod("setStatusBarColorHint",
+ QtJniTypes::QtWindowInsetsController::callStaticMethod("setStatusBarColorHint",
iface->context().object<QtJniTypes::Activity>(), isLight);
- QtJniTypes::QtDisplayManager::callStaticMethod("setNavigationBarColorHint",
+ QtJniTypes::QtWindowInsetsController::callStaticMethod("setNavigationBarColorHint",
iface->context().object<QtJniTypes::Activity>(), isLight);
});
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 937839ace0c..96c4bfa06f1 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -22,6 +22,7 @@ Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface
Q_DECLARE_JNI_CLASS(QtInputConnectionListener,
"org/qtproject/qt/android/QtInputConnection$QtInputConnectionListener")
Q_DECLARE_JNI_CLASS(QtDisplayManager, "org/qtproject/qt/android/QtWindowInterface")
+Q_DECLARE_JNI_CLASS(QtWindowInsetsController, "org/qtproject/qt/android/QtWindowInsetsController")
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
: QPlatformWindow(window), m_nativeQtWindow(nullptr),
@@ -260,10 +261,17 @@ void QAndroidPlatformWindow::updateSystemUiVisibility()
const int flags = window()->flags();
const bool isNonRegularWindow = flags & (Qt::Popup | Qt::Dialog | Qt::Sheet) & ~Qt::Window;
if (!isNonRegularWindow) {
- const bool isFullScreen = (m_windowState & Qt::WindowFullScreen);
- const bool expandedToCutout = (flags & Qt::ExpandedClientAreaHint);
- QtAndroid::backendRegister()->callInterface<QtJniTypes::QtWindowInterface, void>(
- "setSystemUiVisibility", isFullScreen, expandedToCutout);
+ auto iface = qGuiApp->nativeInterface<QNativeInterface::QAndroidApplication>();
+ iface->runOnAndroidMainThread([=]() {
+ using namespace QtJniTypes;
+ auto activity = iface->context().object<Activity>();
+ if (m_windowState & Qt::WindowFullScreen)
+ QtWindowInsetsController::callStaticMethod("showFullScreen", activity);
+ else if (flags & Qt::ExpandedClientAreaHint)
+ QtWindowInsetsController::callStaticMethod("showExpanded", activity);
+ else
+ QtWindowInsetsController::callStaticMethod("showNormal", activity);
+ });
}
}
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index 69ee3638ac6..08c9f5d5ba2 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -132,6 +132,7 @@ static void populateRoleMap()
roleMap[QAccessible::ComboBox] = NSAccessibilityComboBoxRole;
roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole;
roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole;
+ roleMap[QAccessible::Switch] = NSAccessibilityCheckBoxRole;
roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole;
roleMap[QAccessible::Table] = NSAccessibilityTableRole;
roleMap[QAccessible::StatusBar] = NSAccessibilityStaticTextRole;
@@ -204,6 +205,8 @@ NSString *macSubrole(QAccessibleInterface *interface)
return NSAccessibilitySecureTextFieldSubrole;
if (interface->role() == QAccessible::PageTab)
return NSAccessibilityTabButtonSubrole;
+ if (interface->role() == QAccessible::Switch)
+ return NSAccessibilitySwitchSubrole;
return nil;
}
@@ -328,8 +331,11 @@ NSString *getTranslatedAction(const QString &qtAction)
QString translateAction(NSString *nsAction, QAccessibleInterface *interface)
{
if ([nsAction compare: NSAccessibilityPressAction] == NSOrderedSame) {
- if (interface->role() == QAccessible::CheckBox || interface->role() == QAccessible::RadioButton)
+ if (interface->role() == QAccessible::CheckBox
+ || interface->role() == QAccessible::RadioButton
+ || interface->role() == QAccessible::Switch) {
return QAccessibleActionInterface::toggleAction();
+ }
return QAccessibleActionInterface::pressAction();
} else if ([nsAction compare: NSAccessibilityIncrementAction] == NSOrderedSame)
return QAccessibleActionInterface::increaseAction();
diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm
index d10fe40840a..0d6952bddf0 100644
--- a/src/plugins/platforms/ios/quiaccessibilityelement.mm
+++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm
@@ -115,6 +115,9 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
|| iface->role() == QAccessible::RadioButton)
return @"";
+ if (iface->role() == QAccessible::Switch)
+ return state.checked ? @"1" : @"0";
+
return state.checked
? QCoreApplication::translate(ACCESSIBILITY_ELEMENT, AE_CHECKED).toNSString()
: QCoreApplication::translate(ACCESSIBILITY_ELEMENT, AE_UNCHECKED).toNSString();
@@ -169,6 +172,8 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QMacAccessibilityElement);
|| accessibleRole == QAccessible::RadioButton) {
if (state.checked)
traits |= UIAccessibilityTraitSelected;
+ } else if (accessibleRole == QAccessible::Switch) {
+ traits |= UIAccessibilityTraitToggleButton;
} else if (accessibleRole == QAccessible::EditableText) {
static auto defaultTextFieldTraits = []{
auto *textField = [[[UITextField alloc] initWithFrame:CGRectZero] autorelease];
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index 1cf81453fe7..35e804531bc 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -363,6 +363,17 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac
addEventListener(element, "change");
} break;
+ case QAccessible::Switch: {
+ element = document.call<emscripten::val>("createElement", std::string("button"));
+ setAttribute(element, "type", "button");
+ setAttribute(element, "role", "switch");
+ if (iface->state().checked)
+ setAttribute(element, "aria-checked", "true");
+ else
+ setAttribute(element, "aria-checked", "false");
+ addEventListener(element, "change");
+ } break;
+
case QAccessible::RadioButton: {
element = document.call<emscripten::val>("createElement", std::string("input"));
setAttribute(element, "type", "radio");
@@ -743,6 +754,28 @@ void QWasmAccessibility::handleCheckBoxUpdate(QAccessibleEvent *event)
break;
}
}
+
+void QWasmAccessibility::handleSwitchUpdate(QAccessibleEvent *event)
+{
+ switch (event->type()) {
+ case QAccessible::Focus:
+ case QAccessible::NameChanged: {
+ setHtmlElementTextName(event->accessibleInterface());
+ } break;
+ case QAccessible::StateChanged: {
+ QAccessibleInterface *accessible = event->accessibleInterface();
+ const emscripten::val element = getHtmlElement(accessible);
+ if (accessible->state().checked)
+ setAttribute(element, "aria-checked", "true");
+ else
+ setAttribute(element, "aria-checked", "false");
+ } break;
+ default:
+ qCDebug(lcQpaAccessibility) << "TODO: implement handleSwitchUpdate for event" << event->type();
+ break;
+ }
+}
+
void QWasmAccessibility::handleToolUpdate(QAccessibleEvent *event)
{
QAccessibleInterface *iface = event->accessibleInterface();
@@ -1152,6 +1185,9 @@ void QWasmAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event)
case QAccessible::CheckBox:
handleCheckBoxUpdate(event);
break;
+ case QAccessible::Switch:
+ handleSwitchUpdate(event);
+ break;
case QAccessible::EditableText:
handleLineEditUpdate(event);
break;
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h
index ee2be18e5b7..2b4716d64e7 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.h
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.h
@@ -81,6 +81,7 @@ private:
void handleStaticTextUpdate(QAccessibleEvent *event);
void handleButtonUpdate(QAccessibleEvent *event);
void handleCheckBoxUpdate(QAccessibleEvent *event);
+ void handleSwitchUpdate(QAccessibleEvent *event);
void handleDialogUpdate(QAccessibleEvent *event);
void handleMenuUpdate(QAccessibleEvent *event);
void handleToolUpdate(QAccessibleEvent *event);
diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
index a1a173f0182..17422bd606d 100644
--- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
+++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp
@@ -201,7 +201,7 @@ void QWaylandXdgSurface::Toplevel::requestWindowFlags(Qt::WindowFlags flags)
delete m_decoration;
m_decoration = nullptr;
} else {
- m_decoration->unsetMode();
+ m_decoration->requestMode(QWaylandXdgToplevelDecorationV1::mode_server_side);
}
}
}
@@ -697,108 +697,135 @@ void QWaylandXdgSurface::setWindowPosition(const QPoint &position)
window()->updateExposure();
}
+static QtWayland::xdg_positioner::gravity gravityFromEdge(Qt::Edges edges)
+{
+ switch (edges) {
+ case Qt::Edges():
+ return QtWayland::xdg_positioner::gravity_none;
+ case Qt::TopEdge:
+ return QtWayland::xdg_positioner::gravity_top;
+ case Qt::TopEdge | Qt::RightEdge:
+ return QtWayland::xdg_positioner::gravity_top_right;
+ case Qt::RightEdge:
+ return QtWayland::xdg_positioner::gravity_right;
+ case Qt::BottomEdge | Qt::RightEdge:
+ return QtWayland::xdg_positioner::gravity_bottom_right;
+ case Qt::BottomEdge:
+ return QtWayland::xdg_positioner::gravity_bottom;
+ case Qt::BottomEdge | Qt::LeftEdge:
+ return QtWayland::xdg_positioner::gravity_bottom_left;
+ case Qt::LeftEdge:
+ return QtWayland::xdg_positioner::gravity_left;
+ case Qt::TopEdge | Qt::LeftEdge:
+ return QtWayland::xdg_positioner::gravity_top_left;
+ }
+ qCWarning(lcQpaWayland) << "Cannot map positioner gravity " << edges;
+ return QtWayland::xdg_positioner::gravity_none;
+}
+
+static QtWayland::xdg_positioner::anchor anchorFromEdge(Qt::Edges edges)
+{
+ switch (edges) {
+ case Qt::Edges():
+ return QtWayland::xdg_positioner::anchor_none;
+ case Qt::TopEdge:
+ return QtWayland::xdg_positioner::anchor_top;
+ case Qt::TopEdge | Qt::RightEdge:
+ return QtWayland::xdg_positioner::anchor_top_right;
+ case Qt::RightEdge:
+ return QtWayland::xdg_positioner::anchor_right;
+ case Qt::BottomEdge | Qt::RightEdge:
+ return QtWayland::xdg_positioner::anchor_bottom_right;
+ case Qt::BottomEdge:
+ return QtWayland::xdg_positioner::anchor_bottom;
+ case Qt::BottomEdge | Qt::LeftEdge:
+ return QtWayland::xdg_positioner::anchor_bottom_left;
+ case Qt::LeftEdge:
+ return QtWayland::xdg_positioner::anchor_left;
+ case Qt::TopEdge | Qt::LeftEdge:
+ return QtWayland::xdg_positioner::anchor_top_left;
+ }
+ qCWarning(lcQpaWayland) << "Cannot map positioner anchor" << edges;
+ return QtWayland::xdg_positioner::anchor_none;
+}
+
std::unique_ptr<QWaylandXdgSurface::Positioner> QWaylandXdgSurface::createPositioner(QWaylandWindow *parent)
{
std::unique_ptr<Positioner> positioner(new Positioner(m_shell));
- // set_popup expects a position relative to the parent
- QRect windowGeometry = m_window->windowContentGeometry();
- QMargins windowMargins = m_window->windowContentMargins() - m_window->clientSideMargins();
- QMargins parentMargins = parent->windowContentMargins() - parent->clientSideMargins();
- // These property overrides may be removed when public API becomes available
- QRect placementAnchor = m_window->window()->property("_q_waylandPopupAnchorRect").toRect();
- if (!placementAnchor.isValid()) {
- placementAnchor = QRect(m_window->geometry().topLeft() - parent->geometry().topLeft(), QSize(1,1));
- }
- placementAnchor.translate(windowMargins.left(), windowMargins.top());
- placementAnchor.translate(-parentMargins.left(), -parentMargins.top());
+ // Default case, map the guessed global position to a relative position
+ QRect placementAnchor = QRect(m_window->geometry().topLeft() - parent->geometry().topLeft(), QSize(1,1));
+ Qt::Edges anchor = Qt::TopEdge | Qt::RightEdge;
+ Qt::Edges gravity = Qt::BottomEdge | Qt::RightEdge;
+ uint32_t constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_slide_x | QtWayland::xdg_positioner::constraint_adjustment_slide_y;
- uint32_t anchor = QtWayland::xdg_positioner::anchor_top_left;
+ // Override from window type
+ if (m_window->parentControlGeometry().isValid())
+ placementAnchor = m_window->parentControlGeometry();
+
+ switch (m_window->extendedWindowType()) {
+ case QNativeInterface::Private::QWaylandWindow::Menu:
+ case QNativeInterface::Private::QWaylandWindow::WindowType::ComboBox:
+ anchor = Qt::BottomEdge | Qt::LeftEdge;
+ gravity = Qt::BottomEdge | Qt::RightEdge;
+ constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_slide_x |
+ QtWayland::xdg_positioner::constraint_adjustment_flip_y | QtWayland::xdg_positioner::constraint_adjustment_slide_y;
+ break;
+ case QNativeInterface::Private::QWaylandWindow::SubMenu:
+ anchor = Qt::TopEdge | Qt::RightEdge;
+ gravity = Qt::BottomEdge | Qt::RightEdge;
+ constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_flip_x |
+ QtWayland::xdg_positioner::constraint_adjustment_slide_y;
+ break;
+ case QNativeInterface::Private::QWaylandWindow::ToolTip:
+ anchor = Qt::BottomEdge | Qt::RightEdge;
+ gravity = Qt::BottomEdge | Qt::RightEdge;
+ constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_flip_x | QtWayland::xdg_positioner::constraint_adjustment_slide_x |
+ QtWayland::xdg_positioner::constraint_adjustment_flip_y | QtWayland::xdg_positioner::constraint_adjustment_slide_y;
+ break;
+ default:
+ break;
+ }
+
+ if (qApp->layoutDirection() == Qt::RightToLeft) {
+ if (anchor & (Qt::RightEdge | Qt::LeftEdge))
+ anchor ^= (Qt::RightEdge | Qt::LeftEdge);
+ if (gravity & (Qt::RightEdge | Qt::LeftEdge))
+ gravity ^= (Qt::RightEdge | Qt::LeftEdge);
+ }
+
+ // Override with properties fauxAPI
+ const QVariant placementAnchorVariant = m_window->window()->property("_q_waylandPopupAnchorRect");
+ if (placementAnchorVariant.isValid())
+ placementAnchor = placementAnchorVariant.toRect();
const QVariant anchorVariant = m_window->window()->property("_q_waylandPopupAnchor");
- if (anchorVariant.isValid()) {
- switch (anchorVariant.value<Qt::Edges>()) {
- case Qt::Edges():
- anchor = QtWayland::xdg_positioner::anchor_none;
- break;
- case Qt::TopEdge:
- anchor = QtWayland::xdg_positioner::anchor_top;
- break;
- case Qt::TopEdge | Qt::RightEdge:
- anchor = QtWayland::xdg_positioner::anchor_top_right;
- break;
- case Qt::RightEdge:
- anchor = QtWayland::xdg_positioner::anchor_right;
- break;
- case Qt::BottomEdge | Qt::RightEdge:
- anchor = QtWayland::xdg_positioner::anchor_bottom_right;
- break;
- case Qt::BottomEdge:
- anchor = QtWayland::xdg_positioner::anchor_bottom;
- break;
- case Qt::BottomEdge | Qt::LeftEdge:
- anchor = QtWayland::xdg_positioner::anchor_bottom_left;
- break;
- case Qt::LeftEdge:
- anchor = QtWayland::xdg_positioner::anchor_left;
- break;
- case Qt::TopEdge | Qt::LeftEdge:
- anchor = QtWayland::xdg_positioner::anchor_top_left;
- break;
- }
- }
-
- uint32_t gravity = QtWayland::xdg_positioner::gravity_bottom_right;
+ if (anchorVariant.isValid())
+ anchor = anchorVariant.value<Qt::Edges>();
const QVariant popupGravityVariant = m_window->window()->property("_q_waylandPopupGravity");
- if (popupGravityVariant.isValid()) {
- switch (popupGravityVariant.value<Qt::Edges>()) {
- case Qt::Edges():
- gravity = QtWayland::xdg_positioner::gravity_none;
- break;
- case Qt::TopEdge:
- gravity = QtWayland::xdg_positioner::gravity_top;
- break;
- case Qt::TopEdge | Qt::RightEdge:
- gravity = QtWayland::xdg_positioner::gravity_top_right;
- break;
- case Qt::RightEdge:
- gravity = QtWayland::xdg_positioner::gravity_right;
- break;
- case Qt::BottomEdge | Qt::RightEdge:
- gravity = QtWayland::xdg_positioner::gravity_bottom_right;
- break;
- case Qt::BottomEdge:
- gravity = QtWayland::xdg_positioner::gravity_bottom;
- break;
- case Qt::BottomEdge | Qt::LeftEdge:
- gravity = QtWayland::xdg_positioner::gravity_bottom_left;
- break;
- case Qt::LeftEdge:
- gravity = QtWayland::xdg_positioner::gravity_left;
- break;
- case Qt::TopEdge | Qt::LeftEdge:
- gravity = QtWayland::xdg_positioner::gravity_top_left;
- break;
- }
- }
-
- uint32_t constraintAdjustment = QtWayland::xdg_positioner::constraint_adjustment_slide_x | QtWayland::xdg_positioner::constraint_adjustment_slide_y;
+ if (popupGravityVariant.isValid())
+ gravity = popupGravityVariant.value<Qt::Edges>();
const QVariant constraintAdjustmentVariant = m_window->window()->property("_q_waylandPopupConstraintAdjustment");
- if (constraintAdjustmentVariant.isValid()) {
+ if (constraintAdjustmentVariant.isValid())
constraintAdjustment = constraintAdjustmentVariant.toUInt();
- }
+
+ // set_popup expects a position relative to the parent
+ QRect windowGeometry = m_window->windowContentGeometry();
+ QMargins windowMargins = m_window->windowContentMargins() - m_window->clientSideMargins();
+ QMargins parentMargins = parent->windowContentMargins() - parent->clientSideMargins();
+ placementAnchor.translate(windowMargins.left(), windowMargins.top());
+ placementAnchor.translate(-parentMargins.left(), -parentMargins.top());
positioner->set_anchor_rect(placementAnchor.x(),
placementAnchor.y(),
placementAnchor.width(),
placementAnchor.height());
- positioner->set_anchor(anchor);
- positioner->set_gravity(gravity);
+ positioner->set_anchor(anchorFromEdge(anchor));
+ positioner->set_gravity(gravityFromEdge(gravity));
positioner->set_size(windowGeometry.width(), windowGeometry.height());
positioner->set_constraint_adjustment(constraintAdjustment);
return positioner;
}
-
void QWaylandXdgSurface::setIcon(const QIcon &icon)
{
if (!m_shell->m_topLevelIconManager || !m_toplevel)
diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp
index 7c300843518..be527b08f4d 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow.cpp
+++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp
@@ -481,8 +481,9 @@ void QWaylandWindow::setGeometry(const QRect &r)
if (mShellSurface && !mInResizeFromApplyConfigure) {
const QRect frameGeometry = r.marginsAdded(clientSideMargins()).marginsRemoved(windowContentMargins());
- if (qt_window_private(window())->positionAutomatic)
+ if (qt_window_private(window())->positionAutomatic || m_popupInfo.parentControlGeometry.isValid())
mShellSurface->setWindowSize(frameGeometry.size());
+
else
mShellSurface->setWindowGeometry(frameGeometry);
}
@@ -1945,6 +1946,27 @@ QString QWaylandWindow::sessionRestoreId() const
return mSessionRestoreId;
}
+void QWaylandWindow::setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::WindowType windowType) {
+ m_popupInfo.extendedWindowType = windowType;
+}
+
+QNativeInterface::Private::QWaylandWindow::WindowType QWaylandWindow::extendedWindowType() const
+{
+ return m_popupInfo.extendedWindowType;
+}
+
+void QWaylandWindow::setParentControlGeometry(const QRect &parentControlGeometry) {
+ m_popupInfo.parentControlGeometry = parentControlGeometry;
+ if (mExposed) {
+ mShellSurface->setWindowPosition(window()->position());
+ }
+}
+
+QRect QWaylandWindow::parentControlGeometry() const
+{
+ return m_popupInfo.parentControlGeometry;
+}
+
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h
index 854724daf82..d6b24d0569f 100644
--- a/src/plugins/platforms/wayland/qwaylandwindow_p.h
+++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h
@@ -255,6 +255,11 @@ public:
void setSessionRestoreId(const QString &role) override;
QString sessionRestoreId() const;
+ void setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::WindowType) override;
+ QNativeInterface::Private::QWaylandWindow::WindowType extendedWindowType() const;
+ void setParentControlGeometry(const QRect &parentAnchor) override;
+ QRect parentControlGeometry() const;
+
public Q_SLOTS:
void applyConfigure();
@@ -397,6 +402,11 @@ private:
void handleFrameCallback(struct ::wl_callback* callback);
const QPlatformWindow *lastParent = nullptr;
+ struct {
+ QRect parentControlGeometry;
+ QNativeInterface::Private::QWaylandWindow::WindowType extendedWindowType = QNativeInterface::Private::QWaylandWindow::Default;
+ } m_popupInfo;
+
static QWaylandWindow *mMouseGrab;
static QWaylandWindow *mTopPopup;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index fc0e053f396..0144786ce5e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -82,8 +82,9 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
if (event->changedStates().checked || event->changedStates().checkStateMixed) {
- // Notifies states changes in checkboxes.
- if (accessible->role() == QAccessible::CheckBox) {
+ // Notifies states changes in checkboxes and switches.
+ if (accessible->role() == QAccessible::CheckBox
+ || accessible->role() == QAccessible::Switch) {
if (auto provider = providerForAccessible(accessible)) {
long toggleState = ToggleState_Off;
if (accessible->state().checked)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index 4146a56b226..b2675d5b884 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -132,6 +132,7 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::EditableText, UIA_EditControlTypeId},
{QAccessible::Button, UIA_ButtonControlTypeId},
{QAccessible::CheckBox, UIA_CheckBoxControlTypeId},
+ {QAccessible::Switch, UIA_ButtonControlTypeId},
{QAccessible::RadioButton, UIA_RadioButtonControlTypeId},
{QAccessible::ComboBox, UIA_ComboBoxControlTypeId},
{QAccessible::ProgressBar, UIA_ProgressBarControlTypeId},
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 9cfd877d945..64af8c10fc1 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -68,6 +68,8 @@ bool Moc::parseClassHead(ClassDef *def)
const QByteArrayView lex = lexemView();
if (lex != "final" && lex != "sealed" && lex != "Q_DECL_FINAL")
name = lexem();
+ else
+ def->isFinal = true;
}
def->qualified += name;
@@ -85,6 +87,8 @@ bool Moc::parseClassHead(ClassDef *def)
const QByteArrayView lex = lexemView();
if (lex != "final" && lex != "sealed" && lex != "Q_DECL_FINAL")
return false;
+ else
+ def->isFinal = true;
}
if (test(COLON)) {
@@ -2055,6 +2059,8 @@ QJsonObject ClassDef::toJson() const
cls["className"_L1] = QString::fromUtf8(classname.constData());
cls["qualifiedClassName"_L1] = QString::fromUtf8(qualified.constData());
cls["lineNumber"_L1] = lineNumber;
+ if (isFinal)
+ cls["final"_L1] = true;
QJsonArray classInfos;
for (const auto &info: std::as_const(classInfoList)) {
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index bf55aa7c44f..aafa80d2164 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -207,6 +207,7 @@ struct ClassDef : BaseDef {
bool hasQGadget = false;
bool hasQNamespace = false;
bool requireCompleteMethodTypes = false;
+ bool isFinal = false;
QJsonObject toJson() const;
};
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index e4159ad2cf0..51aea4079a1 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3298,7 +3298,8 @@ void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
bool QAbstractItemView::isPersistentEditorOpen(const QModelIndex &index) const
{
Q_D(const QAbstractItemView);
- return d->editorForIndex(index).widget;
+ QWidget *editor = d->editorForIndex(index).widget;
+ return editor && d->persistent.contains(editor);
}
/*!
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 6fcfcf1b1ef..53ce4dd8211 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1432,8 +1432,8 @@ void QApplicationPrivate::notifyWindowIconChanged()
// in case there are any plain QWindows in this QApplication-using
// application, also send the notification to them
- for (int i = 0; i < windowList.size(); ++i)
- QCoreApplication::sendEvent(windowList.at(i), &ev);
+ for (QWindow *w : std::as_const(windowList))
+ QCoreApplication::sendEvent(w, &ev);
}
/*!
@@ -1774,9 +1774,9 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
// in case there are any plain QWindows in this QApplication-using
// application, also send the notification to them
- for (int i = 0; i < windowList.size(); ++i) {
+ for (QWindow *w: std::as_const(windowList)) {
QEvent ev(QEvent::ApplicationLayoutDirectionChange);
- QCoreApplication::sendEvent(windowList.at(i), &ev);
+ QCoreApplication::sendEvent(w, &ev);
}
}
@@ -1863,14 +1863,12 @@ void QApplicationPrivate::setActiveWindow(QWidget* act)
QEvent windowActivate(QEvent::WindowActivate);
QEvent windowDeactivate(QEvent::WindowDeactivate);
- for (int i = 0; i < toBeActivated.size(); ++i) {
- QWidget *w = toBeActivated.at(i);
+ for (QWidget *w : std::as_const(toBeActivated)) {
QApplication::sendSpontaneousEvent(w, &windowActivate);
QApplication::sendSpontaneousEvent(w, &activationChange);
}
- for(int i = 0; i < toBeDeactivated.size(); ++i) {
- QWidget *w = toBeDeactivated.at(i);
+ for (QWidget *w : std::as_const(toBeDeactivated)) {
QApplication::sendSpontaneousEvent(w, &windowDeactivate);
QApplication::sendSpontaneousEvent(w, &activationChange);
}
@@ -2082,8 +2080,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
}
QEvent leaveEvent(QEvent::Leave);
- for (int i = 0; i < leaveList.size(); ++i) {
- auto *w = leaveList.at(i);
+ for (QWidget *w : std::as_const(leaveList)) {
if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
QCoreApplication::sendEvent(w, &leaveEvent);
if (w->testAttribute(Qt::WA_Hover) &&
@@ -2125,8 +2122,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
// Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor.
// This is not required on Windows as the cursor is reset on every single mouse move.
QWidget *parentOfLeavingCursor = nullptr;
- for (int i = 0; i < leaveList.size(); ++i) {
- auto *w = leaveList.at(i);
+ for (QWidget *w : std::as_const(leaveList)) {
if (!isAlien(w))
break;
if (w->testAttribute(Qt::WA_SetCursor)) {
@@ -3085,7 +3081,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
const QPoint offset = w->pos();
w = w->parentWidget();
QMutableTouchEvent::setTarget(touchEvent, w);
- for (int i = 0; i < touchEvent->pointCount(); ++i) {
+ for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
auto &pt = touchEvent->point(i);
QMutableEventPoint::setPosition(pt, pt.position() + offset);
}
@@ -3164,8 +3160,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
res = d->notify_helper(w, &ge);
gestureEvent->m_spont = false;
eventAccepted = ge.isAccepted();
- for (int i = 0; i < gestures.size(); ++i) {
- QGesture *g = gestures.at(i);
+ for (QGesture *g : std::as_const(gestures)) {
// Ignore res [event return value] because handling of multiple gestures
// packed into a single QEvent depends on not consuming the event
if (eventAccepted || ge.isAccepted(g)) {
@@ -3708,7 +3703,7 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
{
bool containsPress = false;
- for (int i = 0; i < touchEvent->pointCount(); ++i) {
+ for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
auto &pt = touchEvent->point(i);
QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition()));
@@ -3768,7 +3763,7 @@ void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent
// If the widget dispatched the event further (see QGraphicsProxyWidget), then
// there might already be an implicit grabber. Don't override that. A widget that
// has partially recognized a gesture needs to grab all points.
- for (int i = 0; i < touchEvent->pointCount(); ++i) {
+ for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) {
auto &ep = touchEvent->point(i);
if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints))
QMutableEventPoint::setTarget(ep, widget);
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index 9e6aaf4b95f..d989feb7f91 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -20,6 +20,8 @@
#if QT_CONFIG(style_stylesheet)
#include <private/qstylesheetstyle_p.h>
#endif
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h>
#include <qlabel.h>
#include <QtWidgets/private/qlabel_p.h>
@@ -386,6 +388,17 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
p += offset;
+#if QT_CONFIG(wayland)
+ create();
+ if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(windowHandle()->handle())) {
+ // based on the existing code below, by default position at 'p' stored at the bottom right of our rect
+ // then flip to the other arbitrary 4x24 space if constrained
+ const QRect controlGeometry(QRect(p.x() - 4, p.y() - 24, 4, 24));
+ waylandWindow->setParentControlGeometry(controlGeometry);
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ToolTip);
+ }
+#endif
+
QRect screenRect = screen->geometry();
if (p.x() + this->width() > screenRect.x() + screenRect.width())
p.rx() -= 4 + this->width();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 36446c3e5c4..9499c88af12 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -13144,11 +13144,22 @@ int QWidget::metric(PaintDeviceMetric m) const
void QWidget::initPainter(QPainter *painter) const
{
const QPalette &pal = palette();
- painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1);
- painter->d_func()->state->bgBrush = pal.brush(backgroundRole());
+ QPainterPrivate *painterPrivate = QPainterPrivate::get(painter);
+
+ painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1);
+ painterPrivate->state->bgBrush = pal.brush(backgroundRole());
QFont f(font(), this);
- painter->d_func()->state->deviceFont = f;
- painter->d_func()->state->font = f;
+ painterPrivate->state->deviceFont = f;
+ painterPrivate->state->font = f;
+
+ painterPrivate->setEngineDirtyFlags({
+ QPaintEngine::DirtyPen,
+ QPaintEngine::DirtyBrush,
+ QPaintEngine::DirtyFont,
+ });
+
+ if (painterPrivate->extended)
+ painterPrivate->extended->penChanged();
}
/*!
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 737ccb0e807..622f1548756 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -591,6 +591,10 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
}
}
+ // Event delivery above might have destroyed this object. See QTBUG-138419.
+ if (self.isNull())
+ return;
+
if (QApplication::activePopupWidget() != activePopupWidget
&& QApplicationPrivate::replayMousePress
&& QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool()) {
diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp
index 220f600ea41..735b574d293 100644
--- a/src/widgets/util/qcompleter.cpp
+++ b/src/widgets/util/qcompleter.cpp
@@ -122,6 +122,8 @@
#include "QtGui/qevent.h"
#include <private/qapplication_p.h>
#include <private/qwidget_p.h>
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h>
#if QT_CONFIG(lineedit)
#include "QtWidgets/qlineedit.h"
#endif
@@ -925,10 +927,15 @@ void QCompleterPrivate::showPopup(const QRect& rect)
popup->setGeometry(pos.x(), pos.y(), w, h);
if (!popup->isVisible()) {
- // Make sure popup has a transient parent set, Wayland needs it. QTBUG-130474
- popup->winId(); // force creation of windowHandle
- popup->windowHandle()->setTransientParent(widget->window()->windowHandle());
-
+#if QT_CONFIG(wayland)
+ popup->createWinId();
+ if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(popup->windowHandle()->handle())) {
+ popup->windowHandle()->setTransientParent(widget->window()->windowHandle());
+ const QRect controlGeometry = QRect(widget->mapTo(widget->topLevelWidget(), QPoint(0,0)), widget->size());
+ waylandWindow->setParentControlGeometry(controlGeometry);
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ComboBox);
+ }
+#endif
popup->show();
}
}
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 6f25b8bde67..2f51b83a49d 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -7,6 +7,9 @@
#include <qstylepainter.h>
#include <qpa/qplatformtheme.h>
#include <qpa/qplatformmenu.h>
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h>
+
#include <qlineedit.h>
#include <qapplication.h>
#include <qlistview.h>
@@ -2868,6 +2871,17 @@ void QComboBox::showPopup()
container->hide();
}
}
+
+#if QT_CONFIG(wayland)
+ if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(container->windowHandle()->handle())) {
+ const QRect popup(style->subControlRect(QStyle::CC_ComboBox, &opt,
+ QStyle::SC_ComboBoxListBoxPopup, this));
+ const QRect controlGeometry = QRect(mapTo(window(), popup.topLeft()), popup.size());
+ waylandWindow->setParentControlGeometry(controlGeometry);
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ComboBox);
+ }
+#endif
+
container->show();
if (!neededHorizontalScrollBar && needHorizontalScrollBar()) {
listRect.adjust(0, 0, 0, sb->height());
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 5cda8f33f4c..7d4228709be 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -40,6 +40,8 @@
#include <private/qaction_p.h>
#include <private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformwindow.h>
+#include <qpa/qplatformwindow_p.h>
#include <private/qstyle_p.h>
QT_BEGIN_NAMESPACE
@@ -2535,6 +2537,23 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po
}
popupScreen = QGuiApplication::screenAt(pos);
q->setGeometry(QRect(pos, size));
+
+#if QT_CONFIG(wayland)
+ q->create();
+ if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(q->windowHandle()->handle())) {
+ if (causedButton) {
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::Menu);
+ waylandWindow->setParentControlGeometry(causedButton->geometry());
+ } else if (caused) {
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::SubMenu);
+ waylandWindow->setParentControlGeometry(caused->d_func()->actionRect(caused->d_func()->currentAction));
+ } else if (auto menubar = qobject_cast<QMenuBar*>(causedPopup.widget)) {
+ waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::Menu);
+ waylandWindow->setParentControlGeometry(menubar->actionGeometry(causedPopup.action));
+ }
+ }
+#endif
+
#if QT_CONFIG(effects)
int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll;
int vGuess = QEffects::DownScroll;
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index e6f7edc1ac1..01150cd39b2 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -58,7 +58,8 @@ public:
Qt::ArrowType arrowType;
Qt::ToolButtonStyle toolButtonStyle;
QToolButton::ToolButtonPopupMode popupMode;
- enum { NoButtonPressed=0, MenuButtonPressed=1, ToolButtonPressed=2 };
+ uint popupModeSetByUser : 1; // true if popupMode was set through setPopupMode
+ enum { NoButtonPressed = 0, MenuButtonPressed = 1, ToolButtonPressed = 2 };
uint buttonPressed : 2;
uint menuButtonDown : 1;
uint autoRaise : 1;
@@ -178,6 +179,7 @@ void QToolButtonPrivate::init()
arrowType = Qt::NoArrow;
menuButtonDown = false;
popupMode = QToolButton::DelayedPopup;
+ popupModeSetByUser = false;
buttonPressed = QToolButtonPrivate::NoButtonPressed;
toolButtonStyle = Qt::ToolButtonIconOnly;
@@ -827,7 +829,7 @@ void QToolButtonPrivate::onMenuTriggered(QAction *action)
void QToolButtonPrivate::onDefaultActionChanged()
{
Q_Q(QToolButton);
- if (defaultAction && defaultAction->menu())
+ if (defaultAction && defaultAction->menu() && !popupModeSetByUser)
q->setPopupMode(QToolButton::MenuButtonPopup);
}
@@ -864,6 +866,7 @@ void QToolButtonPrivate::onDefaultActionChanged()
void QToolButton::setPopupMode(ToolButtonPopupMode mode)
{
Q_D(QToolButton);
+ d->popupModeSetByUser = true;
d->popupMode = mode;
}
@@ -922,10 +925,11 @@ void QToolButton::setDefaultAction(QAction *action)
{
Q_D(QToolButton);
#if QT_CONFIG(menu)
- if (d->defaultAction) {
+ if (d->defaultAction && d->defaultAction != action) {
QObjectPrivate::disconnect(d->defaultAction, &QAction::changed, d,
&QToolButtonPrivate::onDefaultActionChanged);
}
+ const bool hadMenu = d->hasMenu();
#endif
d->defaultAction = action;
if (!action)
@@ -949,15 +953,18 @@ void QToolButton::setDefaultAction(QAction *action)
setWhatsThis(action->whatsThis());
#endif
#if QT_CONFIG(menu)
- if (action->menu()) {
+ if (!hadMenu && !d->popupModeSetByUser) {
// ### Qt7 Fixme
// new 'default' popup mode defined introduced by tool bar. We
// should have changed QToolButton's default instead. Do that
// in 4.2.
- setPopupMode(QToolButton::MenuButtonPopup);
+ if (action->menu()) {
+ setPopupMode(QToolButton::MenuButtonPopup);
+ } else {
+ QObjectPrivate::connect(d->defaultAction, &QAction::changed, d,
+ &QToolButtonPrivate::onDefaultActionChanged);
+ }
}
- QObjectPrivate::connect(d->defaultAction, &QAction::changed, d,
- &QToolButtonPrivate::onDefaultActionChanged);
#endif
setCheckable(action->isCheckable());
setChecked(action->isChecked());
diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
index d33f343045b..d2fee5124db 100644
--- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
+++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp
@@ -990,12 +990,6 @@ using ushort = unsigned short;
using uint = unsigned int;
using ulong = unsigned long;
-#if CHAR_MAX == 127 // char is signed
-SIGNED_TYPE_TEST(char, CHAR_MIN, CHAR_MAX)
-#else
-UNSIGNED_TYPE_TEST(char, CHAR_MAX)
-#endif
-
SIGNED_TYPE_TEST(schar, SCHAR_MIN, SCHAR_MAX)
UNSIGNED_TYPE_TEST(uchar, UCHAR_MAX)
diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json
index a0bca54df25..8f7757a7272 100644
--- a/tests/auto/tools/moc/allmocs_baseline_in.json
+++ b/tests/auto/tools/moc/allmocs_baseline_in.json
@@ -734,6 +734,7 @@
"classes": [
{
"className": "FinalTestClassQt",
+ "final": true,
"lineNumber": 15,
"object": true,
"qualifiedClassName": "FinalTestClassQt",
@@ -746,6 +747,7 @@
},
{
"className": "ExportedFinalTestClassQt",
+ "final": true,
"lineNumber": 24,
"object": true,
"qualifiedClassName": "ExportedFinalTestClassQt",
@@ -758,6 +760,7 @@
},
{
"className": "ExportedFinalTestClassQtX",
+ "final": true,
"lineNumber": 32,
"object": true,
"qualifiedClassName": "ExportedFinalTestClassQtX",
@@ -770,6 +773,7 @@
},
{
"className": "FinalTestClassCpp11",
+ "final": true,
"lineNumber": 40,
"object": true,
"qualifiedClassName": "FinalTestClassCpp11",
@@ -782,6 +786,7 @@
},
{
"className": "ExportedFinalTestClassCpp11",
+ "final": true,
"lineNumber": 48,
"object": true,
"qualifiedClassName": "ExportedFinalTestClassCpp11",
@@ -794,6 +799,7 @@
},
{
"className": "ExportedFinalTestClassCpp11X",
+ "final": true,
"lineNumber": 56,
"object": true,
"qualifiedClassName": "ExportedFinalTestClassCpp11X",
@@ -806,6 +812,7 @@
},
{
"className": "SealedTestClass",
+ "final": true,
"lineNumber": 64,
"object": true,
"qualifiedClassName": "SealedTestClass",
@@ -818,6 +825,7 @@
},
{
"className": "ExportedSealedTestClass",
+ "final": true,
"lineNumber": 72,
"object": true,
"qualifiedClassName": "ExportedSealedTestClass",
@@ -830,6 +838,7 @@
},
{
"className": "ExportedSealedTestClassX",
+ "final": true,
"lineNumber": 80,
"object": true,
"qualifiedClassName": "ExportedSealedTestClassX",
diff --git a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
index 5ee85694406..65ac08f5069 100644
--- a/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
+++ b/tests/auto/wayland/xdgdecorationv1/tst_xdgdecorationv1.cpp
@@ -149,7 +149,7 @@ void tst_xdgdecorationv1::clientSidePreferredByCompositor()
QVERIFY(window.frameMargins().isNull());
QCOMPOSITOR_TRY_VERIFY(xdgToplevel());
- QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_unsetModeRequested);
+ QCOMPOSITOR_TRY_VERIFY(toplevelDecoration()->m_requestedMode == XdgToplevelDecorationV1::mode_server_side);
QVERIFY(window.frameMargins().isNull()); // We're still waiting for a configure
exec([&] {
toplevelDecoration()->sendConfigure(XdgToplevelDecorationV1::mode_client_side);
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 805fa046a07..3e5c65cf0be 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -156,6 +156,7 @@ private slots:
void removeIndexWhileEditing();
void focusNextOnHide();
void shiftSelectionAfterModelSetCurrentIndex();
+ void QTBUG72333_isPersistentEditorOpen();
private:
static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr)
@@ -3604,5 +3605,29 @@ void tst_QAbstractItemView::shiftSelectionAfterModelSetCurrentIndex()
QCOMPARE(selection.first().bottom(), 2);
}
+void tst_QAbstractItemView::QTBUG72333_isPersistentEditorOpen()
+{
+ QStandardItemModel model(1, 1);
+ model.setData(model.index(0, 0), QStringLiteral("Test"));
+
+ QTableView view;
+ view.setModel(&model);
+ view.show();
+
+ const QModelIndex index = model.index(0, 0);
+
+ view.edit(index);
+ QVERIFY(view.state() == QAbstractItemView::EditingState);
+ QVERIFY(!view.isPersistentEditorOpen(index));
+
+ view.closeEditor(view.indexWidget(index), QAbstractItemDelegate::RevertModelCache);
+
+ view.openPersistentEditor(index);
+ QVERIFY(view.isPersistentEditorOpen(index));
+
+ view.closePersistentEditor(index);
+ QVERIFY(!view.isPersistentEditorOpen(index));
+}
+
QTEST_MAIN(tst_QAbstractItemView)
#include "tst_qabstractitemview.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 72f5ada4889..8e46876934d 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -11280,7 +11280,7 @@ void tst_QWidget::destroyBackingStore()
#endif // QT_BUILD_INTERNAL
// Helper function
-QWidgetRepaintManager* repaintManager(QWidget &widget)
+QWidgetRepaintManager* repaintManager([[maybe_unused]] QWidget &widget)
{
QWidgetRepaintManager *repaintManager = nullptr;
#ifdef QT_BUILD_INTERNAL
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index c6bebe55f23..8f5fd72610a 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -5096,9 +5096,6 @@ void tst_QLineEdit::testQuickSelectionWithMouse()
QVERIFY(lineEdit.selectedText().endsWith(suffix));
QTest::mouseMove(lineEdit.windowHandle(), center + QPoint(20, 0));
qCDebug(lcTests) << "Selected text:" << lineEdit.selectedText();
-#if defined(Q_PROCESSOR_ARM_32) && !defined(Q_OS_VXWORKS)
- QEXPECT_FAIL("", "Currently fails on gcc-armv7, needs investigation.", Continue);
-#endif
QCOMPARE(lineEdit.selectedText(), partialSelection);
mouseReleaseIfNeeded(center + QPoint(20, 0));
diff --git a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
index 9588f193387..8721a0a1657 100644
--- a/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
+++ b/tests/auto/widgets/widgets/qtoolbutton/tst_qtoolbutton.cpp
@@ -36,6 +36,7 @@ private slots:
void defaultActionSynced();
void deleteInHandler();
void emptyMenu();
+ void popupMode();
protected slots:
void sendMouseClick();
@@ -361,5 +362,78 @@ void tst_QToolButton::emptyMenu()
QTRY_COMPARE(triggeredSpy.size(), 1);
}
+void tst_QToolButton::popupMode()
+{
+ {
+ // action without menu -> no change in popup mode
+ QToolButton tb;
+ QCOMPARE(tb.popupMode(), QToolButton::DelayedPopup); // ### Qt7 change to MenuButtonPopup
+ auto a = new QAction("Action 1");
+ tb.setDefaultAction(a);
+ QCOMPARE(tb.popupMode(), QToolButton::DelayedPopup);
+ }
+ {
+ // action with menu, no user-set popup mode -> MenuButtonPopup
+ QToolButton tb;
+ auto a = new QAction("Action 1");
+ auto menu = new QMenu;
+ menu->addAction("Menuaction");
+ a->setMenu(menu); // before setDefaultAction
+ tb.setDefaultAction(a);
+ QCOMPARE(tb.popupMode(), QToolButton::MenuButtonPopup);
+ tb.setPopupMode(QToolButton::InstantPopup);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ }
+ {
+ // action with menu, no user-set popup mode -> MenuButtonPopup
+ QToolButton tb;
+ auto a = new QAction("Action 1");
+ auto menu = new QMenu;
+ menu->addAction("Menuaction");
+ tb.setDefaultAction(a);
+ a->setMenu(menu); // after setDefaultAction
+ QCOMPARE(tb.popupMode(), QToolButton::MenuButtonPopup);
+ tb.setPopupMode(QToolButton::InstantPopup);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ }
+ {
+ // action without (initial) menu, user-set popup mode is not changed
+ QToolButton tb;
+ auto a = new QAction("Action 1");
+ auto menu = new QMenu;
+ menu->addAction("Menuaction");
+ tb.setDefaultAction(a);
+ tb.setPopupMode(QToolButton::InstantPopup);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ a->setMenu(menu);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ }
+ {
+ // action with menu but after user-set popup mode -> popup mode is not changed
+ QToolButton tb;
+ auto a = new QAction("Action 1");
+ auto menu = new QMenu;
+ menu->addAction("Menuaction");
+ tb.setPopupMode(QToolButton::InstantPopup);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ a->setMenu(menu); // before setDefaultAction
+ tb.setDefaultAction(a);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ }
+ {
+ // action with menu but after user-set popup mode -> popup mode is not changed
+ QToolButton tb;
+ auto a = new QAction("Action 1");
+ auto menu = new QMenu;
+ menu->addAction("Menuaction");
+ tb.setPopupMode(QToolButton::InstantPopup);
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ tb.setDefaultAction(a);
+ a->setMenu(menu); // after setDefaultAction
+ QCOMPARE(tb.popupMode(), QToolButton::InstantPopup);
+ }
+}
+
+
QTEST_MAIN(tst_QToolButton)
#include "tst_qtoolbutton.moc"
diff --git a/util/unicode/main.cpp b/util/unicode/main.cpp
index ffd7d185905..1f31febeaaf 100644
--- a/util/unicode/main.cpp
+++ b/util/unicode/main.cpp
@@ -3365,11 +3365,13 @@ int main(int, char **)
QByteArray normalizationCorrections = createNormalizationCorrections();
QByteArray idnaMapping = createIdnaMapping();
+ # REUSE-IgnoreStart
QByteArray header =
"// Copyright (C) 2020 The Qt Company Ltd.\n"
"// SPDX-License-Identifier: Unicode-3.0\n"
"// Qt-Security score:significant reason:default\n"
"\n";
+ # REUSE-IgnoreEnd
QByteArray note =
"/* This file is autogenerated from the Unicode " DATA_VERSION_S " database. Do not edit */\n\n";
diff --git a/util/xkbdatagen/main.cpp b/util/xkbdatagen/main.cpp
index 6dfd765e392..4c9227816b1 100644
--- a/util/xkbdatagen/main.cpp
+++ b/util/xkbdatagen/main.cpp
@@ -374,13 +374,14 @@ int main(int argc, char **argv)
}
QList<XKBLayout> layouts = findLayouts(layoutList);
-
+ # REUSE-IgnoreStart
// copyright and stuff
printf("// Copyright (C) 2016 The Qt Company Ltd.\n"
"// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only\n"
"// This file is auto-generated, do not edit!\n"
"// (Generated using util/xkbdatagen)\n"
"\n");
+ # REUSE-IgnoreEnd
// data structure
printf("static struct {\n"