diff options
author | Liang Qi <liang.qi@qt.io> | 2018-06-30 22:59:21 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-07-02 11:23:45 +0200 |
commit | e3ed2281c0c891cf3b15c95f9f7cdae42e9f233a (patch) | |
tree | aae8da6ce616eae02b69fb1fcdcb4383c8fe6811 /src/plugins | |
parent | 3be141d5bc199080b524d8f6f5ce514e8f74d23a (diff) | |
parent | e75e4b39b78ba05ea2cd45dc96acf99fc89c5915 (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Conflicts:
src/plugins/platforms/cocoa/qnsview.mm
src/plugins/platforms/cocoa/qnsview_dragging.mm
src/plugins/platforms/ios/qiosinputcontext.mm
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/plugins/platforms/xcb/qxcbwindow.cpp
src/tools/androiddeployqt/main.cpp
Was moved from qttools into qtbase in 5.11.
So re-apply 32398e4d here.
tests/auto/corelib/global/qlogging/test/test.pro
tests/auto/corelib/global/qlogging/tst_qlogging.cpp
tests/auto/corelib/io/qfile/tst_qfile.cpp
tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
tests/auto/corelib/thread/qthreadstorage/test/test.pro
tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
tests/auto/widgets/kernel/qapplication/test/test.pro
Done-with: Gatis Paeglis <gatis.paeglis@qt.io>
Done-with: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Done-with: Oliver Wolff <oliver.wolff@qt.io>
Change-Id: Id970486c5315a1718c540f00deb2633533e8fc7b
Diffstat (limited to 'src/plugins')
35 files changed, 378 insertions, 202 deletions
diff --git a/src/plugins/imageformats/ico/ico.json b/src/plugins/imageformats/ico/ico.json index 14093ee471..304e2f1c02 100644 --- a/src/plugins/imageformats/ico/ico.json +++ b/src/plugins/imageformats/ico/ico.json @@ -1,4 +1,4 @@ { "Keys": [ "ico", "cur" ], - "MimeTypes": [ "image/vnd.microsoft.icon" ] + "MimeTypes": [ "image/vnd.microsoft.icon", "image/vnd.microsoft.icon" ] } diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 2493181bc5..348a9b0c24 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -117,6 +117,9 @@ static void updateFormatFromContext(QSurfaceFormat *format) format->setProfile(QSurfaceFormat::CompatibilityProfile); } + // NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579) +static QMutex s_contextMutex; + QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle) : m_context(nil), @@ -248,6 +251,7 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) QWindow *window = static_cast<QCocoaWindow *>(surface)->window(); setActiveWindow(window); + QMutexLocker locker(&s_contextMutex); [m_context flushBuffer]; } @@ -400,6 +404,7 @@ QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName) void QCocoaGLContext::update() { + QMutexLocker locker(&s_contextMutex); [m_context update]; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 022242130b..9e168835f1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -503,7 +503,10 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) { const Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type); - const bool resizeable = !(flags & Qt::CustomizeWindowHint); // Remove zoom button by disabling resize + + // Remove zoom button by disabling resize for CustomizeWindowHint windows, except for + // Qt::Tool windows (e.g. dock windows) which should always be resizeable. + const bool resizeable = !(flags & Qt::CustomizeWindowHint) || (type == Qt::Tool); // Select base window type. Note that the value of NSBorderlessWindowMask is 0. NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask; @@ -517,6 +520,8 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) styleMask |= NSClosableWindowMask; if (flags & Qt::WindowMinimizeButtonHint) styleMask |= NSMiniaturizableWindowMask; + if (flags & Qt::WindowMaximizeButtonHint) + styleMask |= NSResizableWindowMask; } else { styleMask |= NSClosableWindowMask | NSTitledWindowMask; diff --git a/src/plugins/platforms/cocoa/qnsview_dragging.mm b/src/plugins/platforms/cocoa/qnsview_dragging.mm index 01df0e9337..e61329f169 100644 --- a/src/plugins/platforms/cocoa/qnsview_dragging.mm +++ b/src/plugins/platforms/cocoa/qnsview_dragging.mm @@ -165,7 +165,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin [nativeCursor set]; // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor - // by creating a fake move event + // by creating a fake move event, unless on 10.14 and later where doing so will trigger a security + // warning dialog. FIXME: Find a way to update the cursor without fake mouse events. + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) + return; + if (m_updatingDrag) return; diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index 6079a35d05..1c21879a89 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -72,25 +72,38 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*")); /*! Overridden to ensure that the zoomed state always results in a maximized window, which would otherwise not be the case for borderless windows. + + We also keep the window on the same screen as before; something AppKit + sometimes fails to do using its built in logic. */ - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)proposedFrame { Q_UNUSED(proposedFrame); Q_ASSERT(window == m_cocoaWindow->nativeWindow()); - - // We compute the maximized state based on the maximum size, and - // the current position of the window. This may result in the window - // geometry falling outside of the current screen's available geometry, - // e.g. when there is not maximize size set, but this is okey, AppKit - // will then shift and possibly clip the geometry for us. const QWindow *w = m_cocoaWindow->window(); - QRect maximizedRect = QRect(w->framePosition(), w->maximumSize()); - // QWindow::maximumSize() refers to the client size, - // but AppKit expects the full frame size. - maximizedRect.adjust(0, 0, 0, w->frameMargins().top()); + // maximumSize() refers to the client size, but AppKit expects the full frame size + QSizeF maximumSize = w->maximumSize() + QSize(0, w->frameMargins().top()); + + // The window should never be larger than the current screen geometry + const QRectF screenGeometry = m_cocoaWindow->screen()->geometry(); + maximumSize = maximumSize.boundedTo(screenGeometry.size()); + + // Use the current frame position for the initial maximized frame, + // so that the window stays put and just expand, in case its maximum + // size is within the screen bounds. + QRectF maximizedFrame = QRectF(w->framePosition(), maximumSize); + + // But constrain the frame to the screen bounds in case the frame + // extends beyond the screen bounds as a result of starting out + // with the current frame position. + maximizedFrame.translate(QPoint( + qMax(screenGeometry.left() - maximizedFrame.left(), 0.0) + + qMin(screenGeometry.right() - maximizedFrame.right(), 0.0), + qMax(screenGeometry.top() - maximizedFrame.top(), 0.0) + + qMin(screenGeometry.bottom() - maximizedFrame.bottom(), 0.0))); - return QCocoaScreen::mapToNative(maximizedRect); + return QCocoaScreen::mapToNative(maximizedFrame); } - (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro index 6eb9f2c534..71257d09f7 100644 --- a/src/plugins/platforms/ios/kernel.pro +++ b/src/plugins/platforms/ios/kernel.pro @@ -5,8 +5,6 @@ TARGET = qios # application's main() when the plugin is a shared library. qtConfig(shared): CONFIG += static -CONFIG += no_app_extension_api_only - QT += \ core-private gui-private \ clipboard_support-private fontdatabase_support-private graphics_support-private diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm index cc76d198f5..bf4e9cc900 100644 --- a/src/plugins/platforms/ios/qiosapplicationstate.mm +++ b/src/plugins/platforms/ios/qiosapplicationstate.mm @@ -86,7 +86,7 @@ static void qRegisterApplicationStateNotifications() QLatin1String("Extension loaded, assuming state is active")); } else { // Initialize correct startup state, which may not be the Qt default (inactive) - UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + UIApplicationState startupState = qt_apple_sharedApplication().applicationState; QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application loaded")); } } @@ -95,7 +95,7 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterApplicationStateNotifications) QIOSApplicationState::QIOSApplicationState() { if (!qt_apple_isApplicationExtension()) { - UIApplicationState startupState = [UIApplication sharedApplication].applicationState; + UIApplicationState startupState = qt_apple_sharedApplication().applicationState; QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application launched")); } } diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm index 5987bc1540..e8a3f5b30e 100644 --- a/src/plugins/platforms/ios/qiosfiledialog.mm +++ b/src/plugins/platforms/ios/qiosfiledialog.mm @@ -43,6 +43,8 @@ #include <QtGui/qwindow.h> #include <QDebug> +#include <QtCore/private/qcore_mac_p.h> + #include "qiosfiledialog.h" #include "qiosintegration.h" #include "qiosoptionalplugininterface.h" @@ -94,7 +96,7 @@ bool QIOSFileDialog::showImagePickerDialog(QWindow *parent) } UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window - : [UIApplication sharedApplication].keyWindow; + : qt_apple_sharedApplication().keyWindow; [window.rootViewController presentViewController:m_viewController animated:YES completion:nil]; return true; diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm index f27b2242df..a523d1be45 100644 --- a/src/plugins/platforms/ios/qiosglobal.mm +++ b/src/plugins/platforms/ios/qiosglobal.mm @@ -42,6 +42,8 @@ #include "qiosviewcontroller.h" #include "qiosscreen.h" +#include <QtCore/private/qcore_mac_p.h> + QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application"); @@ -50,13 +52,16 @@ Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window"); bool isQtApplication() { + if (qt_apple_isApplicationExtension()) + return false; + // Returns \c true if the plugin is in full control of the whole application. This means // that we control the application delegate and the top view controller, and can take // actions that impacts all parts of the application. The opposite means that we are // embedded inside a native iOS application, and should be more focused on playing along // with native UIControls, and less inclined to change structures that lies outside the // scope of our QWindows/UIViews. - static bool isQt = ([[UIApplication sharedApplication].delegate isKindOfClass:[QIOSApplicationDelegate class]]); + static bool isQt = ([qt_apple_sharedApplication().delegate isKindOfClass:[QIOSApplicationDelegate class]]); return isQt; } @@ -152,8 +157,13 @@ QT_END_NAMESPACE + (id)currentFirstResponder { + if (qt_apple_isApplicationExtension()) { + qWarning() << "can't get first responder in application extensions!"; + return nil; + } + QtFirstResponderEvent *event = [[[QtFirstResponderEvent alloc] init] autorelease]; - [[UIApplication sharedApplication] sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event]; + [qt_apple_sharedApplication() sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event]; return event.firstResponder; } diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm index 3e22634071..d2229df133 100644 --- a/src/plugins/platforms/ios/qiosinputcontext.mm +++ b/src/plugins/platforms/ios/qiosinputcontext.mm @@ -49,6 +49,8 @@ #include "qioswindow.h" #include "quiview.h" +#include <QtCore/private/qcore_mac_p.h> + #include <QGuiApplication> #include <QtGui/private/qwindow_p.h> @@ -535,6 +537,11 @@ void QIOSInputContext::scroll(int y) if (!rootView) return; + if (qt_apple_isApplicationExtension()) { + qWarning() << "can't scroll root view in application extension"; + return; + } + CATransform3D translationTransform = CATransform3DMakeTranslation(0.0, -y, 0.0); if (CATransform3DEqualToTransform(translationTransform, rootView.layer.sublayerTransform)) return; @@ -573,7 +580,7 @@ void QIOSInputContext::scroll(int y) // Raise all known windows to above the status-bar if we're scrolling the screen, // while keeping the relative window level between the windows the same. - NSArray<UIWindow *> *applicationWindows = [[UIApplication sharedApplication] windows]; + NSArray<UIWindow *> *applicationWindows = [qt_apple_sharedApplication() windows]; static QHash<UIWindow *, UIWindowLevel> originalWindowLevels; for (UIWindow *window in applicationWindows) { if (keyboardScrollIsActive && !originalWindowLevels.contains(window)) diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index eae0530fbe..9a5a0ab499 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -86,7 +86,7 @@ QIOSIntegration::QIOSIntegration() , m_accessibility(0) , m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, QLatin1String("/platforms/darwin"))) { - if (Q_UNLIKELY(![UIApplication sharedApplication])) { + if (Q_UNLIKELY(!qt_apple_isApplicationExtension() && !qt_apple_sharedApplication())) { qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n" \ "If you are writing a native iOS application, and only want to use Qt for\n" \ "parts of the application, a good place to create QApplication is from within\n" \ diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm index 9d05b792c2..a7de9b473a 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.mm +++ b/src/plugins/platforms/ios/qiosmessagedialog.mm @@ -43,6 +43,8 @@ #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +#include <QtCore/private/qcore_mac_p.h> + #include "qiosglobal.h" #include "quiview.h" #include "qiosmessagedialog.h" @@ -126,7 +128,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win [m_alertController addAction:createAction(NoButton)]; } - UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : [UIApplication sharedApplication].keyWindow; + UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : qt_apple_sharedApplication().keyWindow; [window.rootViewController presentViewController:m_alertController animated:YES completion:nil]; return true; } diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 96679eaccd..f1121a102b 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -46,6 +46,8 @@ #include "qiosviewcontroller.h" #include "quiview.h" +#include <QtCore/private/qcore_mac_p.h> + #include <QtGui/private/qwindow_p.h> #include <private/qcoregraphics_p.h> @@ -269,17 +271,19 @@ QIOSScreen::QIOSScreen(UIScreen *screen) m_physicalDpi = 96; } - for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { - if (existingWindow.screen == m_uiScreen) { - m_uiWindow = [m_uiWindow retain]; - break; + if (!qt_apple_isApplicationExtension()) { + for (UIWindow *existingWindow in qt_apple_sharedApplication().windows) { + if (existingWindow.screen == m_uiScreen) { + m_uiWindow = [m_uiWindow retain]; + break; + } } - } - if (!m_uiWindow) { - // Create a window and associated view-controller that we can use - m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]]; - m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; + if (!m_uiWindow) { + // Create a window and associated view-controller that we can use + m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]]; + m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease]; + } } updateProperties(); @@ -325,17 +329,20 @@ void QIOSScreen::updateProperties() #ifndef Q_OS_TVOS if (m_uiScreen == [UIScreen mainScreen]) { - Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); - QIOSViewController *qtViewController = [m_uiWindow.rootViewController isKindOfClass:[QIOSViewController class]] ? static_cast<QIOSViewController *>(m_uiWindow.rootViewController) : nil; if (qtViewController.lockedOrientation) { + Q_ASSERT(!qt_apple_isApplicationExtension()); + // Setting the statusbar orientation (content orientation) on will affect the screen geometry, // which is not what we want. We want to reflect the screen geometry based on the locked orientation, // and adjust the available geometry based on the repositioned status bar for the current status // bar orientation. + Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation( + UIDeviceOrientation(qt_apple_sharedApplication().statusBarOrientation)); + Qt::ScreenOrientation lockedOrientation = toQtScreenOrientation(UIDeviceOrientation(qtViewController.lockedOrientation)); QTransform transform = transformBetween(lockedOrientation, statusBarOrientation, m_geometry).inverted(); @@ -489,8 +496,8 @@ Qt::ScreenOrientation QIOSScreen::orientation() const // the orientation the application was started up in (which may not match // the physical orientation of the device, but typically does unless the // application has been locked to a subset of the available orientations). - if (deviceOrientation == UIDeviceOrientationUnknown) - deviceOrientation = UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation); + if (deviceOrientation == UIDeviceOrientationUnknown && !qt_apple_isApplicationExtension()) + deviceOrientation = UIDeviceOrientation(qt_apple_sharedApplication().statusBarOrientation); // If the device reports face up or face down orientations, we can't map // them to Qt orientations, so we pretend we're in the same orientation diff --git a/src/plugins/platforms/ios/qiosservices.mm b/src/plugins/platforms/ios/qiosservices.mm index 3c44e1d7d6..7222bf6793 100644 --- a/src/plugins/platforms/ios/qiosservices.mm +++ b/src/plugins/platforms/ios/qiosservices.mm @@ -40,6 +40,9 @@ #include "qiosservices.h" #include <QtCore/qurl.h> +#include <QtCore/qdebug.h> +#include <QtCore/private/qcore_mac_p.h> + #include <QtGui/qdesktopservices.h> #import <UIKit/UIApplication.h> @@ -48,6 +51,11 @@ QT_BEGIN_NAMESPACE bool QIOSServices::openUrl(const QUrl &url) { + if (qt_apple_isApplicationExtension()) { + qWarning() << "openUrl not implement for application extensions yet"; + return false; + } + if (url == m_handlingUrl) return false; @@ -55,12 +63,25 @@ bool QIOSServices::openUrl(const QUrl &url) return openDocument(url); NSURL *nsUrl = url.toNSURL(); - UIApplication *application = [UIApplication sharedApplication]; + UIApplication *application = qt_apple_sharedApplication(); if (![application canOpenURL:nsUrl]) return false; - [application openURL:nsUrl options:@{} completionHandler:nil]; + static SEL openUrlSelector = @selector(openURL:options:completionHandler:); + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature: + [UIApplication instanceMethodSignatureForSelector:openUrlSelector]]; + invocation.target = application; + invocation.selector = openUrlSelector; + + static auto kEmptyDictionary = @{}; + // Indices 0 and 1 are self and _cmd + [invocation setArgument:&nsUrl atIndex:2]; + [invocation setArgument:&kEmptyDictionary atIndex:3]; + // Fourth argument is nil, so left unset + + [invocation invoke]; + return true; } diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index ff696f5b7f..e5419b1766 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -46,6 +46,7 @@ #include <QtGui/private/qinputmethod_p.h> #include <QtCore/private/qobject_p.h> +#include <QtCore/private/qcore_mac_p.h> #include "qiosglobal.h" #include "qiostextinputoverlay.h" @@ -462,7 +463,7 @@ static void executeBlockWithoutAnimation(Block block) if (enabled) { _focusView = [reinterpret_cast<UIView *>(qApp->focusWindow()->winId()) retain]; - _desktopView = [[UIApplication sharedApplication].keyWindow.rootViewController.view retain]; + _desktopView = [qt_apple_sharedApplication().keyWindow.rootViewController.view retain]; Q_ASSERT(_focusView && _desktopView && _desktopView.superview); [_desktopView addGestureRecognizer:self]; } else { @@ -978,6 +979,11 @@ QIOSTextInputOverlay::QIOSTextInputOverlay() , m_selectionRecognizer(nullptr) , m_openMenuOnTapRecognizer(nullptr) { + if (qt_apple_isApplicationExtension()) { + qWarning() << "text input overlays disabled in application extensions"; + return; + } + connect(qApp, &QGuiApplication::focusObjectChanged, this, &QIOSTextInputOverlay::updateFocusObject); } diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index 91980d3f35..5534264a60 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -41,6 +41,7 @@ #include <QtCore/QStringList> #include <QtCore/QVariant> +#include <QtCore/private/qcore_mac_p.h> #include <QtGui/QFont> @@ -103,7 +104,7 @@ bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const switch (type) { case FileDialog: case MessageDialog: - return true; + return !qt_apple_isApplicationExtension(); default: return false; } diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index f254a8692d..ce2aa96ca5 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -41,6 +41,7 @@ #import "qiosviewcontroller.h" #include <QtCore/qscopedvaluerollback.h> +#include <QtCore/private/qcore_mac_p.h> #include <QtGui/QGuiApplication> #include <QtGui/QWindow> @@ -305,15 +306,17 @@ { [super viewDidLoad]; + Q_ASSERT(!qt_apple_isApplicationExtension()); + #ifndef Q_OS_TVOS NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(willChangeStatusBarFrame:) name:UIApplicationWillChangeStatusBarFrameNotification - object:[UIApplication sharedApplication]]; + object:qt_apple_sharedApplication()]; [center addObserver:self selector:@selector(didChangeStatusBarOrientation:) name:UIApplicationDidChangeStatusBarOrientationNotification - object:[UIApplication sharedApplication]]; + object:qt_apple_sharedApplication()]; #endif } @@ -453,7 +456,6 @@ focusWindow = qt_window_private(focusWindow)->topLevelWindow(); #ifndef Q_OS_TVOS - UIApplication *uiApplication = [UIApplication sharedApplication]; // -------------- Status bar style and visbility --------------- @@ -477,6 +479,8 @@ // -------------- Content orientation --------------- + UIApplication *uiApplication = qt_apple_sharedApplication(); + static BOOL kAnimateContentOrientationChanges = YES; Qt::ScreenOrientation contentOrientation = focusWindow->contentOrientation(); diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.h b/src/plugins/platforms/qnx/qqnxeglwindow.h index 3a3840f13c..d8cfd730ac 100644 --- a/src/plugins/platforms/qnx/qqnxeglwindow.h +++ b/src/plugins/platforms/qnx/qqnxeglwindow.h @@ -60,6 +60,8 @@ public: void setGeometry(const QRect &rect) override; + QSurfaceFormat format() const override { return m_format; } + protected: int pixelFormat() const override; void resetBuffers() override; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 80f3203289..980a9fe9ab 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1430,7 +1430,7 @@ bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result) bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) { long filterResult = 0; - if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), &msg, &filterResult)) { + if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), msg, &filterResult)) { *result = LRESULT(filterResult); return true; } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 6358778914..2409d70ec9 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -153,9 +153,11 @@ QT_BEGIN_NAMESPACE QWindowsOpengl32DLL QOpenGLStaticContext::opengl32; -FARPROC QWindowsOpengl32DLL::resolve(const char *name) +QFunctionPointer QWindowsOpengl32DLL::resolve(const char *name) { - return m_lib ? ::GetProcAddress(m_lib, name) : nullptr; + return m_lib + ? reinterpret_cast<QFunctionPointer>(::GetProcAddress(m_lib, name)) + : nullptr; } bool QWindowsOpengl32DLL::init(bool softwareRendering) @@ -977,12 +979,18 @@ QOpenGLStaticContext::QOpenGLStaticContext() : extensionNames(QOpenGLStaticContext::getGlString(GL_EXTENSIONS)), extensions(0), defaultFormat(QWindowsOpenGLContextFormat::current()), - wglGetPixelFormatAttribIVARB((WglGetPixelFormatAttribIVARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetPixelFormatAttribivARB")), - wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")), - wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")), - wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")), - wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")), - wglGetExtensionsStringARB((WglGetExtensionsStringARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB")) + wglGetPixelFormatAttribIVARB(reinterpret_cast<WglGetPixelFormatAttribIVARB>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetPixelFormatAttribivARB")))), + wglChoosePixelFormatARB(reinterpret_cast<WglChoosePixelFormatARB>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")))), + wglCreateContextAttribsARB(reinterpret_cast<WglCreateContextAttribsARB>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")))), + wglSwapInternalExt(reinterpret_cast<WglSwapInternalExt>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")))), + wglGetSwapInternalExt(reinterpret_cast<WglGetSwapInternalExt>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")))), + wglGetExtensionsStringARB(reinterpret_cast<WglGetExtensionsStringARB>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB")))) { if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ") || extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1) @@ -1231,7 +1239,8 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) hasRobustness = exts && strstr(exts, "GL_ARB_robustness"); } else { typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint); - glGetStringi_t glGetStringi = (glGetStringi_t) QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi"); + glGetStringi_t glGetStringi = reinterpret_cast<glGetStringi_t>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi"))); if (glGetStringi) { GLint n = 0; QOpenGLStaticContext::opengl32.glGetIntegerv(GL_NUM_EXTENSIONS, &n); @@ -1244,8 +1253,10 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval) } } } - if (hasRobustness) - m_getGraphicsResetStatus = (GLenum (APIENTRY *)()) QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetGraphicsResetStatusARB"); + if (hasRobustness) { + m_getGraphicsResetStatus = reinterpret_cast<GlGetGraphicsResetStatusArbType>( + reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetGraphicsResetStatusARB"))); + } QOpenGLStaticContext::opengl32.wglMakeCurrent(prevSurface, prevContext); return true; @@ -1369,16 +1380,17 @@ QFunctionPointer QWindowsGLContext::getProcAddress(const char *procName) // Even though we use QFunctionPointer, it does not mean the function can be called. // It will need to be cast to the proper function type with the correct calling // convention. QFunctionPointer is nothing more than a glorified void* here. - PROC procAddress = QOpenGLStaticContext::opengl32.wglGetProcAddress(procName); + QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName)); // We support AllGLFunctionsQueryable, which means this function must be able to // return a function pointer even for functions that are in GL.h and exported // normally from opengl32.dll. wglGetProcAddress() is not guaranteed to work for such // functions, however in QT_OPENGL_DYNAMIC builds QOpenGLFunctions will just blindly // call into here for _any_ OpenGL function. - if (!procAddress || procAddress == reinterpret_cast<PROC>(0x1) || procAddress == reinterpret_cast<PROC>(0x2) - || procAddress == reinterpret_cast<PROC>(0x3) || procAddress == reinterpret_cast<PROC>(-1)) + if (procAddress == nullptr || reinterpret_cast<quintptr>(procAddress) < 4u + || procAddress == reinterpret_cast<QFunctionPointer>(-1)) { procAddress = QOpenGLStaticContext::opengl32.resolve(procName); + } if (QWindowsContext::verbose > 1) qCDebug(lcQpaGl) << __FUNCTION__ << procName << QOpenGLStaticContext::opengl32.wglGetCurrentContext() << "returns" << procAddress; diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h index 2e89711740..8c96a8dd0c 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.h +++ b/src/plugins/platforms/windows/qwindowsglcontext.h @@ -122,7 +122,7 @@ struct QWindowsOpengl32DLL void (APIENTRY * glGetIntegerv)(GLenum pname, GLint* params); const GLubyte * (APIENTRY * glGetString)(GLenum name); - FARPROC resolve(const char *name); + QFunctionPointer resolve(const char *name); private: HMODULE m_lib; bool m_nonOpengl32; @@ -217,6 +217,8 @@ public: void *nativeContext() const override { return m_renderingContext; } private: + typedef GLenum (APIENTRY *GlGetGraphicsResetStatusArbType)(); + inline void releaseDCs(); bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0); @@ -230,7 +232,7 @@ private: bool m_extensionsUsed; int m_swapInterval; bool m_ownsContext; - GLenum (APIENTRY * m_getGraphicsResetStatus)(); + GlGetGraphicsResetStatusArbType m_getGraphicsResetStatus; bool m_lost; }; #endif diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 9f4dea915e..30da0da1de 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -163,19 +163,22 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp */ -HIMC QWindowsInputContext::m_defaultContext = 0; - QWindowsInputContext::QWindowsInputContext() : m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")), m_languageId(currentInputLanguageId()), m_locale(qt_localeFromLCID(m_languageId)) { + const quint32 bmpData = 0; + m_transparentBitmap = CreateBitmap(2, 2, 1, 1, &bmpData); + connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged, this, &QWindowsInputContext::cursorRectChanged); } QWindowsInputContext::~QWindowsInputContext() { + if (m_transparentBitmap) + DeleteObject(m_transparentBitmap); } bool QWindowsInputContext::hasCapability(Capability capability) const @@ -242,6 +245,43 @@ bool QWindowsInputContext::isInputPanelVisible() const return hwnd && ::IsWindowEnabled(hwnd) && ::IsWindowVisible(hwnd); } +void QWindowsInputContext::showInputPanel() +{ + if (!inputMethodAccepted()) + return; + + QWindow *window = QGuiApplication::focusWindow(); + if (!window) + return; + + QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(window); + if (!platformWindow) + return; + + // Create an invisible 2x2 caret, which will be kept at the microfocus position. + // It is important for triggering the on-screen keyboard in touch-screen devices, + // for some Chinese input methods, and for Magnifier's "follow keyboard" feature. + if (!m_caretCreated && m_transparentBitmap) + m_caretCreated = CreateCaret(platformWindow->handle(), m_transparentBitmap, 0, 0); + + // For some reason, the on-screen keyboard is only triggered on the Surface + // with Windows 10 if the Windows IME is (re)enabled _after_ the caret is shown. + if (m_caretCreated) { + cursorRectChanged(); + ShowCaret(platformWindow->handle()); + setWindowsImeEnabled(platformWindow, false); + setWindowsImeEnabled(platformWindow, true); + } +} + +void QWindowsInputContext::hideInputPanel() +{ + if (m_caretCreated) { + DestroyCaret(); + m_caretCreated = false; + } +} + void QWindowsInputContext::updateEnabled() { if (!QGuiApplication::focusObject()) @@ -256,18 +296,14 @@ void QWindowsInputContext::updateEnabled() void QWindowsInputContext::setWindowsImeEnabled(QWindowsWindow *platformWindow, bool enabled) { - if (!platformWindow || platformWindow->testFlag(QWindowsWindow::InputMethodDisabled) == !enabled) + if (!platformWindow) return; if (enabled) { - // Re-enable Windows IME by associating default context saved on first disabling. - ImmAssociateContext(platformWindow->handle(), QWindowsInputContext::m_defaultContext); - platformWindow->clearFlag(QWindowsWindow::InputMethodDisabled); + // Re-enable Windows IME by associating default context. + ImmAssociateContextEx(platformWindow->handle(), 0, IACE_DEFAULT); } else { - // Disable Windows IME by associating 0 context. Store context first time. - const HIMC oldImC = ImmAssociateContext(platformWindow->handle(), 0); - platformWindow->setFlag(QWindowsWindow::InputMethodDisabled); - if (!QWindowsInputContext::m_defaultContext && oldImC) - QWindowsInputContext::m_defaultContext = oldImC; + // Disable Windows IME by associating 0 context. + ImmAssociateContext(platformWindow->handle(), 0); } } @@ -284,15 +320,25 @@ void QWindowsInputContext::update(Qt::InputMethodQueries queries) void QWindowsInputContext::cursorRectChanged() { - if (!m_compositionContext.hwnd) + QWindow *window = QGuiApplication::focusWindow(); + if (!window) return; + + qreal factor = QHighDpiScaling::factor(window); + const QInputMethod *inputMethod = QGuiApplication::inputMethod(); const QRectF cursorRectangleF = inputMethod->cursorRectangle(); if (!cursorRectangleF.isValid()) return; + const QRect cursorRectangle = - QRectF(cursorRectangleF.topLeft() * m_compositionContext.factor, - cursorRectangleF.size() * m_compositionContext.factor).toRect(); + QRectF(cursorRectangleF.topLeft() * factor, cursorRectangleF.size() * factor).toRect(); + + if (m_caretCreated) + SetCaretPos(cursorRectangle.x(), cursorRectangle.y()); + + if (!m_compositionContext.hwnd) + return; qCDebug(lcQpaInputMethods) << __FUNCTION__<< cursorRectangle; @@ -316,9 +362,6 @@ void QWindowsInputContext::cursorRectChanged() candf.rcArea.right = cursorRectangle.x() + cursorRectangle.width(); candf.rcArea.bottom = cursorRectangle.y() + cursorRectangle.height(); - if (m_compositionContext.haveCaret) - SetCaretPos(cursorRectangle.x(), cursorRectangle.y()); - ImmSetCompositionWindow(himc, &cf); ImmSetCandidateWindow(himc, &candf); ImmReleaseContext(m_compositionContext.hwnd, himc); @@ -410,7 +453,7 @@ bool QWindowsInputContext::startComposition(HWND hwnd) qCDebug(lcQpaInputMethods) << __FUNCTION__ << fo << window << "language=" << m_languageId; if (!fo || QWindowsWindow::handleOf(window) != hwnd) return false; - initContext(hwnd, QHighDpiScaling::factor(window), fo); + initContext(hwnd, fo); startContextComposition(); return true; } @@ -550,18 +593,13 @@ bool QWindowsInputContext::endComposition(HWND hwnd) return true; } -void QWindowsInputContext::initContext(HWND hwnd, qreal factor, QObject *focusObject) +void QWindowsInputContext::initContext(HWND hwnd, QObject *focusObject) { if (m_compositionContext.hwnd) doneContext(); m_compositionContext.hwnd = hwnd; m_compositionContext.focusObject = focusObject; - m_compositionContext.factor = factor; - // Create a hidden caret which is kept at the microfocus - // position in update(). This is important for some - // Chinese input methods. - m_compositionContext.haveCaret = CreateCaret(hwnd, 0, 1, 1); - HideCaret(hwnd); + update(Qt::ImQueryAll); m_compositionContext.isComposing = false; m_compositionContext.position = 0; @@ -571,12 +609,10 @@ void QWindowsInputContext::doneContext() { if (!m_compositionContext.hwnd) return; - if (m_compositionContext.haveCaret) - DestroyCaret(); m_compositionContext.hwnd = 0; m_compositionContext.composition.clear(); m_compositionContext.position = 0; - m_compositionContext.isComposing = m_compositionContext.haveCaret = false; + m_compositionContext.isComposing = false; m_compositionContext.focusObject = 0; } diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 35105d15ff..8668efbb15 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -58,12 +58,10 @@ class QWindowsInputContext : public QPlatformInputContext struct CompositionContext { HWND hwnd = 0; - bool haveCaret = false; QString composition; int position = 0; bool isComposing = false; QPointer<QObject> focusObject; - qreal factor = 1; }; public: explicit QWindowsInputContext(); @@ -81,6 +79,8 @@ public: QRectF keyboardRect() const override; bool isInputPanelVisible() const override; + void showInputPanel() override; + void hideInputPanel() override; bool startComposition(HWND hwnd); bool composition(HWND hwnd, LPARAM lParam); @@ -96,7 +96,7 @@ private slots: void cursorRectChanged(); private: - void initContext(HWND hwnd, qreal factor, QObject *focusObject); + void initContext(HWND hwnd, QObject *focusObject); void doneContext(); void startContextComposition(); void endContextComposition(); @@ -104,7 +104,8 @@ private: HWND getVirtualKeyboardWindowHandle() const; const DWORD m_WM_MSIME_MOUSE; - static HIMC m_defaultContext; + bool m_caretCreated = false; + HBITMAP m_transparentBitmap; CompositionContext m_compositionContext; bool m_endCompositionRecursionGuard = false; LCID m_languageId; diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index a90a44c4e1..c4ee820211 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -283,16 +283,21 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers() bool QWindowsOpenGLTester::testDesktopGL() { #if !defined(QT_NO_OPENGL) + typedef HGLRC (WINAPI *CreateContextType)(HDC); + typedef BOOL (WINAPI *DeleteContextType)(HGLRC); + typedef BOOL (WINAPI *MakeCurrentType)(HDC, HGLRC); + typedef PROC (WINAPI *WglGetProcAddressType)(LPCSTR); + HMODULE lib = 0; HWND wnd = 0; HDC dc = 0; HGLRC context = 0; LPCTSTR className = L"qtopengltest"; - HGLRC (WINAPI * CreateContext)(HDC dc) = 0; - BOOL (WINAPI * DeleteContext)(HGLRC context) = 0; - BOOL (WINAPI * MakeCurrent)(HDC dc, HGLRC context) = 0; - PROC (WINAPI * WGL_GetProcAddress)(LPCSTR name) = 0; + CreateContextType CreateContext = nullptr; + DeleteContextType DeleteContext = nullptr; + MakeCurrentType MakeCurrent = nullptr; + WglGetProcAddressType WGL_GetProcAddress = nullptr; bool result = false; @@ -300,16 +305,20 @@ bool QWindowsOpenGLTester::testDesktopGL() // This will typically fail on systems that do not have a real OpenGL driver. lib = LoadLibraryA("opengl32.dll"); if (lib) { - CreateContext = reinterpret_cast<HGLRC (WINAPI *)(HDC)>(::GetProcAddress(lib, "wglCreateContext")); + CreateContext = reinterpret_cast<CreateContextType>( + reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglCreateContext"))); if (!CreateContext) goto cleanup; - DeleteContext = reinterpret_cast<BOOL (WINAPI *)(HGLRC)>(::GetProcAddress(lib, "wglDeleteContext")); + DeleteContext = reinterpret_cast<DeleteContextType>( + reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglDeleteContext"))); if (!DeleteContext) goto cleanup; - MakeCurrent = reinterpret_cast<BOOL (WINAPI *)(HDC, HGLRC)>(::GetProcAddress(lib, "wglMakeCurrent")); + MakeCurrent = reinterpret_cast<MakeCurrentType>( + reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglMakeCurrent"))); if (!MakeCurrent) goto cleanup; - WGL_GetProcAddress = reinterpret_cast<PROC (WINAPI *)(LPCSTR)>(::GetProcAddress(lib, "wglGetProcAddress")); + WGL_GetProcAddress = reinterpret_cast<WglGetProcAddressType>( + reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "wglGetProcAddress"))); if (!WGL_GetProcAddress) goto cleanup; @@ -356,7 +365,8 @@ bool QWindowsOpenGLTester::testDesktopGL() // Check the version. If we got 1.x then it's all hopeless and we can stop right here. typedef const GLubyte * (APIENTRY * GetString_t)(GLenum name); - GetString_t GetString = reinterpret_cast<GetString_t>(::GetProcAddress(lib, "glGetString")); + GetString_t GetString = reinterpret_cast<GetString_t>( + reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "glGetString"))); if (GetString) { if (const char *versionStr = reinterpret_cast<const char *>(GetString(GL_VERSION))) { const QByteArray version(versionStr); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 02e986fd90..5ff25eb474 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -215,12 +215,11 @@ public: WithinCreate = 0x20000, WithinMaximize = 0x40000, MaximizeToFullScreen = 0x80000, - InputMethodDisabled = 0x100000, - Compositing = 0x200000, - HasBorderInFullScreen = 0x400000, - WithinDpiChanged = 0x800000, - VulkanSurface = 0x1000000, - ResizeMoveActive = 0x2000000 + Compositing = 0x100000, + HasBorderInFullScreen = 0x200000, + WithinDpiChanged = 0x400000, + VulkanSurface = 0x800000, + ResizeMoveActive = 0x1000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 8cfcc49f9a..b81cb8efa1 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -95,6 +95,9 @@ public: void put(xcb_drawable_t dst, const QRegion ®ion, const QPoint &offset); void preparePaint(const QRegion ®ion); + static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1, + xcb_shm_segment_info_t *shm_info = nullptr); + private: void createShmSegment(size_t segmentSize); void destroyShmSegment(size_t segmentSize); @@ -325,15 +328,16 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize) #ifdef XCB_USE_SHM_FD if (connection()->hasShmFd()) { if (Q_UNLIKELY(segmentSize > std::numeric_limits<uint32_t>::max())) { - qWarning("QXcbShmImage: xcb_shm_create_segment() can't be called for size %zu, maximum allowed size is %u", - segmentSize, std::numeric_limits<uint32_t>::max()); + qCWarning(lcQpaXcb, "xcb_shm_create_segment() can't be called for size %zu, maximum" + "allowed size is %u", segmentSize, std::numeric_limits<uint32_t>::max()); return; } + const auto seg = xcb_generate_id(xcb_connection()); auto reply = Q_XCB_REPLY(xcb_shm_create_segment, xcb_connection(), seg, segmentSize, false); if (!reply) { - qWarning("QXcbShmImage: xcb_shm_create_segment() failed for size %zu", segmentSize); + qCWarning(lcQpaXcb, "xcb_shm_create_segment() failed for size %zu", segmentSize); return; } @@ -342,13 +346,13 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize) for (int i = 0; i < reply->nfd; i++) close(fds[i]); - qWarning("QXcbShmImage: failed to get file descriptor for shm segment of size %zu", segmentSize); + qCWarning(lcQpaXcb, "failed to get file descriptor for shm segment of size %zu", segmentSize); return; } void *addr = mmap(nullptr, segmentSize, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0); if (addr == MAP_FAILED) { - qWarning("QXcbShmImage: failed to mmap segment from X server (%d: %s) for size %zu", + qCWarning(lcQpaXcb, "failed to mmap segment from X server (%d: %s) for size %zu", errno, strerror(errno), segmentSize); close(fds[0]); xcb_shm_detach(xcb_connection(), seg); @@ -358,47 +362,54 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize) close(fds[0]); m_shm_info.shmseg = seg; m_shm_info.shmaddr = static_cast<quint8 *>(addr); - m_segmentSize = segmentSize; } else #endif { - const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); - if (id == -1) { - qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu", - errno, strerror(errno), segmentSize); - return; - } - - void *addr = shmat(id, 0, 0); - if (addr == (void *)-1) { - qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d", - errno, strerror(errno), id); - return; - } - - if (shmctl(id, IPC_RMID, 0) == -1) - qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed"); + if (createSystemVShmSegment(connection(), segmentSize, &m_shm_info)) + m_segmentSize = segmentSize; + } +} - const auto seg = xcb_generate_id(xcb_connection()); - auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false); - auto *error = xcb_request_check(xcb_connection(), cookie); - if (error) { - connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error); - free(error); - if (shmdt(addr) == -1) { - qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", - errno, strerror(errno), addr); - } - return; - } +bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize, + xcb_shm_segment_info_t *shmInfo) +{ + const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); + if (id == -1) { + qCWarning(lcQpaXcb, "shmget() failed (%d: %s) for size %zu", errno, strerror(errno), segmentSize); + return false; + } - m_shm_info.shmseg = seg; - m_shm_info.shmid = id; // unused - m_shm_info.shmaddr = static_cast<quint8 *>(addr); + void *addr = shmat(id, 0, 0); + if (addr == (void *)-1) { + qCWarning(lcQpaXcb, "shmat() failed (%d: %s) for id %d", errno, strerror(errno), id); + return false; + } - m_segmentSize = segmentSize; + if (shmctl(id, IPC_RMID, 0) == -1) + qCWarning(lcQpaXcb, "Error while marking the shared memory segment to be destroyed"); + + const auto seg = xcb_generate_id(c->xcb_connection()); + auto cookie = xcb_shm_attach_checked(c->xcb_connection(), seg, id, false); + auto *error = xcb_request_check(c->xcb_connection(), cookie); + if (error) { + c->printXcbError("xcb_shm_attach() failed with error", error); + free(error); + if (shmdt(addr) == -1) + qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), addr); + return false; + } else if (!shmInfo) { // this was a test run, free the allocated test segment + xcb_shm_detach(c->xcb_connection(), seg); + auto shmaddr = static_cast<quint8 *>(addr); + if (shmdt(shmaddr) == -1) + qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), shmaddr); + } + if (shmInfo) { + shmInfo->shmseg = seg; + shmInfo->shmid = id; // unused + shmInfo->shmaddr = static_cast<quint8 *>(addr); } + return true; } void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize) @@ -409,21 +420,21 @@ void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize) auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg); xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); if (error) - connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error); + connection()->printXcbError("xcb_shm_detach() failed with error", error); m_shm_info.shmseg = 0; #ifdef XCB_USE_SHM_FD if (connection()->hasShmFd()) { if (munmap(m_shm_info.shmaddr, segmentSize) == -1) { - qWarning("QXcbShmImage: munmap() failed (%d: %s) for %p with size %zu", - errno, strerror(errno), m_shm_info.shmaddr, segmentSize); + qCWarning(lcQpaXcb, "munmap() failed (%d: %s) for %p with size %zu", + errno, strerror(errno), m_shm_info.shmaddr, segmentSize); } } else #endif { if (shmdt(m_shm_info.shmaddr) == -1) { - qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", - errno, strerror(errno), m_shm_info.shmaddr); + qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", + errno, strerror(errno), m_shm_info.shmaddr); } m_shm_info.shmid = 0; // unused } @@ -718,6 +729,12 @@ void QXcbBackingStoreImage::preparePaint(const QRegion ®ion) m_pendingFlush |= region; } +bool QXcbBackingStore::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize, void *shmInfo) +{ + auto info = reinterpret_cast<xcb_shm_segment_info_t *>(shmInfo); + return QXcbBackingStoreImage::createSystemVShmSegment(c, segmentSize, info); +} + QXcbBackingStore::QXcbBackingStore(QWindow *window) : QPlatformBackingStore(window) { @@ -757,7 +774,7 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) void QXcbBackingStore::endPaint() { if (Q_UNLIKELY(m_paintRegions.isEmpty())) { - qWarning("%s: paint regions empty!", Q_FUNC_INFO); + qCWarning(lcQpaXcb, "%s: paint regions empty!", Q_FUNC_INFO); return; } @@ -811,7 +828,7 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); if (!platformWindow) { - qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)"); + qCWarning(lcQpaXcb, "%s QWindow has no platform window, see QTBUG-32681", Q_FUNC_INFO); return; } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 747626c213..734de1f7d7 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -74,6 +74,9 @@ public: void beginPaint(const QRegion &) override; void endPaint() override; + static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1, + void *shmInfo = nullptr); + private: QXcbBackingStoreImage *m_image = nullptr; QStack<QRegion> m_paintRegions; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 4ffeb4ff77..0e45b1efaf 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -56,6 +56,7 @@ #include "qxcbglintegrationfactory.h" #include "qxcbglintegration.h" #include "qxcbcursor.h" +#include "qxcbbackingstore.h" #include <QSocketNotifier> #include <QAbstractEventDispatcher> @@ -591,7 +592,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeAllAtoms(); initializeXSync(); - initializeShm(); + if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM")) + initializeShm(); if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR")) initializeXRandr(); if (!has_randr_extension) @@ -979,7 +981,7 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); - qWarning("%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", + qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d", message, int(error->error_code), xcb_errors[clamped_error_code], int(error->sequence), int(error->resource_id), @@ -1661,7 +1663,7 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, if (!hasXInput2()) return false; - // compress XI_Motion, but not from tablet devices + // compress XI_Motion if (isXIType(event, m_xiOpCode, XCB_INPUT_MOTION)) { #if QT_CONFIG(tabletevent) auto *xdev = reinterpret_cast<xcb_input_motion_event_t *>(event); @@ -2074,20 +2076,34 @@ void QXcbConnection::initializeShm() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id); if (!reply || !reply->present) { - qWarning("QXcbConnection: MIT-SHM extension is not present on the X server."); + qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server"); return; } - has_shm = true; auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection); - if (!shm_query) { - qWarning("QXcbConnection: Failed to request MIT-SHM version"); - return; + if (shm_query) { + has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) || + shm_query->major_version > 1; + } else { + qCWarning(lcQpaXcb, "QXcbConnection: Failed to request MIT-SHM version"); } - has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) || - shm_query->major_version > 1; + qCDebug(lcQpaXcb) << "Has MIT-SHM :" << has_shm; + qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << has_shm_fd; + + // Temporary disable warnings (unless running in debug mode). + auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb()); + bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg); + if (!logging->isEnabled(QtMsgType::QtDebugMsg)) + logging->setEnabled(QtMsgType::QtWarningMsg, false); + if (!QXcbBackingStore::createSystemVShmSegment(this)) { + qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote " + "X11 connection?), disabling SHM"); + has_shm = has_shm_fd = false; + } + if (wasEnabled) + logging->setEnabled(QtMsgType::QtWarningMsg, true); } void QXcbConnection::initializeXFixes() diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 475afa65db..7ed61bff4e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -1017,6 +1017,7 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin std::swap(angleDelta.rx(), angleDelta.ry()); std::swap(rawDelta.rx(), rawDelta.ry()); } + qCDebug(lcQpaXInputEvents) << "scroll wheel @ window pos" << local << "delta px" << rawDelta << "angle" << angleDelta; QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, rawDelta, angleDelta, modifiers); } } @@ -1041,6 +1042,7 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective); if (modifiers & Qt::AltModifier) std::swap(angleDelta.rx(), angleDelta.ry()); + qCDebug(lcQpaXInputEvents) << "scroll wheel (button" << xiDeviceEvent->detail << ") @ window pos" << local << "delta angle" << angleDelta; QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiDeviceEvent->time, local, global, QPoint(), angleDelta, modifiers); } } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index d9cddef2d2..3ad16d78d9 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -136,6 +136,13 @@ static const unsigned int KeyTbl[] = { XKB_KEY_KP_Decimal, Qt::Key_Period, XKB_KEY_KP_Divide, Qt::Key_Slash, + // special non-XF86 function keys + + XKB_KEY_Undo, Qt::Key_Undo, + XKB_KEY_Redo, Qt::Key_Redo, + XKB_KEY_Find, Qt::Key_Find, + XKB_KEY_Cancel, Qt::Key_Cancel, + // International input method support keys // International & multi-key character composition diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 3b440bbb71..dd7e054301 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -744,12 +744,7 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation) m_sizeMillimeters = sizeInMillimeters(geometry.size(), virtualDpi()); qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4); - qreal rawFactor = dpi/96; - int roundedFactor = qFloor(rawFactor); - // Round up for .8 and higher. This favors "small UI" over "large UI". - if (rawFactor - roundedFactor >= 0.8) - roundedFactor = qCeil(rawFactor); - m_pixelDensity = qMax(1, roundedFactor); + m_pixelDensity = qMax(1, qRound(dpi/96)); m_geometry = geometry; m_availableGeometry = geometry & m_virtualDesktop->workArea(); QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 3c2d4edc4d..9192f1d9e4 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -2200,15 +2200,15 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in quint8 mode, quint8 detail, xcb_timestamp_t timestamp) { connection()->setTime(timestamp); -#if QT_CONFIG(xcb_xinput) - // Updates scroll valuators, as user might have done some scrolling outside our X client. - connection()->xi2UpdateScrollingDevices(); -#endif const QPoint global = QPoint(root_x, root_y); if (ignoreEnterEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; +#if QT_CONFIG(xcb_xinput) + // Updates scroll valuators, as user might have done some scrolling outside our X client. + connection()->xi2UpdateScrollingDevices(); +#endif const QPoint local(event_x, event_y); QWindowSystemInterface::handleEnterEvent(window(), local, global); diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp index 484dad6e1d..ead08dbce8 100644 --- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp +++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp @@ -1845,9 +1845,11 @@ bool QIBaseDriver::subscribeToNotification(const QString &name) eBuffer->bufferLength, eBuffer->eventBuffer, #if defined (FB_API_VER) && FB_API_VER >= 20 - reinterpret_cast<ISC_EVENT_CALLBACK>(qEventCallback), + reinterpret_cast<ISC_EVENT_CALLBACK>(reinterpret_cast<void *> + (&qEventCallback)), #else - reinterpret_cast<isc_callback>(qEventCallback), + reinterpret_cast<isc_callback>(reinterpret_cast<void *> + (&qEventCallback)), #endif eBuffer->resultBuffer); @@ -1925,9 +1927,11 @@ void QIBaseDriver::qHandleEventNotification(void *updatedResultBuffer) eBuffer->bufferLength, eBuffer->eventBuffer, #if defined (FB_API_VER) && FB_API_VER >= 20 - reinterpret_cast<ISC_EVENT_CALLBACK>(qEventCallback), + reinterpret_cast<ISC_EVENT_CALLBACK>(reinterpret_cast<void *> + (&qEventCallback)), #else - reinterpret_cast<isc_callback>(qEventCallback), + reinterpret_cast<isc_callback>(reinterpret_cast<void *> + (&qEventCallback)), #endif eBuffer->resultBuffer); if (Q_UNLIKELY(status[0] == 1 && status[1])) { diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index bb5f25e4d7..60fe547807 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -238,24 +238,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView); } @end -#if !QT_CONFIG(appstore_compliant) - -// This API was requested to Apple in rdar #36197888. -// We know it's safe to use up to macOS 10.13.3. -// See drawComplexControl(CC_ComboBox) for its usage. - -@interface NSComboBoxCell (QtButtonCell) -@property (readonly) NSButtonCell *qt_buttonCell; -@end - -@implementation NSComboBoxCell (QtButtonCell) -- (NSButtonCell *)qt_buttonCell { - return self->_buttonCell; -} -@end - -#endif - QT_BEGIN_NAMESPACE // The following constants are used for adjusting the size @@ -5205,11 +5187,14 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex auto *cb = static_cast<NSComboBox *>(cc); const auto frameRect = cw.adjustedControlFrame(combo->rect); cb.frame = frameRect.toCGRect(); -#if !QT_CONFIG(appstore_compliant) - static_cast<NSComboBoxCell *>(cc.cell).qt_buttonCell.highlighted = isPressed; -#else - // TODO Render to pixmap and darken the button manually -#endif + + // This API was requested to Apple in rdar #36197888. We know it's safe to use up to macOS 10.13.3 + if (NSButtonCell *cell = static_cast<NSButtonCell *>([cc.cell qt_valueForPrivateKey:@"_buttonCell"])) { + cell.highlighted = isPressed; + } else { + // TODO Render to pixmap and darken the button manually + } + d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) { // FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case [cb.cell drawWithFrame:r inView:cb]; diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index e690a424ac..4b583e13d3 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -944,7 +944,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa if (!isCached) { // SHORTCUT: If the part's state has no data, cache it for NOOP later if (!stateHasData) { - memset(&data, 0, sizeof(data)); + memset(static_cast<void *>(&data), 0, sizeof(data)); data.dataValid = true; alphaCache.insert(key, data); return true; @@ -1051,7 +1051,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa // Add to theme part cache if (!isCached) { - memset(&data, 0, sizeof(data)); + memset(static_cast<void *>(&data), 0, sizeof(data)); data.dataValid = true; data.partIsTransparent = partIsTransparent; data.alphaType = alphaType; |