summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/.prev_CMakeLists.txt24
-rw-r--r--src/plugins/platforms/cocoa/CMakeLists.txt24
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h11
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm30
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm83
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm23
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm39
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindowmanager.h63
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindowmanager.mm108
-rw-r--r--src/plugins/platforms/cocoa/qprintengine_mac.mm8
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp50
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h2
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp4
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp90
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h36
-rw-r--r--src/plugins/platforms/wasm/qwasmfontdatabase.cpp11
-rw-r--r--src/plugins/platforms/wasm/wasm.pro2
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h1
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp31
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp38
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbeventqueue.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
32 files changed, 522 insertions, 239 deletions
diff --git a/src/plugins/platforms/cocoa/.prev_CMakeLists.txt b/src/plugins/platforms/cocoa/.prev_CMakeLists.txt
index a8ee50e715..b8ab5af395 100644
--- a/src/plugins/platforms/cocoa/.prev_CMakeLists.txt
+++ b/src/plugins/platforms/cocoa/.prev_CMakeLists.txt
@@ -37,6 +37,7 @@ add_qt_plugin(qcocoa
qcocoasystemtrayicon.h qcocoasystemtrayicon.mm
qcocoatheme.h qcocoatheme.mm
qcocoawindow.h qcocoawindow.mm
+ qcocoawindowmanager.h qcocoawindowmanager.mm
qiosurfacegraphicsbuffer.h qiosurfacegraphicsbuffer.mm
qmacclipboard.h qmacclipboard.mm
qmultitouch_mac.mm qmultitouch_mac_p.h
@@ -71,14 +72,21 @@ add_qt_plugin(qcocoa
)
# Resources:
-add_qt_resource(qcocoa "qcocoaresources" PREFIX "/qt-project.org/mac/cursors" FILES
- images/sizeallcursor.png
- images/spincursor.png
- images/waitcursor.png)
+set(qcocoaresources_resource_files
+ "images/sizeallcursor.png"
+ "images/spincursor.png"
+ "images/waitcursor.png"
+)
+
+add_qt_resource(qcocoa "qcocoaresources"
+ PREFIX
+ "/qt-project.org/mac/cursors"
+ FILES
+ ${qcocoaresources_resource_files}
+)
#### Keys ignored in scope 1:.:.:cocoa.pro:<TRUE>:
-# CONFIG = "no_app_extension_api_only"
# OTHER_FILES = "cocoa.json"
# PLUGIN_CLASS_NAME = "QCocoaIntegrationPlugin"
# PLUGIN_TYPE = "platforms"
@@ -118,17 +126,17 @@ extend_target(qcocoa CONDITION TARGET Qt::Widgets
#### Keys ignored in scope 5:.:.:cocoa.pro:TARGET Qt::Widgets:
# QT_FOR_CONFIG = "widgets"
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_colordialog)
+extend_target(qcocoa CONDITION QT_FEATURE_colordialog AND TARGET Qt::Widgets
SOURCES
qcocoacolordialoghelper.h qcocoacolordialoghelper.mm
)
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_filedialog)
+extend_target(qcocoa CONDITION QT_FEATURE_filedialog AND TARGET Qt::Widgets
SOURCES
qcocoafiledialoghelper.h qcocoafiledialoghelper.mm
)
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_fontdialog)
+extend_target(qcocoa CONDITION QT_FEATURE_fontdialog AND TARGET Qt::Widgets
SOURCES
qcocoafontdialoghelper.h qcocoafontdialoghelper.mm
)
diff --git a/src/plugins/platforms/cocoa/CMakeLists.txt b/src/plugins/platforms/cocoa/CMakeLists.txt
index 9b546990ba..6bf0976224 100644
--- a/src/plugins/platforms/cocoa/CMakeLists.txt
+++ b/src/plugins/platforms/cocoa/CMakeLists.txt
@@ -41,6 +41,7 @@ add_qt_plugin(qcocoa
qcocoasystemtrayicon.h qcocoasystemtrayicon.mm
qcocoatheme.h qcocoatheme.mm
qcocoawindow.h qcocoawindow.mm
+ qcocoawindowmanager.h qcocoawindowmanager.mm
qiosurfacegraphicsbuffer.h qiosurfacegraphicsbuffer.mm
qmacclipboard.h qmacclipboard.mm
qmultitouch_mac.mm qmultitouch_mac_p.h
@@ -75,14 +76,21 @@ add_qt_plugin(qcocoa
)
# Resources:
-add_qt_resource(qcocoa "qcocoaresources" PREFIX "/qt-project.org/mac/cursors" FILES
- images/sizeallcursor.png
- images/spincursor.png
- images/waitcursor.png)
+set(qcocoaresources_resource_files
+ "images/sizeallcursor.png"
+ "images/spincursor.png"
+ "images/waitcursor.png"
+)
+
+add_qt_resource(qcocoa "qcocoaresources"
+ PREFIX
+ "/qt-project.org/mac/cursors"
+ FILES
+ ${qcocoaresources_resource_files}
+)
#### Keys ignored in scope 1:.:.:cocoa.pro:<TRUE>:
-# CONFIG = "no_app_extension_api_only"
# OTHER_FILES = "cocoa.json"
# PLUGIN_CLASS_NAME = "QCocoaIntegrationPlugin"
# PLUGIN_TYPE = "platforms"
@@ -122,17 +130,17 @@ extend_target(qcocoa CONDITION TARGET Qt::Widgets
#### Keys ignored in scope 5:.:.:cocoa.pro:TARGET Qt::Widgets:
# QT_FOR_CONFIG = "widgets"
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_colordialog)
+extend_target(qcocoa CONDITION QT_FEATURE_colordialog AND TARGET Qt::Widgets
SOURCES
qcocoacolordialoghelper.h qcocoacolordialoghelper.mm
)
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_filedialog)
+extend_target(qcocoa CONDITION QT_FEATURE_filedialog AND TARGET Qt::Widgets
SOURCES
qcocoafiledialoghelper.h qcocoafiledialoghelper.mm
)
-extend_target(qcocoa CONDITION (TARGET Qt::Widgets) AND (QT_FEATURE_fontdialog)
+extend_target(qcocoa CONDITION QT_FEATURE_fontdialog AND TARGET Qt::Widgets
SOURCES
qcocoafontdialoghelper.h qcocoafontdialoghelper.mm
)
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 083b7c1655..02e00039ae 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -6,6 +6,7 @@ SOURCES += main.mm \
qcocoatheme.mm \
qcocoabackingstore.mm \
qcocoawindow.mm \
+ qcocoawindowmanager.mm \
qnsview.mm \
qnswindow.mm \
qnswindowdelegate.mm \
@@ -41,6 +42,7 @@ HEADERS += qcocoaintegration.h \
qcocoatheme.h \
qcocoabackingstore.h \
qcocoawindow.h \
+ qcocoawindowmanager.h \
qnsview.h \
qnswindow.h \
qnswindowdelegate.h \
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 2398e6351e..9be6814ae7 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -49,7 +49,14 @@
QT_BEGIN_NAMESPACE
-class QNSWindowBackingStore : public QRasterBackingStore
+class QCocoaBackingStore : public QRasterBackingStore
+{
+protected:
+ QCocoaBackingStore(QWindow *window);
+ QCFType<CGColorSpaceRef> colorSpace() const;
+};
+
+class QNSWindowBackingStore : public QCocoaBackingStore
{
public:
QNSWindowBackingStore(QWindow *window);
@@ -64,7 +71,7 @@ private:
void redrawRoundedBottomCorners(CGRect) const;
};
-class QCALayerBackingStore : public QPlatformBackingStore
+class QCALayerBackingStore : public QCocoaBackingStore
{
public:
QCALayerBackingStore(QWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 01b4894324..6015257f4e 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -48,11 +48,24 @@
QT_BEGIN_NAMESPACE
-QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window)
+QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
: QRasterBackingStore(window)
{
}
+QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const
+{
+ NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
+ return QCFType<CGColorSpaceRef>::constructFromGet(view.window.colorSpace.CGColorSpace);
+}
+
+// ----------------------------------------------------------------------------
+
+QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window)
+ : QCocoaBackingStore(window)
+{
+}
+
QNSWindowBackingStore::~QNSWindowBackingStore()
{
}
@@ -175,11 +188,10 @@ void QNSWindowBackingStore::flush(QWindow *window, const QRegion &region, const
Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
"Focusing the view should give us a current graphics context");
- // Prevent potentially costly color conversion by assigning the display color space
- // to the backingstore image. This does not copy the underlying image data.
- CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace;
+ // Tag backingstore image with color space based on the window.
+ // Note: This does not copy the underlying image data.
QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace(
- QCFType<CGImageRef>(m_image.toCGImage()), displayColorSpace);
+ QCFType<CGImageRef>(m_image.toCGImage()), colorSpace());
// Create temporary image to use for blitting, without copying image data
NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
@@ -293,7 +305,7 @@ void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
// ----------------------------------------------------------------------------
QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
+ : QCocoaBackingStore(window)
{
qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window;
m_buffers.resize(1);
@@ -432,11 +444,7 @@ bool QCALayerBackingStore::recreateBackBufferIfNeeded()
<< "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio;
static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied);
-
- NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
- auto colorSpace = QCFType<CGColorSpaceRef>::constructFromGet(view.window.screen.colorSpace.CGColorSpace);
-
- m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace));
+ m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace()));
return true;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index c1041ac2da..bb309c0713 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -56,6 +56,8 @@ public:
QCocoaGLContext(QOpenGLContext *context);
~QCocoaGLContext();
+ void initialize() override;
+
bool makeCurrent(QPlatformSurface *surface) override;
void swapBuffers(QPlatformSurface *surface) override;
void doneCurrent() override;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index 0f8fec0548..7b124ea517 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -40,6 +40,8 @@
#include "qcocoaglcontext.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include "qcocoascreen.h"
+
#include <qdebug.h>
#include <QtPlatformHeaders/qcocoanativecontext.h>
#include <dlfcn.h>
@@ -53,32 +55,19 @@ static inline QByteArray getGlString(GLenum param)
return QByteArray();
}
-@implementation NSOpenGLPixelFormat (QtHelpers)
-- (GLint)qt_getAttribute:(NSOpenGLPixelFormatAttribute)attribute
-{
- int value = 0;
- [self getValues:&value forAttribute:attribute forVirtualScreen:0];
- return value;
-}
-@end
-
-@implementation NSOpenGLContext (QtHelpers)
-- (GLint)qt_getParameter:(NSOpenGLContextParameter)parameter
-{
- int value = 0;
- [self getValues:&value forParameter:parameter];
- return value;
-}
-@end
-
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaOpenGLContext, "qt.qpa.openglcontext", QtWarningMsg);
QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
- : QPlatformOpenGLContext(), m_format(context->format())
+ : QPlatformOpenGLContext()
+ , m_format(context->format())
+{
+}
+
+void QCocoaGLContext::initialize()
{
- QVariant nativeHandle = context->nativeHandle();
+ QVariant nativeHandle = context()->nativeHandle();
if (!nativeHandle.isNull()) {
if (!nativeHandle.canConvert<QCocoaNativeContext>()) {
qCWarning(lcQpaOpenGLContext, "QOpenGLContext native handle must be a QCocoaNativeContext");
@@ -95,7 +84,7 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
// Note: We have no way of knowing whether the NSOpenGLContext was created with the
// share context as reported by the QOpenGLContext, but we just have to trust that
// it was. It's okey, as the only thing we're using it for is to report isShared().
- if (QPlatformOpenGLContext *shareContext = context->shareHandle())
+ if (QPlatformOpenGLContext *shareContext = context()->shareHandle())
m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
updateSurfaceFormat();
@@ -110,7 +99,7 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
if (m_format.renderableType() != QSurfaceFormat::OpenGL)
return;
- if (QPlatformOpenGLContext *shareContext = context->shareHandle()) {
+ if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) {
m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
// Allow sharing between 3.2 Core and 4.1 Core profile versions in
@@ -150,6 +139,9 @@ QCocoaGLContext::QCocoaGLContext(QOpenGLContext *context)
return;
}
+ // The native handle should reflect the underlying context, even if we created it
+ context()->setNativeHandle(QVariant::fromValue<QCocoaNativeContext>(m_context));
+
// --------------------- Set NSOpenGLContext properties ---------------------
const GLint interval = m_format.swapInterval() >= 0 ? m_format.swapInterval() : 1;
@@ -285,7 +277,32 @@ void QCocoaGLContext::updateSurfaceFormat()
NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat;
- int colorSize = [pixelFormat qt_getAttribute:NSOpenGLPFAColorSize];
+ GLint virtualScreen = [&, this]() {
+ auto *platformScreen = static_cast<QCocoaScreen*>(context()->screen()->handle());
+ auto displayId = platformScreen->nativeScreen().qt_displayId;
+ auto requestedDisplay = CGDisplayIDToOpenGLDisplayMask(displayId);
+ for (int i = 0; i < pixelFormat.numberOfVirtualScreens; ++i) {
+ GLint supportedDisplays;
+ [pixelFormat getValues:&supportedDisplays forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:i];
+ // Note: The mask returned for NSOpenGLPFAScreenMask is a bit mask of
+ // physical displays that the renderer can drive, while the one returned
+ // from CGDisplayIDToOpenGLDisplayMask has a single bit set, representing
+ // that particular display.
+ if (requestedDisplay & supportedDisplays)
+ return i;
+ }
+ qCWarning(lcQpaOpenGLContext) << "Could not find virtual screen for"
+ << platformScreen << "with displayId" << displayId;
+ return 0;
+ }();
+
+ auto pixelFormatAttribute = [&](NSOpenGLPixelFormatAttribute attribute) {
+ int value = 0;
+ [pixelFormat getValues:&value forAttribute:attribute forVirtualScreen:virtualScreen];
+ return value;
+ };
+
+ int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize);
colorSize /= 4; // The attribute includes the alpha component
m_format.setRedBufferSize(colorSize);
m_format.setGreenBufferSize(colorSize);
@@ -297,22 +314,28 @@ void QCocoaGLContext::updateSurfaceFormat()
// size, as that will make the user believe the alpha channel can be used for
// something useful, when in reality it can't, due to the surface being opaque.
if (m_format.alphaBufferSize() > 0)
- m_format.setAlphaBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAAlphaSize]);
+ m_format.setAlphaBufferSize(pixelFormatAttribute(NSOpenGLPFAAlphaSize));
- m_format.setDepthBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFADepthSize]);
- m_format.setStencilBufferSize([pixelFormat qt_getAttribute:NSOpenGLPFAStencilSize]);
- m_format.setSamples([pixelFormat qt_getAttribute:NSOpenGLPFASamples]);
+ m_format.setDepthBufferSize(pixelFormatAttribute(NSOpenGLPFADepthSize));
+ m_format.setStencilBufferSize(pixelFormatAttribute(NSOpenGLPFAStencilSize));
+ m_format.setSamples(pixelFormatAttribute(NSOpenGLPFASamples));
- if ([pixelFormat qt_getAttribute:NSOpenGLPFATripleBuffer])
+ if (pixelFormatAttribute(NSOpenGLPFATripleBuffer))
m_format.setSwapBehavior(QSurfaceFormat::TripleBuffer);
- else if ([pixelFormat qt_getAttribute:NSOpenGLPFADoubleBuffer])
+ else if (pixelFormatAttribute(NSOpenGLPFADoubleBuffer))
m_format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
else
m_format.setSwapBehavior(QSurfaceFormat::SingleBuffer);
// ------------------- Query the context -------------------
- m_format.setSwapInterval([m_context qt_getParameter:NSOpenGLCPSwapInterval]);
+ auto glContextParameter = [&](NSOpenGLContextParameter parameter) {
+ int value = 0;
+ [m_context getValues:&value forParameter:parameter];
+ return value;
+ };
+
+ m_format.setSwapInterval(glContextParameter(NSOpenGLCPSwapInterval));
if (oldContext)
[oldContext makeCurrentContext];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 08e7447a75..9a2f19c2f2 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -215,25 +215,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
connect(qGuiApp, &QGuiApplication::focusWindowChanged,
this, &QCocoaIntegration::focusWindowChanged);
-
- static auto splashScreenHider = QMacKeyValueObserver(NSApp, @"modalWindow", []{
- const QWindowList allWindows = QGuiApplication::topLevelWindows();
- for (QWindow *window : allWindows) {
- if ((window->flags() & Qt::SplashScreen) == Qt::SplashScreen) {
- QCocoaWindow *platformWindow = static_cast<QCocoaWindow*>(window->handle());
- NSWindow *splashWindow = platformWindow->view().window;
- if (!splashWindow)
- continue;
- if (NSApp.modalWindow) {
- NSInteger originalLevel = splashWindow.level;
- splashWindow.level = NSNormalWindowLevel;
- window->setProperty("_q_levelBeforeModalSession", (qlonglong)originalLevel);
- } else if (NSInteger originalLevel = window->property("_q_levelBeforeModalSession").toLongLong()) {
- splashWindow.level = originalLevel;
- }
- }
- }
- });
}
QCocoaIntegration::~QCocoaIntegration()
@@ -331,9 +312,7 @@ QPlatformOffscreenSurface *QCocoaIntegration::createPlatformOffscreenSurface(QOf
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
- QCocoaGLContext *glContext = new QCocoaGLContext(context);
- context->setNativeHandle(QVariant::fromValue<QCocoaNativeContext>(glContext->nativeContext()));
- return glContext;
+ return new QCocoaGLContext(context);
}
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
index de5cf85854..db64702b8d 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm
@@ -118,11 +118,13 @@ class QSystemTrayIconSys
public:
QSystemTrayIconSys(QCocoaSystemTrayIcon *sys) {
item = [[QNSStatusItem alloc] initWithSysTray:sys];
- [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:item];
+ NSUserNotificationCenter.defaultUserNotificationCenter.delegate = item;
}
~QSystemTrayIconSys() {
[[[item item] view] setHidden: YES];
- [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:nil];
+ NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter;
+ if (center.delegate == item)
+ center.delegate = nil;
[item release];
}
QNSStatusItem *item;
@@ -264,7 +266,6 @@ bool QCocoaSystemTrayIcon::supportsMessages() const
void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &message,
const QIcon& icon, MessageIcon, int)
{
- Q_UNUSED(icon);
if (!m_sys)
return;
@@ -272,7 +273,16 @@ void QCocoaSystemTrayIcon::showMessage(const QString &title, const QString &mess
notification.title = [NSString stringWithUTF8String:title.toUtf8().data()];
notification.informativeText = [NSString stringWithUTF8String:message.toUtf8().data()];
- [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];
+ if (!icon.isNull()) {
+ auto *nsimage = qt_mac_create_nsimage(icon);
+ [nsimage setTemplate:icon.isMask()];
+ notification.contentImage = [nsimage autorelease];
+ }
+
+ NSUserNotificationCenter *center = NSUserNotificationCenter.defaultUserNotificationCenter;
+ center.delegate = m_sys->item;
+ [center deliverNotification:notification];
+ [notification release];
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 363a026e71..8f3c192745 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -454,13 +454,35 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags)
if (type == Qt::ToolTip)
windowLevel = NSScreenSaverWindowLevel;
- // Any "special" window should be in at least the same level as its parent.
- if (type != Qt::Window) {
- const QWindow * const transientParent = window()->transientParent();
- const QCocoaWindow * const transientParentWindow = transientParent ?
- static_cast<QCocoaWindow *>(transientParent->handle()) : nullptr;
- if (transientParentWindow)
- windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel);
+ auto *transientParent = window()->transientParent();
+ if (transientParent && transientParent->handle()) {
+ // We try to keep windows in at least the same window level as
+ // their transient parent. Unfortunately this only works when the
+ // window is created. If the window level changes after that, as
+ // a result of a call to setWindowFlags, or by changing the level
+ // of the native window, we will not pick this up, and the window
+ // will be left behind (or in a different window level than) its
+ // parent. We could KVO-observe the window level of our transient
+ // parent, but that requires us to know when the parent goes away
+ // so that we can unregister the observation before the parent is
+ // dealloced, something we can't do for generic NSWindows. Another
+ // way would be to override [NSWindow setLevel:] and notify child
+ // windows about the change, but that doesn't work for foreign
+ // windows, which can still be transient parents via fromWinId().
+ // One area where this problem is apparent is when AppKit tweaks
+ // the window level of modal windows during application activation
+ // and deactivation. Since we don't pick up on these window level
+ // changes in a generic way, we need to add logic explicitly to
+ // re-evaluate the window level after AppKit has done its tweaks.
+
+ auto *transientCocoaWindow = static_cast<QCocoaWindow *>(transientParent->handle());
+ auto *nsWindow = transientCocoaWindow->nativeWindow();
+
+ // We only upgrade the window level for "special" windows, to work
+ // around Qt Designer parenting the designer windows to the widget
+ // palette window (QTBUG-31779). This should be fixed in designer.
+ if (type != Qt::Window)
+ windowLevel = qMax(windowLevel, nsWindow.level);
}
return windowLevel;
@@ -1626,6 +1648,9 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
[nsWindow setDepthLimit:NSWindowDepthTwentyfourBitRGB];
}
+ if (format().colorSpace() == QSurfaceFormat::sRGBColorSpace)
+ nsWindow.colorSpace = NSColorSpace.sRGBColorSpace;
+
return nsWindow;
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.h b/src/plugins/platforms/cocoa/qcocoawindowmanager.h
new file mode 100644
index 0000000000..54f17eeccd
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOCOAWINDOWMANAGER_H
+#define QCOCOAWINDOWMANAGER_H
+
+#include <QtCore/qglobal.h>
+
+#include <AppKit/AppKit.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCocoaWindowManager
+{
+public:
+ static QCocoaWindowManager *instance();
+
+private:
+ QCocoaWindowManager();
+ void initialize();
+
+ void modalSessionChanged();
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOCOAWINDOWMANAGER_H
diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
new file mode 100644
index 0000000000..879bfaa546
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcocoawindowmanager.h"
+#include "qcocoawindow.h"
+
+#include <QtCore/private/qcore_mac_p.h>
+
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qwindow.h>
+
+QT_BEGIN_NAMESPACE
+
+QCocoaWindowManager *QCocoaWindowManager::instance()
+{
+ static auto *instance = new QCocoaWindowManager;
+ return instance;
+}
+
+QCocoaWindowManager::QCocoaWindowManager()
+{
+ if (NSApp) {
+ initialize();
+ } else {
+ static auto applicationDidFinishLaunching(QMacNotificationObserver(nil,
+ NSApplicationDidFinishLaunchingNotification, [this] { initialize(); }));
+ }
+}
+
+void QCocoaWindowManager::initialize()
+{
+ Q_ASSERT(NSApp);
+
+ // Whenever the modalWindow property of NSApplication changes we have a new
+ // modal session running. Observing the app modal window instead of our own
+ // event dispatcher sessions allows us to track session started by native
+ // APIs as well. We need to check the initial state as well, in case there
+ // is already a modal session running.
+ static auto modalSessionObserver(QMacKeyValueObserver(
+ NSApp, @"modalWindow", [this] { modalSessionChanged(); },
+ NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew));
+}
+
+void QCocoaWindowManager::modalSessionChanged()
+{
+ // Make sure that no window is overlapping the modal window. This can
+ // happen for e.g. splash screens, which have the NSPopUpMenuWindowLevel.
+ for (auto *window : QGuiApplication::topLevelWindows()) {
+ auto *platformWindow = static_cast<QCocoaWindow*>(window->handle());
+ if (!platformWindow)
+ continue;
+
+ auto naturalWindowLevel = platformWindow->windowLevel(window->flags());
+ if (naturalWindowLevel > NSModalPanelWindowLevel) {
+ NSWindow *nativeWindow = platformWindow->nativeWindow();
+ if (NSApp.modalWindow) {
+ // Lower window to that of the modal windows, but no less
+ nativeWindow.level = NSModalPanelWindowLevel;
+ [nativeWindow orderBack:nil];
+ } else {
+ // Restore window's natural window level, whatever that was
+ nativeWindow.level = naturalWindowLevel;
+ }
+ }
+ }
+}
+
+static void initializeWindowManager() { Q_UNUSED(QCocoaWindowManager::instance()); }
+Q_CONSTRUCTOR_FUNCTION(initializeWindowManager)
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm
index f2f29b26ee..58ad53a6e1 100644
--- a/src/plugins/platforms/cocoa/qprintengine_mac.mm
+++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm
@@ -522,16 +522,16 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va
if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode))
break;
switch (mode) {
- case QPrinter::DuplexNone:
+ case QPrint::DuplexNone:
PMSetDuplex(d->settings(), kPMDuplexNone);
break;
- case QPrinter::DuplexAuto:
+ case QPrint::DuplexAuto:
PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble);
break;
- case QPrinter::DuplexLongSide:
+ case QPrint::DuplexLongSide:
PMSetDuplex(d->settings(), kPMDuplexNoTumble);
break;
- case QPrinter::DuplexShortSide:
+ case QPrint::DuplexShortSide:
PMSetDuplex(d->settings(), kPMDuplexTumble);
break;
default:
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index 2c6b4245b7..3e78196227 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -114,20 +114,16 @@ public:
: QEglFSWindow(w)
, m_integration(integration)
, m_egl_stream(EGL_NO_STREAM_KHR)
- , m_framePending(false)
{ }
~QEglFSKmsEglDeviceWindow() { destroy(); }
void invalidateSurface() override;
void resetSurface() override;
- void flip();
- static void pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data);
const QEglFSKmsEglDeviceIntegration *m_integration;
EGLStreamKHR m_egl_stream;
EGLint m_latency;
- bool m_framePending;
};
void QEglFSKmsEglDeviceWindow::invalidateSurface()
@@ -148,9 +144,6 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
streamAttribs[streamAttribCount++] = EGL_STREAM_FIFO_LENGTH_KHR;
streamAttribs[streamAttribCount++] = fifoLength;
}
-
- streamAttribs[streamAttribCount++] = EGL_CONSUMER_AUTO_ACQUIRE_EXT;
- streamAttribs[streamAttribCount++] = EGL_FALSE;
streamAttribs[streamAttribCount++] = EGL_NONE;
m_egl_stream = m_integration->m_funcs->create_stream(display, streamAttribs);
@@ -248,49 +241,6 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
qCDebug(qLcEglfsKmsDebug, "Created stream producer surface %p", m_surface);
}
-void QEglFSKmsEglDeviceWindow::flip()
-{
- EGLDisplay display = screen()->display();
-
- EGLAttrib acquire_attribs[3] = { EGL_NONE };
-
- acquire_attribs[0] = EGL_DRM_FLIP_EVENT_DATA_NV;
- acquire_attribs[1] = (EGLAttrib)this;
- acquire_attribs[2] = EGL_NONE;
-
- if (m_egl_stream != EGL_NO_STREAM_KHR)
- if (!m_integration->m_funcs->acquire_stream_attrib_nv(display, m_egl_stream, acquire_attribs))
- qWarning("eglStreamConsumerAcquireAttribNV failed: eglError: %x", eglGetError());
-
- m_framePending = true;
-
- while (m_framePending) {
- drmEventContext drmEvent;
- memset(&drmEvent, 0, sizeof(drmEvent));
- drmEvent.version = 3;
- drmEvent.vblank_handler = nullptr;
- drmEvent.page_flip_handler = pageFlipHandler;
- drmHandleEvent(m_integration->m_device->fd(), &drmEvent);
- }
-}
-
-void QEglFSKmsEglDeviceWindow::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
-{
- Q_UNUSED(fd);
- Q_UNUSED(sequence);
- Q_UNUSED(tv_sec);
- Q_UNUSED(tv_usec);
-
- QEglFSKmsEglDeviceWindow *window = static_cast<QEglFSKmsEglDeviceWindow*>(user_data);
- window->m_framePending = false;
-}
-
-void QEglFSKmsEglDeviceIntegration::presentBuffer(QPlatformSurface *surface)
-{
- QEglFSKmsEglDeviceWindow *eglWindow = static_cast<QEglFSKmsEglDeviceWindow*>(surface);
- eglWindow->flip();
-}
-
QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
{
QEglFSKmsEglDeviceWindow *eglWindow = new QEglFSKmsEglDeviceWindow(window, this);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
index a5697ec831..5819d82ebf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.h
@@ -62,8 +62,6 @@ public:
bool supportsPBuffers() const override;
QEglFSWindow *createWindow(QWindow *window) const override;
- void presentBuffer(QPlatformSurface *surface) override;
-
EGLDeviceEXT eglDevice() const { return m_egl_device; }
protected:
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index 6d211667be..a810880c43 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -681,7 +681,7 @@ void QWasmCompositor::frame()
QWasmWindow *someWindow = nullptr;
- foreach (QWasmWindow *window, m_windowStack) {
+ for (QWasmWindow *window : qAsConst(m_windowStack)) {
if (window->window()->surfaceClass() == QSurface::Window
&& qt_window_private(static_cast<QWindow *>(window->window()))->receivedExpose) {
someWindow = window;
@@ -715,7 +715,7 @@ void QWasmCompositor::frame()
m_blitter->bind();
m_blitter->setRedBlueSwizzle(true);
- foreach (QWasmWindow *window, m_windowStack) {
+ for (QWasmWindow *window : qAsConst(m_windowStack)) {
QWasmCompositedWindow &compositedWindow = m_compositedWindows[window];
if (!compositedWindow.visible)
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 3895646b89..ad94ba9c77 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -138,16 +138,16 @@ static constexpr const auto KeyTbl = qMakeArray(
Emkb2Qt< Qt::Key_Minus, '-' >,
Emkb2Qt< Qt::Key_Period, '.' >,
Emkb2Qt< Qt::Key_Slash, '/' >,
- Emkb2Qt< Qt::Key_0, '0' >,
- Emkb2Qt< Qt::Key_1, '1' >,
- Emkb2Qt< Qt::Key_2, '2' >,
- Emkb2Qt< Qt::Key_3, '3' >,
- Emkb2Qt< Qt::Key_4, '4' >,
- Emkb2Qt< Qt::Key_5, '5' >,
- Emkb2Qt< Qt::Key_6, '6' >,
- Emkb2Qt< Qt::Key_7, '7' >,
- Emkb2Qt< Qt::Key_8, '8' >,
- Emkb2Qt< Qt::Key_9, '9' >,
+ Emkb2Qt< Qt::Key_0, 'D','i','g','i','t','0' >,
+ Emkb2Qt< Qt::Key_1, 'D','i','g','i','t','1' >,
+ Emkb2Qt< Qt::Key_2, 'D','i','g','i','t','2' >,
+ Emkb2Qt< Qt::Key_3, 'D','i','g','i','t','3' >,
+ Emkb2Qt< Qt::Key_4, 'D','i','g','i','t','4' >,
+ Emkb2Qt< Qt::Key_5, 'D','i','g','i','t','5' >,
+ Emkb2Qt< Qt::Key_6, 'D','i','g','i','t','6' >,
+ Emkb2Qt< Qt::Key_7, 'D','i','g','i','t','7' >,
+ Emkb2Qt< Qt::Key_8, 'D','i','g','i','t','8' >,
+ Emkb2Qt< Qt::Key_9, 'D','i','g','i','t','9' >,
Emkb2Qt< Qt::Key_Semicolon, ';' >,
Emkb2Qt< Qt::Key_Equal, '=' >,
Emkb2Qt< Qt::Key_A, 'K','e','y','A' >,
@@ -432,7 +432,8 @@ Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent
{
Qt::Key qtKey = Qt::Key_unknown;
- if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0) {
+ if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0 ||
+ qstrncmp(emscriptKey->code, "Digit", 5) == 0) {
emkb2qt_t searchKey{emscriptKey->code, 0}; // search emcsripten code
auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
@@ -779,6 +780,60 @@ quint64 QWasmEventTranslator::getTimestamp()
return QDeadlineTimer::current().deadlineNSecs() / 1000;
}
+struct KeyMapping { Qt::Key from, to; };
+
+constexpr KeyMapping tildeKeyTable[] = { // ~
+ { Qt::Key_A, Qt::Key_Atilde },
+ { Qt::Key_N, Qt::Key_Ntilde },
+ { Qt::Key_O, Qt::Key_Otilde },
+};
+constexpr KeyMapping graveKeyTable[] = { // `
+ { Qt::Key_A, Qt::Key_Agrave },
+ { Qt::Key_E, Qt::Key_Egrave },
+ { Qt::Key_I, Qt::Key_Igrave },
+ { Qt::Key_O, Qt::Key_Ograve },
+ { Qt::Key_U, Qt::Key_Ugrave },
+};
+constexpr KeyMapping acuteKeyTable[] = { // '
+ { Qt::Key_A, Qt::Key_Aacute },
+ { Qt::Key_E, Qt::Key_Eacute },
+ { Qt::Key_I, Qt::Key_Iacute },
+ { Qt::Key_O, Qt::Key_Oacute },
+ { Qt::Key_U, Qt::Key_Uacute },
+ { Qt::Key_Y, Qt::Key_Yacute },
+};
+constexpr KeyMapping diaeresisKeyTable[] = { // umlaut ¨
+ { Qt::Key_A, Qt::Key_Adiaeresis },
+ { Qt::Key_E, Qt::Key_Ediaeresis },
+ { Qt::Key_I, Qt::Key_Idiaeresis },
+ { Qt::Key_O, Qt::Key_Odiaeresis },
+ { Qt::Key_U, Qt::Key_Udiaeresis },
+ { Qt::Key_Y, Qt::Key_ydiaeresis },
+};
+constexpr KeyMapping circumflexKeyTable[] = { // ^
+ { Qt::Key_A, Qt::Key_Acircumflex },
+ { Qt::Key_E, Qt::Key_Ecircumflex },
+ { Qt::Key_I, Qt::Key_Icircumflex },
+ { Qt::Key_O, Qt::Key_Ocircumflex },
+ { Qt::Key_U, Qt::Key_Ucircumflex },
+};
+
+static Qt::Key find_impl(const KeyMapping *first, const KeyMapping *last, Qt::Key key) noexcept
+{
+ while (first != last) {
+ if (first->from == key)
+ return first->to;
+ ++first;
+ }
+ return Qt::Key_unknown;
+}
+
+template <size_t N>
+static Qt::Key find(const KeyMapping (&map)[N], Qt::Key key) noexcept
+{
+ return find_impl(map, map + N, key);
+}
+
Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey)
{
Qt::Key wasmKey = Qt::Key_unknown;
@@ -788,31 +843,30 @@ Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBa
#else
case Qt::Key_O: // ´ Key_Dead_Grave
#endif
- wasmKey = graveKeyTable.value(accentBaseKey);
+ wasmKey = find(graveKeyTable, accentBaseKey);
break;
case Qt::Key_E: // ´ Key_Dead_Acute
- wasmKey = acuteKeyTable.value(accentBaseKey);
+ wasmKey = find(acuteKeyTable, accentBaseKey);
break;
case Qt::Key_AsciiTilde:
case Qt::Key_N:// Key_Dead_Tilde
- wasmKey = tildeKeyTable.value(accentBaseKey);
+ wasmKey = find(tildeKeyTable, accentBaseKey);
break;
#ifndef Q_OS_MACOS
case Qt::Key_QuoteLeft:
#endif
case Qt::Key_U:// ¨ Key_Dead_Diaeresis
- wasmKey = diaeresisKeyTable.value(accentBaseKey);
+ wasmKey = find(diaeresisKeyTable, accentBaseKey);
break;
case Qt::Key_I:// macOS Key_Dead_Circumflex
case Qt::Key_6:// linux
case Qt::Key_Apostrophe:// linux
- wasmKey = circumflexKeyTable.value(accentBaseKey);
- break;
+ wasmKey = find(circumflexKeyTable, accentBaseKey);
break;
default:
break;
- };
+ };
return wasmKey;
}
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index 1655b7226a..568ae00732 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -77,42 +77,6 @@ private:
Qt::Key translateDeadKey(Qt::Key deadKey, Qt::Key accentBaseKey);
- QHash<Qt::Key , Qt::Key> tildeKeyTable { // ~
- { Qt::Key_A, Qt::Key_Atilde},
- { Qt::Key_N, Qt::Key_Ntilde},
- { Qt::Key_O, Qt::Key_Otilde}
- };
- QHash<Qt::Key , Qt::Key> graveKeyTable { // `
- { Qt::Key_A, Qt::Key_Agrave},
- { Qt::Key_E, Qt::Key_Egrave},
- { Qt::Key_I, Qt::Key_Igrave},
- { Qt::Key_O, Qt::Key_Ograve},
- { Qt::Key_U, Qt::Key_Ugrave}
- };
- QHash<Qt::Key , Qt::Key> acuteKeyTable { // '
- { Qt::Key_A, Qt::Key_Aacute},
- { Qt::Key_E, Qt::Key_Eacute},
- { Qt::Key_I, Qt::Key_Iacute},
- { Qt::Key_O, Qt::Key_Oacute},
- { Qt::Key_U, Qt::Key_Uacute},
- { Qt::Key_Y, Qt::Key_Yacute}
- };
- QHash<Qt::Key , Qt::Key> diaeresisKeyTable { // umlaut ¨
- { Qt::Key_A, Qt::Key_Adiaeresis},
- { Qt::Key_E, Qt::Key_Ediaeresis},
- { Qt::Key_I, Qt::Key_Idiaeresis},
- { Qt::Key_O, Qt::Key_Odiaeresis},
- { Qt::Key_U, Qt::Key_Udiaeresis},
- { Qt::Key_Y, Qt::Key_ydiaeresis}
- };
- QHash<Qt::Key , Qt::Key> circumflexKeyTable { // ^
- { Qt::Key_A, Qt::Key_Acircumflex},
- { Qt::Key_E, Qt::Key_Ecircumflex},
- { Qt::Key_I, Qt::Key_Icircumflex},
- { Qt::Key_O, Qt::Key_Ocircumflex},
- { Qt::Key_U, Qt::Key_Ucircumflex}
- };
-
QMap <int, QPointF> pressedTouchIds;
private:
diff --git a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
index dc6bb5847e..53e875ead6 100644
--- a/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
+++ b/src/plugins/platforms/wasm/qwasmfontdatabase.cpp
@@ -38,10 +38,13 @@ void QWasmFontDatabase::populateFontDatabase()
// Load font file from resources. Currently
// all fonts needs to be bundled with the nexe
// as Qt resources.
- QStringList fontFileNames = QStringList() << QStringLiteral(":/fonts/DejaVuSansMono.ttf")
- << QStringLiteral(":/fonts/Vera.ttf")
- << QStringLiteral(":/fonts/DejaVuSans.ttf");
- foreach (const QString &fontFileName, fontFileNames) {
+
+ const QString fontFileNames[] = {
+ QStringLiteral(":/fonts/DejaVuSansMono.ttf"),
+ QStringLiteral(":/fonts/Vera.ttf"),
+ QStringLiteral(":/fonts/DejaVuSans.ttf"),
+ };
+ for (const QString &fontFileName : fontFileNames) {
QFile theFont(fontFileName);
if (!theFont.open(QIODevice::ReadOnly))
break;
diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro
index c28df8f893..f8c8175525 100644
--- a/src/plugins/platforms/wasm/wasm.pro
+++ b/src/plugins/platforms/wasm/wasm.pro
@@ -7,6 +7,8 @@ QT += \
# Avoid X11 header collision, use generic EGL native types
DEFINES += QT_EGL_NO_X11
+DEFINES += QT_NO_FOREACH
+
SOURCES = \
main.cpp \
qwasmintegration.cpp \
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index e681dbb0cb..d5258ca6a3 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -47,6 +47,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qrect.h>
#include <QtCore/qtextboundaryfinder.h>
+#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qevent.h>
#include <QtGui/qtextformat.h>
@@ -279,7 +280,13 @@ void QWindowsInputContext::showInputPanel()
// with Windows 10 if the Windows IME is (re)enabled _after_ the caret is shown.
if (m_caretCreated) {
cursorRectChanged();
- ShowCaret(platformWindow->handle());
+ // We only call ShowCaret() on Windows 10 as in earlier versions the caret
+ // would actually be visible (QTBUG-74492) and the workaround for the
+ // Surface seems unnecessary there anyway. But leave it hidden for IME.
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
+ ShowCaret(platformWindow->handle());
+ else
+ HideCaret(platformWindow->handle());
setWindowsImeEnabled(platformWindow, false);
setWindowsImeEnabled(platformWindow, true);
}
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 4b54051e0c..4f0f846749 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -1301,7 +1301,23 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|| code == Qt::Key_Control
|| code == Qt::Key_Meta
|| code == Qt::Key_Alt)) {
- // Someone ate the key down event
+
+ // Workaround for QTBUG-77153:
+ // The Surface Pen eraser button generates Meta+F18/19/20 keystrokes,
+ // but when it is not touching the screen the Fn Down is eaten and only
+ // a Fn Up with the previous state as "not pressed" is generated, which
+ // would be ignored. We detect this case and synthesize the expected events.
+ if ((msg.lParam & 0x40000000) == 0 &&
+ Qt::KeyboardModifier(state) == Qt::NoModifier &&
+ ((code == Qt::Key_F18) || (code == Qt::Key_F19) || (code == Qt::Key_F20))) {
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
+ Qt::MetaModifier, scancode,
+ quint32(msg.wParam), MetaLeft);
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
+ Qt::NoModifier, scancode,
+ quint32(msg.wParam), 0);
+ result = true;
+ }
} else {
if (!code)
code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state);
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index b3d961db72..cffd8427a2 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -80,13 +80,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
*result = 0;
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
- POINTER_INPUT_TYPE pointerType;
- if (!QWindowsContext::user32dll.getPointerType(pointerId, &pointerType)) {
+ if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
qWarning() << "GetPointerType() failed:" << qt_error_string();
return false;
}
- switch (pointerType) {
+ switch (m_pointerType) {
case QT_PT_POINTER:
case QT_PT_MOUSE:
case QT_PT_TOUCHPAD: {
@@ -684,7 +683,7 @@ bool QWindowsPointerHandler::translateMouseWheelEvent(QWindow *window,
QPoint localPos = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos);
- QWindowSystemInterface::handleWheelEvent(window, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
+ QWindowSystemInterface::handleWheelEvent(receiver, localPos, globalPos, QPoint(), angleDelta, keyModifiers);
return true;
}
@@ -734,7 +733,11 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
- if (isMouseEventSynthesizedFromPenOrTouch()) {
+ // Following the logic of the old mouse handler, only events synthesized
+ // for touch screen are marked as such. On some systems, using the bit 7 of
+ // the extra msg info for checking if synthesized for touch does not work,
+ // so we use the pointer type of the last pointer message.
+ if (isMouseEventSynthesizedFromPenOrTouch() && m_pointerType == QT_PT_TOUCH) {
if (QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)
return false;
source = Qt::MouseEventSynthesizedBySystem;
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index 068e804007..8874db27e3 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -82,6 +82,7 @@ private:
bool m_needsEnterOnPointerUpdate = false;
QEvent::Type m_lastEventType = QEvent::None;
Qt::MouseButton m_lastEventButton = Qt::NoButton;
+ DWORD m_pointerType = 0;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index d919d97211..282c0b107e 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -303,23 +303,28 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData)
m_data.hMonitor = newData.hMonitor;
}
- if (m_data.geometry != newData.geometry || m_data.availableGeometry != newData.availableGeometry) {
- m_data.geometry = newData.geometry;
- m_data.availableGeometry = newData.availableGeometry;
- QWindowSystemInterface::handleScreenGeometryChange(screen(),
- newData.geometry, newData.availableGeometry);
- }
- if (!qFuzzyCompare(m_data.dpi.first, newData.dpi.first)
- || !qFuzzyCompare(m_data.dpi.second, newData.dpi.second)) {
- m_data.dpi = newData.dpi;
+ // QGuiApplicationPrivate::processScreenGeometryChange() checks and emits
+ // DPI and orientation as well, so, assign new values and emit DPI first.
+ const bool geometryChanged = m_data.geometry != newData.geometry
+ || m_data.availableGeometry != newData.availableGeometry;
+ const bool dpiChanged = !qFuzzyCompare(m_data.dpi.first, newData.dpi.first)
+ || !qFuzzyCompare(m_data.dpi.second, newData.dpi.second);
+ const bool orientationChanged = m_data.orientation != newData.orientation;
+ m_data.dpi = newData.dpi;
+ m_data.orientation = newData.orientation;
+ m_data.geometry = newData.geometry;
+ m_data.availableGeometry = newData.availableGeometry;
+
+ if (dpiChanged) {
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(),
newData.dpi.first,
newData.dpi.second);
}
- if (m_data.orientation != newData.orientation) {
- m_data.orientation = newData.orientation;
- QWindowSystemInterface::handleScreenOrientationChange(screen(),
- newData.orientation);
+ if (orientationChanged)
+ QWindowSystemInterface::handleScreenOrientationChange(screen(), newData.orientation);
+ if (geometryChanged) {
+ QWindowSystemInterface::handleScreenGeometryChange(screen(),
+ newData.geometry, newData.availableGeometry);
}
}
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index 3014b30c38..962e4ab938 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -43,6 +43,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QHash>
#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/private/qfsfileengine_p.h>
#include <wrl.h>
#include <windows.storage.h>
@@ -196,7 +197,19 @@ bool QWinRTFileEngine::open(QIODevice::OpenMode openMode)
hr = QWinRTFunctions::await(op, d->stream.GetAddressOf());
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false);
- d->openMode = openMode;
+ const ProcessOpenModeResult res = processOpenModeFlags(openMode);
+ if (!res.ok) {
+ setError(QFileDevice::OpenError, res.error);
+ return false;
+ }
+ d->openMode = res.openMode;
+ if (d->openMode & QIODevice::Truncate) {
+ if (!setSize(0)) {
+ close();
+ setError(QFileDevice::OpenError, QLatin1String("Could not truncate file"));
+ return false;
+ }
+ }
return SUCCEEDED(hr);
}
@@ -257,6 +270,29 @@ qint64 QWinRTFileEngine::size() const
return qint64(size);
}
+bool QWinRTFileEngine::setSize(qint64 size)
+{
+ Q_D(QWinRTFileEngine);
+ if (!d->stream) {
+ setError(QFileDevice::ResizeError, QLatin1String("File must be open to be resized"));
+ return false;
+ }
+
+ if (size < 0) {
+ setError(QFileDevice::ResizeError, QLatin1String("File size cannot be negative"));
+ return false;
+ }
+
+ HRESULT hr = d->stream->put_Size(static_cast<quint64>(size));
+ RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ResizeError, false);
+ if (!flush()) {
+ setError(QFileDevice::ResizeError, QLatin1String("Could not flush file"));
+ return false;
+ }
+
+ return true;
+}
+
qint64 QWinRTFileEngine::pos() const
{
Q_D(const QWinRTFileEngine);
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h
index 4485917c9e..453565a95a 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.h
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.h
@@ -79,6 +79,7 @@ public:
bool close() override;
bool flush() override;
qint64 size() const override;
+ bool setSize(qint64 size) override;
qint64 pos() const override;
bool seek(qint64 pos) override;
bool remove() override;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 0d77889a36..86ab7651c6 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -669,12 +669,6 @@ QDpi QWinRTScreen::logicalDpi() const
return QDpi(d->logicalDpi, d->logicalDpi);
}
-qreal QWinRTScreen::pixelDensity() const
-{
- Q_D(const QWinRTScreen);
- return qMax(1, qRound(d->logicalDpi / 96));
-}
-
qreal QWinRTScreen::scaleFactor() const
{
Q_D(const QWinRTScreen);
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index 63c254940d..6b57780fa1 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -96,7 +96,6 @@ public:
QImage::Format format() const override;
QSizeF physicalSize() const override;
QDpi logicalDpi() const override;
- qreal pixelDensity() const override;
qreal scaleFactor() const;
QPlatformCursor *cursor() const override;
Qt::KeyboardModifiers keyboardModifiers() const;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index d27a288feb..cac6345b66 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -132,7 +132,9 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
if (!m_startupId.isNull())
qunsetenv("DESKTOP_STARTUP_ID");
+ const int focusInDelay = 100;
m_focusInTimer.setSingleShot(true);
+ m_focusInTimer.setInterval(focusInDelay);
m_focusInTimer.callOnTimeout([]() {
// No FocusIn events for us, proceed with FocusOut normally.
QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason);
diff --git a/src/plugins/platforms/xcb/qxcbeventqueue.cpp b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
index 82a36c0727..759ee3cc95 100644
--- a/src/plugins/platforms/xcb/qxcbeventqueue.cpp
+++ b/src/plugins/platforms/xcb/qxcbeventqueue.cpp
@@ -226,11 +226,13 @@ void QXcbEventQueue::run()
};
while (!m_closeConnectionDetected && (event = xcb_wait_for_event(connection))) {
+ m_newEventsMutex.lock();
enqueueEvent(event);
while (!m_closeConnectionDetected && (event = xcb_poll_for_queued_event(connection)))
enqueueEvent(event);
m_newEventsCondition.wakeOne();
+ m_newEventsMutex.unlock();
wakeUpDispatcher();
}
@@ -350,9 +352,12 @@ bool QXcbEventQueue::peekEventQueue(PeekerCallback peeker, void *peekerData,
void QXcbEventQueue::waitForNewEvents(unsigned long time)
{
- m_newEventsMutex.lock();
+ QMutexLocker locker(&m_newEventsMutex);
+ QXcbEventNode *tailBeforeFlush = m_flushedTail;
+ flushBufferedEvents();
+ if (tailBeforeFlush != m_flushedTail)
+ return;
m_newEventsCondition.wait(&m_newEventsMutex, time);
- m_newEventsMutex.unlock();
}
void QXcbEventQueue::sendCloseConnectionEvent() const
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 396b47001d..1d1a4eea1c 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -848,7 +848,7 @@ void QXcbWindow::doFocusOut()
connection()->setFocusWindow(nullptr);
relayFocusToModalWindow();
// Do not set the active window to nullptr if there is a FocusIn coming.
- connection()->focusInTimer().start(400);
+ connection()->focusInTimer().start();
}
struct QtMotifWmHints {