summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/CMakeLists.txt4
-rw-r--r--src/plugins/platforms/android/CMakeLists.txt5
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp130
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm18
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp209
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h3
15 files changed, 253 insertions, 165 deletions
diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt
index f30c27c24be..498a0772bc9 100644
--- a/src/plugins/platforms/CMakeLists.txt
+++ b/src/plugins/platforms/CMakeLists.txt
@@ -4,10 +4,10 @@
if(ANDROID)
add_subdirectory(android)
endif()
-if(NOT ANDROID AND NOT WASM)
+if(NOT WASM)
add_subdirectory(minimal)
endif()
-if(QT_FEATURE_freetype AND NOT ANDROID AND NOT WASM)
+if(QT_FEATURE_freetype AND NOT WASM)
add_subdirectory(offscreen)
endif()
if(QT_FEATURE_xcb)
diff --git a/src/plugins/platforms/android/CMakeLists.txt b/src/plugins/platforms/android/CMakeLists.txt
index 0160e12c26c..0d2a048abde 100644
--- a/src/plugins/platforms/android/CMakeLists.txt
+++ b/src/plugins/platforms/android/CMakeLists.txt
@@ -51,7 +51,12 @@ qt_internal_add_plugin(QAndroidIntegrationPlugin
qandroidplatformdialoghelpers.cpp
# Conflicting JNI classes, and types
androidcontentfileengine.cpp
+ qandroidplatformforeignwindow.cpp
qandroidplatformintegration.cpp
+ qandroidplatformscreen.cpp
+ qandroidplatformservices.cpp
+ qandroidplatformwindow.cpp
+ qandroidsystemlocale.cpp
INCLUDE_DIRECTORIES
${CMAKE_CURRENT_SOURCE_DIR}
${QtBase_SOURCE_DIR}/src/3rdparty/android
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 200c2f7a47b..b3ff0a4f06e 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -28,6 +28,7 @@ using namespace Qt::StringLiterals;
namespace QtAndroidAccessibility
{
+ static jmethodID m_setClassNameMethodID = 0;
static jmethodID m_addActionMethodID = 0;
static jmethodID m_setCheckableMethodID = 0;
static jmethodID m_setCheckedMethodID = 0;
@@ -421,6 +422,130 @@ namespace QtAndroidAccessibility
return jstr;
}
+ static QString classNameForRole(QAccessible::Role role, QAccessible::State state) {
+ switch (role) {
+ case QAccessible::Role::Button:
+ 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");
+ }
+ case QAccessible::Role::CheckBox:
+ // As of android/accessibility/utils/Role.java::getRole a CheckBox
+ // is NOT android.widget.CheckBox
+ return QStringLiteral("android.widget.CompoundButton");
+ case QAccessible::Role::Clock:
+ return QStringLiteral("android.widget.TextClock");
+ case QAccessible::Role::ComboBox:
+ return QStringLiteral("android.widget.Spinner");
+ case QAccessible::Role::Graphic:
+ // QQuickImage does not provide this role it inherits Client from QQuickItem
+ return QStringLiteral("android.widget.ImageView");
+ case QAccessible::Role::Grouping:
+ return QStringLiteral("android.view.ViewGroup");
+ case QAccessible::Role::List:
+ // As of android/accessibility/utils/Role.java::getRole a List
+ // is NOT android.widget.ListView
+ return QStringLiteral("android.widget.AbsListView");
+ case QAccessible::Role::MenuItem:
+ return QStringLiteral("android.view.MenuItem");
+ case QAccessible::Role::PopupMenu:
+ return QStringLiteral("android.widget.PopupMenu");
+ case QAccessible::Role::Separator:
+ return QStringLiteral("android.widget.Space");
+ case QAccessible::Role::ToolBar:
+ return QStringLiteral("android.view.Toolbar");
+ case QAccessible::Role::Heading: [[fallthrough]];
+ case QAccessible::Role::StaticText:
+ // Heading vs. regular Text is finally determined by AccessibilityNodeInfo.isHeading()
+ return QStringLiteral("android.widget.TextView");
+ case QAccessible::Role::EditableText:
+ return QStringLiteral("android.widget.EditText");
+ case QAccessible::Role::RadioButton:
+ return QStringLiteral("android.widget.RadioButton");
+ case QAccessible::Role::ProgressBar:
+ return QStringLiteral("android.widget.ProgressBar");
+ // Range information need to be filled to announce percentages
+ case QAccessible::Role::SpinBox:
+ return QStringLiteral("android.widget.NumberPicker");
+ case QAccessible::Role::WebDocument:
+ return QStringLiteral("android.webkit.WebView");
+ case QAccessible::Role::Dialog:
+ return QStringLiteral("android.app.AlertDialog");
+ case QAccessible::Role::PageTab:
+ return QStringLiteral("android.app.ActionBar.Tab");
+ case QAccessible::Role::PageTabList:
+ return QStringLiteral("android.widget.TabWidget");
+ case QAccessible::Role::ScrollBar: [[fallthrough]];
+ case QAccessible::Role::Slider:
+ return QStringLiteral("android.widget.SeekBar");
+ case QAccessible::Role::Table:
+ // #TODO Evaluate the usage of AccessibleNodeInfo.setCollectionItemInfo() to provide
+ // infos about colums, rows und items.
+ return QStringLiteral("android.widget.GridView");
+ case QAccessible::Role::Pane:
+ // #TODO QQuickScrollView, QQuickListView (see QTBUG-137806)
+ return QStringLiteral("android.view.ViewGroup");
+ case QAccessible::Role::AlertMessage:
+ case QAccessible::Role::Animation:
+ case QAccessible::Role::Application:
+ case QAccessible::Role::Assistant:
+ case QAccessible::Role::BlockQuote:
+ case QAccessible::Role::Border:
+ case QAccessible::Role::ButtonDropGrid:
+ case QAccessible::Role::ButtonDropDown:
+ case QAccessible::Role::ButtonMenu:
+ case QAccessible::Role::Canvas:
+ case QAccessible::Role::Caret:
+ case QAccessible::Role::Cell:
+ case QAccessible::Role::Chart:
+ case QAccessible::Role::Client:
+ case QAccessible::Role::ColorChooser:
+ case QAccessible::Role::Column:
+ case QAccessible::Role::ColumnHeader:
+ case QAccessible::Role::ComplementaryContent:
+ case QAccessible::Role::Cursor:
+ case QAccessible::Role::Desktop:
+ case QAccessible::Role::Dial:
+ case QAccessible::Role::Document:
+ case QAccessible::Role::Equation:
+ case QAccessible::Role::Footer:
+ case QAccessible::Role::Form:
+ case QAccessible::Role::Grip:
+ case QAccessible::Role::HelpBalloon:
+ case QAccessible::Role::HotkeyField:
+ case QAccessible::Role::Indicator:
+ case QAccessible::Role::LayeredPane:
+ case QAccessible::Role::ListItem:
+ case QAccessible::Role::MenuBar:
+ case QAccessible::Role::NoRole:
+ case QAccessible::Role::Note:
+ case QAccessible::Role::Notification:
+ case QAccessible::Role::Paragraph:
+ case QAccessible::Role::PropertyPage:
+ case QAccessible::Role::Row:
+ case QAccessible::Role::RowHeader:
+ case QAccessible::Role::Section:
+ case QAccessible::Role::Sound:
+ case QAccessible::Role::Splitter:
+ case QAccessible::Role::StatusBar:
+ case QAccessible::Role::Terminal:
+ case QAccessible::Role::TitleBar:
+ case QAccessible::Role::ToolTip:
+ case QAccessible::Role::Tree:
+ case QAccessible::Role::TreeItem:
+ case QAccessible::Role::UserRole:
+ case QAccessible::Role::Whitespace:
+ case QAccessible::Role::Window:
+ // If unsure, every visible or interactive element in Android
+ // inherits android.view.View and by many extends also TextView.
+ // Android itself does a similar thing e.g. in its Settings-App.
+ return QStringLiteral("android.view.TextView");
+ }
+ }
+
static QString descriptionForInterface(QAccessibleInterface *iface)
{
QString desc;
@@ -513,6 +638,10 @@ namespace QtAndroidAccessibility
return false;
}
+ const QString role = classNameForRole(info.role, info.state);
+ jstring jrole = env->NewString((jchar*)role.constData(), (jsize)role.size());
+ env->CallVoidMethod(node, m_setClassNameMethodID, jrole);
+
const bool hasClickableAction =
info.actions.contains(QAccessibleActionInterface::pressAction()) ||
info.actions.contains(QAccessibleActionInterface::toggleAction());
@@ -590,6 +719,7 @@ namespace QtAndroidAccessibility
}
jclass nodeInfoClass = env->FindClass("android/view/accessibility/AccessibilityNodeInfo");
+ GET_AND_CHECK_STATIC_METHOD(m_setClassNameMethodID, nodeInfoClass, "setClassName", "(Ljava/lang/CharSequence;)V");
GET_AND_CHECK_STATIC_METHOD(m_addActionMethodID, nodeInfoClass, "addAction", "(I)V");
GET_AND_CHECK_STATIC_METHOD(m_setCheckableMethodID, nodeInfoClass, "setCheckable", "(Z)V");
GET_AND_CHECK_STATIC_METHOD(m_setCheckedMethodID, nodeInfoClass, "setChecked", "(Z)V");
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 71b6015a54d..79aed15a1d0 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -44,7 +44,8 @@ public:
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
- bool translucentBackground) override;
+ bool translucentBackground,
+ qreal sourceTransformFactor) override;
QImage toImage() const override;
QPlatformGraphicsBuffer *graphicsBuffer() const override;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 78d23b01dea..186aeaac44d 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -457,7 +457,8 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
- bool translucentBackground)
+ bool translucentBackground,
+ qreal sourceTransformFactor)
{
if (!m_buffers.back()) {
qCWarning(lcQpaBackingStore) << "Flush requested with no back buffer. Ignoring.";
@@ -466,7 +467,8 @@ QPlatformBackingStore::FlushResult QCALayerBackingStore::rhiFlush(QWindow *windo
finalizeBackBuffer();
- return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset, textures, translucentBackground);
+ return QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio,
+ region, offset, textures, translucentBackground, sourceTransformFactor);
}
QImage QCALayerBackingStore::toImage() const
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 36546879ae4..13139dd399d 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -43,6 +43,8 @@ public:
QFunctionPointer getProcAddress(const char *procName) override;
+ bool isSoftwareContext() const;
+
private:
static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format);
@@ -54,6 +56,7 @@ private:
QSurfaceFormat m_format;
QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers;
QAtomicInt m_needsUpdate = false;
+ bool m_isSoftwareContext = false;
#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug debug, const QCocoaGLContext *screen);
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index bfac716b633..2f0f513dfc1 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -289,6 +289,9 @@ void QCocoaGLContext::updateSurfaceFormat()
else
m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
+ m_isSoftwareContext = (pixelFormatAttribute(NSOpenGLPFARendererID)
+ & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID;
+
// ------------------- Query the context -------------------
auto glContextParameter = [&](NSOpenGLContextParameter parameter) {
@@ -512,6 +515,11 @@ bool QCocoaGLContext::isSharing() const
return m_shareContext != nil;
}
+bool QCocoaGLContext::isSoftwareContext() const
+{
+ return m_isSoftwareContext;
+}
+
NSOpenGLContext *QCocoaGLContext::nativeContext() const
{
return m_context;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 8c6dcfd4f60..4c5975af34a 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -232,6 +232,24 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
// layer-backed.
return false;
case OpenGL:
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSSonoma) {
+ // Tahoe has issues with software-backed GL, crashing in common operations
+ static bool isSoftwareContext = []{
+ QOpenGLContext context;
+ context.create();
+ auto *cocoaContext = static_cast<QCocoaGLContext*>(context.handle());
+ if (cocoaContext->isSoftwareContext()) {
+ qWarning() << "Detected software OpenGL backend,"
+ << "which is known to be broken on"
+ << qUtf8Printable(QSysInfo::prettyProductName());
+ return true;
+ } else {
+ return false;
+ }
+ }();
+ return !isSoftwareContext;
+ }
+ Q_FALLTHROUGH();
case BufferQueueingOpenGL:
#endif
case ThreadedPixmaps:
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index 9f19e649f85..59265daa127 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -10,6 +10,7 @@
#include <private/qeglfskmsintegration_p.h>
#include <QtCore/QLoggingCategory>
+#include <QtCore/qtimer.h>
#include <QtCore/private/qcore_unix_p.h>
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 38b3bdadd35..a407cde2a7c 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -1156,9 +1156,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::MoveEvent:
platformWindow->handleMoved();
return true;
- case QtWindows::ResizeEvent:
+ case QtWindows::ResizeEvent: {
+ QWindow *window = platformWindow->window();
platformWindow->handleResized(static_cast<int>(wParam), lParam);
+ if (window->flags().testFlags(Qt::ExpandedClientAreaHint))
+ platformWindow->updateCustomTitlebar();
return true;
+ }
case QtWindows::QuerySizeHints:
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
return true;// maybe available on some SDKs revisit WM_NCCALCSIZE
@@ -1174,8 +1178,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return platformWindow->handleNonClientActivate(result);
case QtWindows::GeometryChangingEvent:
return platformWindow->handleGeometryChanging(&msg);
- case QtWindows::ExposeEvent:
+ case QtWindows::ExposeEvent: {
+ QWindow *window = platformWindow->window();
+ if (window->flags().testFlags(Qt::ExpandedClientAreaHint))
+ platformWindow->updateCustomTitlebar();
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
+ }
case QtWindows::NonClientMouseEvent:
if (!platformWindow->frameStrutEventsEnabled())
break;
@@ -1219,6 +1227,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus)
return false;
+ [[fallthrough]];
case QtWindows::FocusOutEvent:
handleFocusEvent(et, platformWindow);
return true;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 25c15861ba1..0f66193f47d 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -262,6 +262,11 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
#ifndef QT_NO_OPENGL
case OpenGL:
+#if !QT_CONFIG(run_opengl_tests)
+ // Workaround for build configs on WoA that don't have OpenGL installed
+ // FIXME: Detect at runtime
+ return false;
+#endif
return true;
case ThreadedOpenGL:
if (const QWindowsStaticOpenGLContext *glContext = QWindowsIntegration::staticOpenGLContext())
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 81a3f1d37b7..731673b61db 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -284,40 +284,6 @@ static inline RECT RECTfromQRect(const QRect &rect)
return result;
}
-static LRESULT WINAPI WndProcTitleBar(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- HWND parentHwnd = reinterpret_cast<HWND>(GetWindowLongPtr(hwnd, GWL_HWNDPARENT));
- QWindowsWindow* platformWindow = QWindowsContext::instance()->findPlatformWindow(parentHwnd);
-
- switch (message) {
- case WM_SHOWWINDOW:
- ShowWindow(hwnd,SW_HIDE);
- if ((BOOL)wParam == TRUE)
- platformWindow->transitionAnimatedCustomTitleBar();
- return 0;
- case WM_SIZE: {
- if (platformWindow)
- platformWindow->updateCustomTitlebar();
- break;
- }
- case WM_NCHITTEST:
- return HTTRANSPARENT;
- case WM_TIMER:
- ShowWindow(hwnd, SW_SHOWNOACTIVATE);
- platformWindow->updateCustomTitlebar();
- break;
- case WM_PAINT:
- {
- PAINTSTRUCT ps;
- BeginPaint(hwnd, &ps);
- EndPaint(hwnd, &ps);
- return 0;
- }
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const RECT &r)
{
@@ -917,7 +883,7 @@ QWindowsWindowData
const auto appinst = reinterpret_cast<HINSTANCE>(GetModuleHandle(nullptr));
const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w);
- const QString windowTitlebarName = QWindowsContext::instance()->registerWindowClass(QStringLiteral("_q_titlebar"), WndProcTitleBar, CS_VREDRAW|CS_HREDRAW, nullptr, false);
+ const QString windowTitlebarName = QWindowsContext::instance()->registerWindowClass(QStringLiteral("_q_titlebar"), DefWindowProc, CS_VREDRAW|CS_HREDRAW, nullptr, false);
const QScreen *screen{};
const QRect rect = QPlatformWindow::initialGeometry(w, data.geometry,
@@ -970,15 +936,13 @@ QWindowsWindowData
context->frameWidth, context->frameHeight,
parentHandle, nullptr, appinst, nullptr);
- if (w->flags().testFlags(Qt::ExpandedClientAreaHint)) {
- const UINT dpi = ::GetDpiForWindow(result.hwnd);
- const int titleBarHeight = getTitleBarHeight_sys(dpi);
- result.hwndTitlebar = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT,
- classTitleBarNameUtf16, classTitleBarNameUtf16,
- WS_POPUP, 0, 0,
- context->frameWidth, titleBarHeight,
- result.hwnd, nullptr, appinst, nullptr);
- }
+ const UINT dpi = ::GetDpiForWindow(result.hwnd);
+ const int titleBarHeight = getTitleBarHeight_sys(dpi);
+ result.hwndTitlebar = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE,
+ classTitleBarNameUtf16, classTitleBarNameUtf16,
+ 0, 0, 0,
+ context->frameWidth, titleBarHeight,
+ nullptr, nullptr, appinst, nullptr);
qCDebug(lcQpaWindow).nospace()
<< "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
@@ -1056,6 +1020,9 @@ void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChang
if (flags & Qt::ExpandedClientAreaHint) { // Gives us the rounded corners looks and the frame shadow
MARGINS margins = { -1, -1, -1, -1 };
DwmExtendFrameIntoClientArea(hwnd, &margins);
+ } else {
+ MARGINS margins = { 0, 0, 0, 0 };
+ DwmExtendFrameIntoClientArea(hwnd, &margins);
}
} else { // child.
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags);
@@ -1191,19 +1158,26 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
bool QWindowsGeometryHint::handleCalculateSize(const QWindow *window, const QMargins &customMargins, const MSG &msg, LRESULT *result)
{
+ // Prevent adding any border for frameless window
+ if (msg.wParam && window->flags() & Qt::FramelessWindowHint) {
+ *result = 0;
+ return true;
+ }
+ const QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window);
+ // In case the platformwindow was not yet created, use the initial windowflags provided by the user.
+ const bool clientAreaExpanded = platformWindow != nullptr ? platformWindow->isClientAreaExpanded() : window->flags() & Qt::ExpandedClientAreaHint;
// Return 0 to remove the window's border
- const bool clientAreaExpanded = window->flags() & Qt::ExpandedClientAreaHint;
if (msg.wParam && clientAreaExpanded) {
// Prevent content from being cutoff by border for maximized, but not fullscreened windows.
- if (IsZoomed(msg.hwnd) && window->visibility() != QWindow::FullScreen) {
- auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
- RECT *clientArea = &ncp->rgrc[0];
- const int border = getResizeBorderThickness(QWindowsWindow::windowsWindowOf(window)->savedDpi());
+ const bool maximized = IsZoomed(msg.hwnd) && window->visibility() != QWindow::FullScreen;
+ auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
+ RECT *clientArea = &ncp->rgrc[0];
+ const int border = getResizeBorderThickness(96);
+ if (maximized)
clientArea->top += border;
- clientArea->bottom -= border;
- clientArea->left += border;
- clientArea->right -= border;
- }
+ clientArea->bottom -= border;
+ clientArea->left += border;
+ clientArea->right -= border;
*result = 0;
return true;
}
@@ -1623,6 +1597,12 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
#endif
{
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
+
+ if (aWindow->flags().testFlags(Qt::ExpandedClientAreaHint)) {
+ SetParent(m_data.hwndTitlebar, m_data.hwnd);
+ ShowWindow(m_data.hwndTitlebar, SW_SHOW);
+ }
+
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
return; // No further handling for Qt::Desktop
@@ -1847,21 +1827,6 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w)
return w;
}
-// Checks whether the Window is tiled with Aero snap
-bool QWindowsWindow::isWindowArranged(HWND hwnd)
-{
- typedef BOOL(WINAPI* PIsWindowArranged)(HWND);
- static PIsWindowArranged pIsWindowArranged = nullptr;
- static bool resolved = false;
- if (!resolved) {
- resolved = true;
- pIsWindowArranged = (PIsWindowArranged)QSystemLibrary::resolve(QLatin1String("user32.dll"), "IsWindowArranged");
- }
- if (pIsWindowArranged == nullptr)
- return false;
- return pIsWindowArranged(hwnd);
-}
-
QWindowsWindowData
QWindowsWindowData::create(const QWindow *w,
const QWindowsWindowData &parameters,
@@ -1903,13 +1868,6 @@ void QWindowsWindow::setVisible(bool visible)
fireExpose(QRegion());
}
}
- if (m_data.hwndTitlebar) {
- if (visible) {
- SetWindowPos(m_data.hwndTitlebar, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- } else {
- ShowWindow(m_data.hwndTitlebar, SW_HIDE);
- }
- }
}
bool QWindowsWindow::isVisible() const
@@ -2050,10 +2008,6 @@ void QWindowsWindow::show_sys() const
setFlag(WithinMaximize); // QTBUG-8361
ShowWindow(m_data.hwnd, sm);
- if (m_data.flags.testFlag(Qt::ExpandedClientAreaHint)) {
- ShowWindow(m_data.hwndTitlebar, sm);
- SetActiveWindow(m_data.hwnd);
- }
clearFlag(WithinMaximize);
@@ -2245,7 +2199,7 @@ QRect QWindowsWindow::normalGeometry() const
QMargins QWindowsWindow::safeAreaMargins() const
{
if (m_data.flags.testFlags(Qt::ExpandedClientAreaHint)) {
- const int titleBarHeight = getTitleBarHeight_sys(savedDpi());
+ const int titleBarHeight = getTitleBarHeight_sys(96);
return QMargins(0, titleBarHeight, 0, 0);
}
@@ -2457,15 +2411,9 @@ void QWindowsWindow::handleGeometryChange()
clearFlag(SynchronousGeometryChangeEvent);
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
- if (m_data.hwndTitlebar) {
- bool arranged = QWindowsWindow::isWindowArranged(m_data.hwnd);
- if (arranged || (m_windowWasArranged && !arranged))
- transitionAnimatedCustomTitleBar();
-
+ if (m_data.flags & Qt::ExpandedClientAreaHint) {
const int titleBarHeight = getTitleBarHeight_sys(savedDpi());
- MoveWindow(m_data.hwndTitlebar, m_data.geometry.x(), m_data.geometry.y(),
- m_data.geometry.width(), titleBarHeight, true);
- m_windowWasArranged = arranged;
+ MoveWindow(m_data.hwndTitlebar, 0, 0, m_data.geometry.width(), titleBarHeight, true);
}
}
@@ -2627,6 +2575,16 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
creationData.applyWindowFlags(m_data.hwnd);
creationData.initialize(window(), m_data.hwnd, true, m_opacity);
+ if (creationData.flags.testFlag(Qt::ExpandedClientAreaHint)) {
+ SetParent(m_data.hwndTitlebar, m_data.hwnd);
+ ShowWindow(m_data.hwndTitlebar, SW_SHOW);
+ } else {
+ if (IsWindowVisible(m_data.hwndTitlebar)) {
+ SetParent(m_data.hwndTitlebar, HWND_MESSAGE);
+ ShowWindow(m_data.hwndTitlebar, SW_HIDE);
+ }
+ }
+
QWindowsWindowData result = m_data;
result.flags = creationData.flags;
result.embedded = creationData.embedded;
@@ -2645,7 +2603,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
} else {
- transitionAnimatedCustomTitleBar();
+ updateCustomTitlebar();
if (state & Qt::WindowMaximized) {
WINDOWPLACEMENT windowPlacement{};
windowPlacement.length = sizeof(WINDOWPLACEMENT);
@@ -2743,20 +2701,6 @@ void QWindowsWindow::correctWindowPlacement(WINDOWPLACEMENT &windowPlacement)
}
}
-void QWindowsWindow::transitionAnimatedCustomTitleBar()
-{
- if (!m_data.hwndTitlebar)
- return;
- const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Control Panel\Desktop\WindowMetrics)");
- if (registry.isValid() && registry.value(LR"(MinAnimate)") == 1) {
- ShowWindow(m_data.hwndTitlebar, SW_HIDE);
- SetTimer(m_data.hwndTitlebar, 1, 200, nullptr);
- } else {
- ShowWindow(m_data.hwndTitlebar, SW_SHOWNOACTIVATE);
- updateCustomTitlebar();
- }
-}
-
void QWindowsWindow::updateRestoreGeometry()
{
m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
@@ -3078,7 +3022,8 @@ void QWindowsWindow::calculateFullFrameMargins()
const auto systemMargins = testFlag(DisableNonClientScaling)
? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd)
: frameMargins_sys();
- const QMargins actualMargins = systemMargins + customMargins();
+ const int extendedClientAreaBorder = window()->flags().testFlag(Qt::ExpandedClientAreaHint) ? qRound(QHighDpiScaling::factor(window())) * 2 : 0;
+ const QMargins actualMargins = systemMargins + customMargins() - extendedClientAreaBorder;
const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
const bool typicalFrame = (actualMargins.left() == actualMargins.right())
@@ -3517,19 +3462,6 @@ bool QWindowsWindow::handleNonClientActivate(LRESULT *result) const
return false;
}
-static void _q_drawCustomTitleBarButton(QPainter& p, const QRectF& r)
-{
- QPainterPath path(QPointF(r.x(), r.y()));
- QRectF rightCorner(r.x() + r.width() - 2.0, r.y() + 4.0, 2, 2);
- QRectF leftCorner(r.x(), r.y() + 4, 2, 2);
- path.lineTo(r.x() + r.width() - 5.0f, r.y());
- path.arcTo(rightCorner, 90, -90);
- path.lineTo(r.x() + r.width(), r.y() + r.height() - 1);
- path.lineTo(r.x(), r.y() + r.height() - 1);
- path.closeSubpath();
- p.drawPath(path);
-}
-
void QWindowsWindow::updateCustomTitlebar()
{
HWND hwnd = m_data.hwndTitlebar;
@@ -3545,7 +3477,7 @@ void QWindowsWindow::updateCustomTitlebar()
POINT localPos;
GetCursorPos(&localPos);
- MapWindowPoints(HWND_DESKTOP, hwnd, &localPos, 1);
+ MapWindowPoints(HWND_DESKTOP, m_data.hwnd, &localPos, 1);
const bool isDarkmode = QWindowsIntegration::instance()->darkModeHandling().testFlags(QWindowsApplication::DarkModeWindowFrames) &&
qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark;
@@ -3567,25 +3499,9 @@ void QWindowsWindow::updateCustomTitlebar()
p.setPen(Qt::NoPen);
if (!wnd->flags().testFlags(Qt::NoTitleBarBackgroundHint)) {
QRect titleRect;
- titleRect.setX(2);
titleRect.setWidth(windowWidth);
titleRect.setHeight(titleBarHeight);
-
- if (isWindows11orAbove) {
- QPainterPath path(QPointF(titleRect.x() + 4.0f, titleRect.y()));
- QRectF rightCorner(titleRect.x() + titleRect.width() - 4.0, titleRect.y() + 4.0, 2, 2);
- QRectF leftCorner(titleRect.x(), titleRect.y() + 4, 2, 2);
- path.lineTo(titleRect.x() + titleRect.width() - 7.0f, titleRect.y());
- path.arcTo(rightCorner, 90, -90);
- path.lineTo(titleRect.x() + titleRect.width() - 2.0, titleRect.y() + titleRect.height() - 1);
- path.lineTo(titleRect.x(), titleRect.y() + titleRect.height() - 1);
- path.lineTo(titleRect.x(), titleRect.y() + 4.0f);
- path.arcTo(leftCorner, -90, -90);
- path.closeSubpath();
- p.drawPath(path);
- } else {
- p.drawRect(titleRect);
- }
+ p.drawRect(titleRect);
}
if (wnd->flags().testFlags(Qt::WindowTitleHint | Qt::CustomizeWindowHint) || !wnd->flags().testFlag(Qt::CustomizeWindowHint)) {
@@ -3631,15 +3547,12 @@ void QWindowsWindow::updateCustomTitlebar()
QRectF rect;
rect.setY(1);
rect.setX(windowWidth - titleButtonWidth * buttons);
- rect.setWidth(titleButtonWidth - 1);
+ rect.setWidth(titleButtonWidth);
rect.setHeight(titleBarHeight);
if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
- if (isWindows11orAbove && buttons == 1)
- _q_drawCustomTitleBarButton(p, rect);
- else
- p.drawRect(rect);
+ p.drawRect(rect);
const QPen closeButtonHoveredPen = QPen(QColor(0xFF, 0xFF, 0xFD, 0xFF));
p.setPen(closeButtonHoveredPen);
} else {
@@ -3655,15 +3568,12 @@ void QWindowsWindow::updateCustomTitlebar()
QRectF rect;
rect.setY(1);
rect.setX(windowWidth - titleButtonWidth * buttons);
- rect.setWidth(titleButtonWidth - 1);
+ rect.setWidth(titleButtonWidth);
rect.setHeight(titleBarHeight);
if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
- if (isWindows11orAbove && buttons == 1)
- _q_drawCustomTitleBarButton(p, rect);
- else
- p.drawRect(rect);
+ p.drawRect(rect);
}
p.setPen(textPen);
p.drawText(rect,QStringLiteral("\uE922"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter));
@@ -3676,15 +3586,12 @@ void QWindowsWindow::updateCustomTitlebar()
QRectF rect;
rect.setY(1);
rect.setX(windowWidth - titleButtonWidth * buttons);
- rect.setWidth(titleButtonWidth - 1);
+ rect.setWidth(titleButtonWidth);
rect.setHeight(titleBarHeight);
if (localPos.x > (windowWidth - buttons * titleButtonWidth) &&
localPos.x < (windowWidth - (buttons - 1) * titleButtonWidth) &&
localPos.y > rect.y() && localPos.y < rect.y() + rect.height()) {
- if (isWindows11orAbove && buttons == 1)
- _q_drawCustomTitleBarButton(p, rect);
- else
- p.drawRect(rect);
+ p.drawRect(rect);
}
p.setPen(textPen);
p.drawText(rect,QStringLiteral("\uE921"), QTextOption(Qt::AlignVCenter | Qt::AlignHCenter));
@@ -3702,7 +3609,7 @@ void QWindowsWindow::updateCustomTitlebar()
BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
- POINT ptLocation = { windowRect.left, windowRect.top };
+ POINT ptLocation = { 0, 0 };
SIZE szWnd = { windowWidth, titleBarHeight };
POINT ptSrc = { 0, 0 };
UpdateLayeredWindow(hwnd, hdc, &ptLocation, &szWnd, memdc, &ptSrc, 0, &blend, ULW_ALPHA);
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index b67bd2850b3..a0e150aeb01 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -307,7 +307,6 @@ public:
static QWindow *topLevelOf(QWindow *w);
static inline void *userDataOf(HWND hwnd);
static inline void setUserDataOf(HWND hwnd, void *ud);
- static bool isWindowArranged(HWND hwnd);
static bool hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags);
static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity);
@@ -359,12 +358,10 @@ public:
int savedDpi() const { return m_savedDpi; }
qreal dpiRelativeScale(const UINT dpi) const;
- bool isFrameless() const { return m_data.flags.testFlag(Qt::FramelessWindowHint); }
+ bool isClientAreaExpanded() const { return m_data.flags.testFlag(Qt::ExpandedClientAreaHint); }
void requestUpdate() override;
- void transitionAnimatedCustomTitleBar();
-
private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 8353fac6a92..fda47944d9d 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -870,7 +870,8 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
- bool translucentBackground)
+ bool translucentBackground,
+ qreal sourceTransformFactor)
{
if (!m_image || m_image->size().isEmpty())
return FlushFailed;
@@ -878,7 +879,7 @@ QPlatformBackingStore::FlushResult QXcbBackingStore::rhiFlush(QWindow *window,
m_image->flushScrolledRegion(true);
auto result = QPlatformBackingStore::rhiFlush(window, sourceDevicePixelRatio, region, offset,
- textures, translucentBackground);
+ textures, translucentBackground, sourceTransformFactor);
if (result != FlushSuccess)
return result;
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index 674640780eb..5cda9e1ab79 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -27,7 +27,8 @@ public:
const QRegion &region,
const QPoint &offset,
QPlatformTextureList *textures,
- bool translucentBackground) override;
+ bool translucentBackground,
+ qreal sourceTransformFactor) override;
QImage toImage() const override;
QPlatformGraphicsBuffer *graphicsBuffer() const override;