diff options
author | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2016-01-08 12:30:57 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@theqtcompany.com> | 2016-01-08 12:35:24 +0100 |
commit | ad16478a76815f8f61d454bf7760aaf9ffbb4b51 (patch) | |
tree | eefdd9219cc9d59b62e042f49fc7555b980cb7a4 /src/plugins | |
parent | 80a741f3616290897ba0d9f1cbd3c9c5ee62da37 (diff) | |
parent | 09c92863001790a0304a5ef389901ee2b5b6cdc2 (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Based on merge done by Liang Qi
Change-Id: Id566e5b9f284d29bff2199f13f9417c660f5b26f
Diffstat (limited to 'src/plugins')
22 files changed, 231 insertions, 39 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 209ce2f7db..8152f1d53f 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -111,9 +111,13 @@ QAndroidPlatformScreen::~QAndroidPlatformScreen() QWindow *QAndroidPlatformScreen::topWindow() const { - foreach (QAndroidPlatformWindow *w, m_windowStack) - if (w->window()->type() == Qt::Window || w->window()->type() == Qt::Dialog) + foreach (QAndroidPlatformWindow *w, m_windowStack) { + if (w->window()->type() == Qt::Window || + w->window()->type() == Qt::Popup || + w->window()->type() == Qt::Dialog) { return w->window(); + } + } return 0; } diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 657295c29c..de27175bbd 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -707,6 +707,7 @@ void qt_mac_cleanUpMacColorSpaces() CGColorSpaceRef qt_mac_colorSpaceForDeviceType(const QPaintDevice *paintDevice) { #ifdef QT_NO_WIDGETS + Q_UNUSED(paintDevice) return qt_mac_displayColorSpace(0); #else bool isWidget = (paintDevice->devType() == QInternal::Widget); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index f776f746de..542a26d409 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -157,6 +157,7 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine macPrintEnginePriv->initialize(); return macPrintEnginePriv->printInfo; #else + Q_UNUSED(printEngine); qFatal("Printing is not supported when Qt is configured with -no-widgets"); return 0; #endif diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 528e6f120f..7f13961897 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -439,16 +439,17 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wobjc-method-access") enum { NSWindowOcclusionStateVisible = 1UL << 1 }; #endif - if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) { - m_platformWindow->exposeWindow(); - } else { - // Send Obscure events on window occlusion to stop animations. Several - // unit tests expect paint and/or expose events for windows that are - // sometimes (unpredictably) occlouded: Don't send Obscure events when - // running under QTestLib. - static bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING"); - if (!onTestLib) + // Several unit tests expect paint and/or expose events for windows that are + // sometimes (unpredictably) occluded and some unit tests depend on QWindow::isExposed - + // don't send Expose/Obscure events when running under QTestLib. + static const bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING"); + if (!onTestLib) { + if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) { + m_platformWindow->exposeWindow(); + } else { + // Send Obscure events on window occlusion to stop animations. m_platformWindow->obscureWindow(); + } } #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 QT_WARNING_POP diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 37b3866299..a5c963a2d5 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -107,8 +107,10 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; - if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) - touchCapabilities |= QTouchDevice::Pressure; + if ([mainScreen respondsToSelector:@selector(traitCollection)]) { + if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) + touchCapabilities |= QTouchDevice::Pressure; + } m_touchDevice->setCapabilities(touchCapabilities); QWindowSystemInterface::registerTouchDevice(m_touchDevice); QMacInternalPasteboardMime::initializeMimeTypes(); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 183c198806..08ef555441 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -308,7 +308,7 @@ static QStringList fontNamesFromTTCFile(const QString &filename) if (ttcTableHeader.majorVersion < 1 || ttcTableHeader.majorVersion > 2) return retVal; QVarLengthArray<quint32> offsetTable(ttcTableHeader.numFonts); - bytesToRead = sizeof(offsetTable) * ttcTableHeader.numFonts; + bytesToRead = sizeof(quint32) * ttcTableHeader.numFonts; bytesRead = f.read((char*)offsetTable.data(), bytesToRead); if (bytesToRead != bytesRead) return retVal; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 5e2e9f6454..a50ee60975 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -50,6 +50,7 @@ #include <QtCore/QtEndian> #include <QtCore/QVarLengthArray> #include <private/qstringiterator_p.h> +#include <QtCore/private/qsystemlibrary_p.h> #include <dwrite.h> #include <d2d1.h> @@ -645,6 +646,16 @@ QFontEngine *QWindowsFontEngineDirectWrite::cloneWithSize(qreal pixelSize) const return fontEngine; } +// Dynamically resolve GetUserDefaultLocaleName, which is available from Windows +// Vista onwards. ### fixme 5.7: Consider reverting to direct linking. +typedef int (WINAPI *GetUserDefaultLocaleNamePtr)(LPWSTR, int); + +static inline GetUserDefaultLocaleNamePtr resolveGetUserDefaultLocaleName() +{ + QSystemLibrary library(QStringLiteral("kernel32")); + return (GetUserDefaultLocaleNamePtr)library.resolve("GetUserDefaultLocaleName"); +} + void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font) { @@ -663,7 +674,9 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, BOOL exists = false; wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; - int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); + static const GetUserDefaultLocaleNamePtr getUserDefaultLocaleName = resolveGetUserDefaultLocaleName(); + const int defaultLocaleSuccess = getUserDefaultLocaleName + ? getUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH) : 0; if (defaultLocaleSuccess) hr = familyNames->FindLocaleName(localeName, &index, &exists); diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index c33b969f08..08eb5c02e2 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -131,7 +131,7 @@ static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue) return defaultValue; } -static inline bool dWordSystemParametersInfo(UINT what, DWORD defaultValue) +static inline DWORD dWordSystemParametersInfo(UINT what, DWORD defaultValue) { DWORD result; if (SystemParametersInfo(what, 0, &result, 0)) @@ -394,7 +394,7 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const case ContextMenuOnMouseRelease: return QVariant(true); case WheelScrollLines: - return dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3); + return QVariant(int(dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3))); default: break; } diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 9db5df995a..e94a0aa846 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -79,6 +79,7 @@ typedef IEventHandler<IInspectable *> ResumeHandler; typedef IEventHandler<SuspendingEventArgs *> SuspendHandler; #ifdef Q_OS_WINPHONE typedef IEventHandler<BackPressedEventArgs*> BackPressedHandler; +typedef IEventHandler<CameraEventArgs*> CameraButtonHandler; #endif QT_BEGIN_NAMESPACE @@ -88,6 +89,8 @@ uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); r #ifdef Q_OS_WINPHONE typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken); uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } +typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken); +uint qHash(HardwareButtons2CallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } #endif class QWinRTIntegrationPrivate @@ -103,6 +106,10 @@ public: #ifdef Q_OS_WINPHONE ComPtr<IHardwareButtonsStatics> hardwareButtons; QHash<HardwareButtonsCallbackRemover, EventRegistrationToken> buttonsTokens; + ComPtr<IHardwareButtonsStatics2> cameraButtons; + QHash<HardwareButtons2CallbackRemover, EventRegistrationToken> cameraTokens; + bool cameraHalfPressed : 1; + bool cameraPressed : 1; #endif }; @@ -130,6 +137,23 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) hr = d->hardwareButtons->add_BackPressed(Callback<BackPressedHandler>(this, &QWinRTIntegration::onBackButtonPressed).Get(), &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); Q_ASSERT_SUCCEEDED(hr); + + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), + IID_PPV_ARGS(&d->cameraButtons)); + Q_ASSERT_SUCCEEDED(hr); + if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) { + hr = d->cameraButtons->add_CameraPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraHalfPressed(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraHalfPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraReleased(Callback<CameraButtonHandler>(this, &QWinRTIntegration::onCameraReleased).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]); + Q_ASSERT_SUCCEEDED(hr); + } + d->cameraPressed = false; + d->cameraHalfPressed = false; #endif // Q_OS_WINPHONE QEventDispatcherWinRT::runOnXamlThread([d]() { @@ -151,6 +175,10 @@ QWinRTIntegration::~QWinRTIntegration() hr = (d->hardwareButtons.Get()->*i.key())(i.value()); Q_ASSERT_SUCCEEDED(hr); } + for (QHash<HardwareButtons2CallbackRemover, EventRegistrationToken>::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { + hr = (d->cameraButtons.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } #endif for (QHash<CoreApplicationCallbackRemover, EventRegistrationToken>::const_iterator i = d->applicationTokens.begin(); i != d->applicationTokens.end(); ++i) { hr = (d->application.Get()->*i.key())(i.value()); @@ -268,6 +296,42 @@ HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEvent args->put_Handled(pressed || released); return S_OK; } + +HRESULT QWinRTIntegration::onCameraPressed(IInspectable *, ICameraEventArgs *) +{ + Q_D(QWinRTIntegration); + QWindow *window = d->mainScreen->topWindow(); + QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyPress, Qt::Key_Camera, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); + d->cameraPressed = true; + return S_OK; +} + +HRESULT QWinRTIntegration::onCameraHalfPressed(IInspectable *, ICameraEventArgs *) +{ + Q_D(QWinRTIntegration); + QWindow *window = d->mainScreen->topWindow(); + QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyPress, Qt::Key_CameraFocus, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); + d->cameraHalfPressed = true; + return S_OK; +} + +HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *) +{ + Q_D(QWinRTIntegration); + QWindow *window = d->mainScreen->topWindow(); + if (d->cameraHalfPressed) + QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyRelease, Qt::Key_CameraFocus, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); + + if (d->cameraPressed) + QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyRelease, Qt::Key_Camera, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); + d->cameraHalfPressed = false; + d->cameraPressed = false; + return S_OK; +} #endif // Q_OS_WINPHONE HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *) diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 3a151e1ed8..5456f6922f 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -52,6 +52,7 @@ namespace ABI { namespace UI { namespace Input { struct IBackPressedEventArgs; + struct ICameraEventArgs; } } } @@ -100,6 +101,9 @@ public: private: #ifdef Q_OS_WINPHONE HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args); + HRESULT onCameraPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); + HRESULT onCameraHalfPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); + HRESULT onCameraReleased(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); #endif HRESULT onSuspended(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *); HRESULT onResume(IInspectable *, IInspectable *); diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index 2f666bebfd..15cf4cf241 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -3,14 +3,14 @@ Requires libxcb >= 1.5. PACKAGE DEPENDENCIES Required packages: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev On Ubuntu 11.10 icccm1 is replaced by icccm4 and xcb-render-util is not available: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-glx0-dev libxcb-xinerama0-dev The packages for xcb-render-util can be installed manually from http://packages.ubuntu.com/natty/libxcb-render-util0 and http://packages.ubuntu.com/natty/libxcb-render-util0-dev On Ubuntu 12.04 icccm1 is replaced by icccm4 and xcb-render-util can be installed automatically: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-glx0-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm4 libxcb-icccm4-dev libxcb-sync0 libxcb-sync0-dev libxcb-xfixes0-dev libxrender-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0 libxcb-render-util0-dev libxcb-glx0-dev libxcb-xinerama0-dev On Fedora, the following packages are required: diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index e1fb63fbc4..208170de37 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -175,7 +175,11 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) { if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) +#if defined(QT_OPENGL_ES_2) + m_format.setRenderableType(QSurfaceFormat::OpenGLES); +#else m_format.setRenderableType(QSurfaceFormat::OpenGL); +#endif if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES) return; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index e28d84cf92..f16bebb758 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -60,6 +60,7 @@ #include <xcb/shm.h> #include <xcb/sync.h> #include <xcb/xfixes.h> +#include <xcb/xinerama.h> #ifdef XCB_USE_XLIB #include <X11/Xlib.h> @@ -386,6 +387,7 @@ void QXcbConnection::initializeScreens() xcb_screen_t *xcbScreen = it.data; QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber); m_virtualDesktops.append(virtualDesktop); + QList<QPlatformScreen *> siblings; if (has_randr_extension) { xcb_generic_error_t *error = NULL; // RRGetScreenResourcesCurrent is fast but it may return nothing if the @@ -429,7 +431,6 @@ void QXcbConnection::initializeScreens() qWarning("failed to get the primary output of the screen"); free(error); } else { - QList<QPlatformScreen *> siblings; for (int i = 0; i < outputCount; i++) { QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output( xcb_randr_get_output_info_reply(xcb_connection(), @@ -471,12 +472,30 @@ void QXcbConnection::initializeScreens() } } } - virtualDesktop->setScreens(siblings); } } } + } else if (has_xinerama_extension) { + // Xinerama is available + xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(m_connection); + xcb_xinerama_query_screens_reply_t *screens = xcb_xinerama_query_screens_reply(m_connection, + cookie, + Q_NULLPTR); + if (screens) { + xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens); + while (it.rem) { + xcb_xinerama_screen_info_t *screen_info = it.data; + QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, + XCB_NONE, Q_NULLPTR, + screen_info, it.index); + siblings << screen; + m_screens << screen; + xcb_xinerama_screen_info_next(&it); + } + free(screens); + } } - if (virtualDesktop->screens().isEmpty()) { + if (siblings.isEmpty()) { // If there are no XRandR outputs or XRandR extension is missing, // then create a fake/legacy screen. QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, XCB_NONE, Q_NULLPTR); @@ -486,8 +505,9 @@ void QXcbConnection::initializeScreens() primaryScreen = screen; primaryScreen->setPrimary(true); } - virtualDesktop->addScreen(screen); + siblings << screen; } + virtualDesktop->setScreens(siblings); xcb_screen_next(&it); ++xcbScreenNumber; } // for each xcb screen @@ -529,12 +549,14 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , xfixes_first_event(0) , xrandr_first_event(0) , xkb_first_event(0) + , has_xinerama_extension(false) , has_shape_extension(false) , has_randr_extension(false) , has_input_shape(false) , has_xkb(false) , m_buttons(0) , m_focusWindow(0) + , m_mouseGrabber(0) , m_clientLeader(0) , m_systemTrayTracker(0) , m_glIntegration(Q_NULLPTR) @@ -583,7 +605,10 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_time = XCB_CURRENT_TIME; m_netWmUserTime = XCB_CURRENT_TIME; - initializeXRandr(); + if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR")) + initializeXRandr(); + if (!has_randr_extension) + initializeXinerama(); initializeXFixes(); initializeScreens(); @@ -1331,6 +1356,10 @@ void QXcbConnection::setFocusWindow(QXcbWindow *w) { m_focusWindow = w; } +void QXcbConnection::setMouseGrabber(QXcbWindow *w) +{ + m_mouseGrabber = w; +} void QXcbConnection::grabServer() { @@ -2090,6 +2119,22 @@ void QXcbConnection::initializeXRandr() } } +void QXcbConnection::initializeXinerama() +{ + const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xinerama_id); + if (!reply || !reply->present) + return; + + xcb_generic_error_t *error = Q_NULLPTR; + xcb_xinerama_is_active_cookie_t xinerama_query_cookie = xcb_xinerama_is_active(m_connection); + xcb_xinerama_is_active_reply_t *xinerama_is_active = xcb_xinerama_is_active_reply(m_connection, + xinerama_query_cookie, + &error); + has_xinerama_extension = xinerama_is_active && !error && xinerama_is_active->state; + free(error); + free(xinerama_is_active); +} + void QXcbConnection::initializeXShape() { const xcb_query_extension_reply_t *xshape_reply = xcb_get_extension_data(m_connection, &xcb_shape_id); @@ -2177,7 +2222,9 @@ void QXcbConnection::initializeXKB() bool QXcbConnection::xi2MouseEvents() const { static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE"); - return mouseViaXI2; + // Don't use XInput2 when Xinerama extension is enabled, + // because it causes problems with multi-monitor setup. + return mouseViaXI2 && !has_xinerama_extension; } #if defined(XCB_USE_XINPUT2) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 4acca7d374..6fa7532555 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -469,6 +469,8 @@ public: QXcbWindow *focusWindow() const { return m_focusWindow; } void setFocusWindow(QXcbWindow *); + QXcbWindow *mouseGrabber() const { return m_mouseGrabber; } + void setMouseGrabber(QXcbWindow *); QByteArray startupId() const { return m_startupId; } void setStartupId(const QByteArray &nextId) { m_startupId = nextId; } @@ -515,6 +517,7 @@ private: void initializeXFixes(); void initializeXRender(); void initializeXRandr(); + void initializeXinerama(); void initializeXShape(); void initializeXKB(); void handleClientMessageEvent(const xcb_client_message_event_t *event); @@ -643,6 +646,7 @@ private: uint32_t xrandr_first_event; uint32_t xkb_first_event; + bool has_xinerama_extension; bool has_shape_extension; bool has_randr_extension; bool has_input_shape; @@ -651,6 +655,7 @@ private: Qt::MouseButtons m_buttons; QXcbWindow *m_focusWindow; + QXcbWindow *m_mouseGrabber; xcb_window_t m_clientLeader; QByteArray m_startupId; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 1a123703a5..1b84de4834 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -274,7 +274,7 @@ void QXcbConnection::finalizeXInput2() void QXcbConnection::xi2Select(xcb_window_t window) { - if (!m_xi2Enabled) + if (!m_xi2Enabled || window == rootWindow()) return; Display *xDisplay = static_cast<Display *>(m_xlib_display); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index d19ea241f1..9296a6d141 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -194,6 +194,8 @@ void QXcbDrag::startDrag() setUseCompositing(current_virtual_desktop->compositingActive()); QBasicDrag::startDrag(); + if (connection()->mouseGrabber() == Q_NULLPTR) + shapedPixmapWindow()->setMouseGrabEnabled(true); } void QXcbDrag::endDrag() diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 9b1b9fcbb0..caddd2b2a5 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -155,8 +155,15 @@ void QXcbVirtualDesktop::updateWorkArea() } } +static inline QSizeF sizeInMillimeters(const QSize &size, const QDpi &dpi) +{ + return QSizeF(Q_MM_PER_INCH * size.width() / dpi.first, + Q_MM_PER_INCH * size.height() / dpi.second); +} + QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, - xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output) + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, + const xcb_xinerama_screen_info_t *xineramaScreenInfo, int xineramaScreenIdx) : QXcbObject(connection) , m_virtualDesktop(virtualDesktop) , m_output(outputId) @@ -188,6 +195,14 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe updateRefreshRate(crtc->mode); free(crtc); } + } else if (xineramaScreenInfo) { + m_geometry = QRect(xineramaScreenInfo->x_org, xineramaScreenInfo->y_org, + xineramaScreenInfo->width, xineramaScreenInfo->height); + m_nativeGeometry = m_geometry; + m_availableGeometry = m_geometry & m_virtualDesktop->workArea(); + m_sizeMillimeters = sizeInMillimeters(m_geometry.size(), virtualDpi()); + if (xineramaScreenIdx > -1) + m_outputName += QLatin1Char('-') + QString::number(xineramaScreenIdx); } if (m_geometry.isEmpty()) { @@ -536,11 +551,8 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) // It can be that physical size is unknown while virtual size // is known (probably back-calculated from DPI and resolution), // e.g. on VNC or with some hardware. - if (m_sizeMillimeters.isEmpty()) { - QDpi dpi = virtualDpi(); - m_sizeMillimeters = QSizeF(Q_MM_PER_INCH * xGeometry.width() / dpi.first, - Q_MM_PER_INCH * xGeometry.width() / dpi.second); - } + if (m_sizeMillimeters.isEmpty()) + m_sizeMillimeters = sizeInMillimeters(xGeometry.size(), virtualDpi()); qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4); m_pixelDensity = qRound(dpi/96); diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 79620f40ec..dd7396aca2 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -40,6 +40,7 @@ #include <xcb/xcb.h> #include <xcb/randr.h> #include <xcb/xfixes.h> +#include <xcb/xinerama.h> #include "qxcbobject.h" #include "qxcbscreen.h" @@ -102,7 +103,8 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen { public: QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop, - xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo); + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *outputInfo, + const xcb_xinerama_screen_info_t *xineramaScreenInfo = Q_NULLPTR, int xineramaScreenIdx = -1); ~QXcbScreen(); QString getOutputName(xcb_randr_get_output_info_reply_t *outputInfo); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index ae81674eca..f030252865 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -594,12 +594,16 @@ QXcbWindow::~QXcbWindow() { if (window()->type() != Qt::ForeignWindow) destroy(); + else if (connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); } void QXcbWindow::destroy() { if (connection()->focusWindow() == this) doFocusOut(); + if (connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); if (m_syncCounter && m_usingSyncProtocol) Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); @@ -847,6 +851,9 @@ void QXcbWindow::hide() xcb_flush(xcb_connection()); + if (connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); + m_mapped = false; } @@ -2367,6 +2374,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev QWindowSystemInterface::handleWindowStateChanged(window(), newState); m_lastWindowStateEvent = newState; m_windowState = newState; + if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); } return; } else if (event->atom == atom(QXcbAtom::_NET_FRAME_EXTENTS)) { @@ -2421,9 +2430,15 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) bool QXcbWindow::setMouseGrabEnabled(bool grab) { + if (!grab && connection()->mouseGrabber() == this) + connection()->setMouseGrabber(Q_NULLPTR); #ifdef XCB_USE_XINPUT22 - if (connection()->xi2MouseEvents()) - return connection()->xi2SetMouseGrabEnabled(m_window, grab); + if (connection()->xi2MouseEvents()) { + bool result = connection()->xi2SetMouseGrabEnabled(m_window, grab); + if (grab && result) + connection()->setMouseGrabber(this); + return result; + } #endif if (grab && !connection()->canGrab()) return false; @@ -2442,6 +2457,8 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab) xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL); bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS); free(reply); + if (result) + connection()->setMouseGrabber(this); return result; } diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro index d0fe282b14..20481e4834 100644 --- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro +++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro @@ -1,7 +1,8 @@ # # Statically compile in code for # libxcb-fixes, libxcb-randr, libxcb-shm, libxcb-sync, libxcb-image, -# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb +# libxcb-keysyms, libxcb-icccm, libxcb-renderutil, libxcb-xkb, +# libxcb-xinerama # CONFIG += static load(qt_helper_lib) @@ -28,7 +29,8 @@ SOURCES += \ $$LIBXCB_DIR/sync.c \ $$LIBXCB_DIR/render.c \ $$LIBXCB_DIR/shape.c \ - $$LIBXCB_DIR/xkb.c + $$LIBXCB_DIR/xkb.c \ + $$LIBXCB_DIR/xinerama.c # # xcb-util diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 60eb8a02e3..302d87e007 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -92,7 +92,7 @@ contains(QT_CONFIG, xcb-qt) { INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static } else { - LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms + LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms -lxcb-xinerama !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb } diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp index 2a3585464f..4af91ded27 100644 --- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp +++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp @@ -71,6 +71,9 @@ Q_SIGNALS: protected: static void onResponse(QGtk3Dialog *dialog, int response); +private slots: + void onParentWindowDestroyed(); + private: GtkWidget *gtkWidget; }; @@ -108,6 +111,8 @@ void QGtk3Dialog::exec() bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { + connect(parent, &QWindow::destroyed, this, &QGtk3Dialog::onParentWindowDestroyed, + Qt::UniqueConnection); setParent(parent); setFlags(flags); setModality(modality); @@ -146,6 +151,12 @@ void QGtk3Dialog::onResponse(QGtk3Dialog *dialog, int response) emit dialog->reject(); } +void QGtk3Dialog::onParentWindowDestroyed() +{ + // The QGtk3*DialogHelper classes own this object. Make sure the parent doesn't delete it. + setParent(0); +} + QGtk3ColorDialogHelper::QGtk3ColorDialogHelper() { d.reset(new QGtk3Dialog(gtk_color_chooser_dialog_new("", 0))); |