From 33c9059f03a67d83123933426ea9164d57399d4c Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sun, 9 Aug 2015 13:47:12 +0300 Subject: Fix XI2 smooth scroll with inverted direction When touchpad scroll direction is inverted, verticalIncrement and horizontalIncrement of scrollingDevice are negative, and rawDelta remains unfilled. It leads to pixelDelta.isNull() being true in wheel event handler even when XI2 smooth scrolling is available on the system. Fix that and fill rawDelta with correct values when inverted scroll direction is used. Change-Id: I9c0bdbad2c6b9bbed765eaa895dca300c5c70e86 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d7688be0ff..5aa1933859 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -859,6 +859,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin // We do not set "pixel" delta if it is only measured in ticks. if (scrollingDevice.verticalIncrement > 1) rawDelta.setY(delta); + else if (scrollingDevice.verticalIncrement < -1) + rawDelta.setY(-delta); } } if (scrollingDevice.orientations & Qt::Horizontal) { @@ -869,6 +871,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin // We do not set "pixel" delta if it is only measured in ticks. if (scrollingDevice.horizontalIncrement > 1) rawDelta.setX(delta); + else if (scrollingDevice.horizontalIncrement < -1) + rawDelta.setX(-delta); } } if (!angleDelta.isNull()) { -- cgit v1.2.3 From c8af3160d2514fb973a0d00d5bac324d4f7159f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= Date: Fri, 8 Jan 2016 04:12:13 +0200 Subject: Don't pass NULL Display to glXGetClientString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glXGetCurrentDisplay can return NULL so need to check for that. Change-Id: I1b85a5c575d1deb24dcce4719b6f737283adeabe Reviewed-by: Błażej Szczygieł Reviewed-by: Laszlo Agocs --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 5 ++++- .../platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'src/plugins') 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 8b14fc7d70..3412f3f3fc 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -644,7 +644,10 @@ void QGLXContext::queryDummyContext() oldSurface = oldContext->surface(); QScopedPointer surface; - const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + Display *display = glXGetCurrentDisplay(); + const char *glxvendor = 0; + if (display) + glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) { QWindow *window = new QWindow; window->resize(64, 64); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index ce72cb64d0..cd4949af5c 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -195,7 +195,10 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO static bool glxPbufferUsable = true; if (!vendorChecked) { vendorChecked = true; - const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + Display *display = glXGetCurrentDisplay(); + const char *glxvendor = 0; + if (display) + glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) glxPbufferUsable = false; } -- cgit v1.2.3 From eef772577594b59d9cee5d55da5c47cd81008735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 12 Jan 2016 13:02:05 +0100 Subject: eglfs: Round value returned from pixelDensity() Avoid returning fractional scale factors, which we do not support. This matches the pixelDensity() implementation for the Xcb and Windows platform plugins. Change-Id: I79156e802a0a436b9344f12d35d1f4861e20e7fa Reviewed-by: Mitch Curtis --- src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index 8af48a893b..1fb6020d69 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -224,7 +224,7 @@ QDpi QEGLDeviceIntegration::logicalDpi() const qreal QEGLDeviceIntegration::pixelDensity() const { - return logicalDpi().first / qreal(100); + return qRound(logicalDpi().first / qreal(100)); } Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const -- cgit v1.2.3 From a9c0a83207599599c2ff67ff00fc7e0cc638a870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Wed, 13 Jan 2016 13:17:43 +0100 Subject: xcb: Don't duplicate expose events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ExposeCompressor for mapping the window to prevent duplicating expose event when window is mapped. Remove sending expose event from configure notivy event. Change-Id: I6836c06047ffebd65775aa8aca90750afba6efe8 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/xcb/qxcbwindow.cpp | 37 ++++++++++++++------------------ src/plugins/platforms/xcb/qxcbwindow.h | 2 ++ 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4e4a0cdaef..c6eb5aa66b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1885,6 +1885,17 @@ private: bool m_pending; }; +bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion) +{ + ExposeCompressor compressor(m_window, &exposeRegion); + xcb_generic_event_t *filter = 0; + do { + filter = connection()->checkEvent(compressor); + free(filter); + } while (filter); + return compressor.pending(); +} + bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) { return QWindowSystemInterface::handleNativeEvent(window(), @@ -1902,15 +1913,10 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) else m_exposeRegion |= rect; - ExposeCompressor compressor(m_window, &m_exposeRegion); - xcb_generic_event_t *filter = 0; - do { - filter = connection()->checkEvent(compressor); - free(filter); - } while (filter); + bool pending = compressExposeEvent(m_exposeRegion); // if count is non-zero there are more expose events pending - if (event->count == 0 || !compressor.pending()) { + if (event->count == 0 || !pending) { QWindowSystemInterface::handleExposeEvent(window(), m_exposeRegion); m_exposeRegion = QRegion(); } @@ -1997,10 +2003,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } } - // The original geometry requested by setGeometry() might be different - // from what we end up with after applying window constraints. - QRect requestedGeometry = geometry(); - const QRect actualGeometry = QRect(pos, QSize(event->width, event->height)); QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry); if (!newScreen) @@ -2021,15 +2023,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * // will make the comparison later. QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - // For expose events we have no way of telling QGuiApplication to used the locally - // cached version of the previous state, so we may in some situations end up with - // an additional expose event. - QRect previousGeometry = requestedGeometry != actualGeometry ? - requestedGeometry : qt_window_private(window())->geometry; - - if (m_mapped && actualGeometry.size() != previousGeometry.size()) - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size())); - if (m_usingSyncProtocol && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; @@ -2096,7 +2089,9 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) if (m_deferredActivation) requestActivateWindow(); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + QRegion exposeRegion = QRect(QPoint(), geometry().size()); + compressExposeEvent(exposeRegion); + QWindowSystemInterface::handleExposeEvent(window(), exposeRegion); } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 3cfa71c9e0..d2c02fe3df 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -201,6 +201,8 @@ protected: void doFocusIn(); void doFocusOut(); + bool compressExposeEvent(QRegion &exposeRegion); + void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); -- cgit v1.2.3 From c3376ed3f90179586aa7a82730fa972dcd4cf5cd Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 13 Jan 2016 12:57:18 +0100 Subject: winrt: enable hardware buttons for Windows 10 Previously the hardware and camera button handler were guarded inside a Q_OS_WINPHONE which does not apply to Windows 10. Instead use WINAPI_PARTITION_FAMILY like on other places, this covers Windows Phone 8.1 as well as Windows 10. To find windows.phone.ui.input.h at build time the Mobile Extension directory needs to be added to the include paths inside qmake. On runtime we need to check whether we have hardware buttons or not. In case they exist, register the handlers, otherwise skip registration. Skipping also helps to keep WACK succeeding. Task-number: QTBUG-50427 Change-Id: Ibeae15dbde12553cebd2b73b1a40b754c014f426 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtintegration.cpp | 97 +++++++++++++++-------- src/plugins/platforms/winrt/qwinrtintegration.h | 4 +- 2 files changed, 64 insertions(+), 37 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 71e92f33ca..2281bf56cc 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -59,10 +59,16 @@ #include #include #include -#ifdef Q_OS_WINPHONE + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) # include +# if _MSC_VER >= 1900 +# include + using namespace ABI::Windows::Foundation::Metadata; +# endif #endif + using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; @@ -73,13 +79,13 @@ using namespace ABI::Windows::UI::Core; using namespace ABI::Windows::UI::ViewManagement; using namespace ABI::Windows::Graphics::Display; using namespace ABI::Windows::ApplicationModel::Core; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) using namespace ABI::Windows::Phone::UI::Input; #endif typedef IEventHandler ResumeHandler; typedef IEventHandler SuspendHandler; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) typedef IEventHandler BackPressedHandler; typedef IEventHandler CameraButtonHandler; #endif @@ -88,7 +94,7 @@ QT_BEGIN_NAMESPACE typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken); uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken); uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken); @@ -105,11 +111,12 @@ public: ComPtr application; QHash applicationTokens; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) ComPtr hardwareButtons; QHash buttonsTokens; ComPtr cameraButtons; QHash cameraTokens; + boolean hasHardwareButtons; bool cameraHalfPressed : 1; bool cameraPressed : 1; #endif @@ -132,31 +139,48 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) &d->applicationTokens[&ICoreApplication::remove_Resuming]); Q_ASSERT_SUCCEEDED(hr); -#ifdef Q_OS_WINPHONE - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), - IID_PPV_ARGS(&d->hardwareButtons)); - Q_ASSERT_SUCCEEDED(hr); - hr = d->hardwareButtons->add_BackPressed(Callback(this, &QWinRTIntegration::onBackButtonPressed).Get(), - &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); - Q_ASSERT_SUCCEEDED(hr); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) +#if _MSC_VER >= 1900 + d->hasHardwareButtons = false; + ComPtr apiInformationStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(), + IID_PPV_ARGS(&apiInformationStatics)); - 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(this, &QWinRTIntegration::onCameraPressed).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]); + if (SUCCEEDED(hr)) { + const HStringReference valueRef(L"Windows.Phone.UI.Input.HardwareButtons"); + hr = apiInformationStatics->IsTypePresent(valueRef.Get(), &d->hasHardwareButtons); + } +#else + d->hasHardwareButtons = true; +#endif // _MSC_VER >= 1900 + + if (d->hasHardwareButtons) { + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), + IID_PPV_ARGS(&d->hardwareButtons)); Q_ASSERT_SUCCEEDED(hr); - hr = d->cameraButtons->add_CameraHalfPressed(Callback(this, &QWinRTIntegration::onCameraHalfPressed).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]); + hr = d->hardwareButtons->add_BackPressed(Callback(this, &QWinRTIntegration::onBackButtonPressed).Get(), + &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); Q_ASSERT_SUCCEEDED(hr); - hr = d->cameraButtons->add_CameraReleased(Callback(this, &QWinRTIntegration::onCameraReleased).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]); + + 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(this, &QWinRTIntegration::onCameraPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraHalfPressed(Callback(this, &QWinRTIntegration::onCameraHalfPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraReleased(Callback(this, &QWinRTIntegration::onCameraReleased).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]); + Q_ASSERT_SUCCEEDED(hr); + } + d->cameraPressed = false; + d->cameraHalfPressed = false; } - d->cameraPressed = false; - d->cameraHalfPressed = false; -#endif // Q_OS_WINPHONE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + QEventDispatcherWinRT::runOnXamlThread([d]() { d->mainScreen = new QWinRTScreen; @@ -172,14 +196,17 @@ QWinRTIntegration::~QWinRTIntegration() { Q_D(QWinRTIntegration); HRESULT hr; -#ifdef Q_OS_WINPHONE - for (QHash::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) { - hr = (d->hardwareButtons.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); - } - for (QHash::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { - hr = (d->cameraButtons.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + if (d->hasHardwareButtons) { + for (QHash::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) { + hr = (d->hardwareButtons.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } + for (QHash::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { + hr = (d->cameraButtons.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } } #endif // Do not execute this on Windows Phone as the application is already @@ -289,7 +316,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &name) cons // System-level integration points -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args) { Q_D(QWinRTIntegration); @@ -339,7 +366,7 @@ HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *) d->cameraPressed = false; return S_OK; } -#endif // Q_OS_WINPHONE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *) { diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 31a3ce7c1c..9bf5d27973 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -47,7 +47,7 @@ namespace ABI { namespace Foundation { struct IAsyncAction; } -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) namespace Phone { namespace UI { namespace Input { @@ -100,7 +100,7 @@ public: QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; private: -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) 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 *); -- cgit v1.2.3 From 18119a58def4e3537dd92b86e9c6115e6a21e866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Thu, 14 Jan 2016 01:50:38 +0100 Subject: xcb: Don't clear alpha on every repaint Since 1bcfc3de7586ddb9f5d1b778b97b26ae3dc9584d every image has alpha in XCB even if it is not used by window. This patch prevents clearing the alpha channel on every repaint when window is not transparent. Change-Id: Icfdd39f8636401906ace77ea3c2fa25386979d5f Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 006df320fe..c34bea0242 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -67,6 +67,8 @@ public: QSize size() const { return m_qimage.size(); } + bool hasAlpha() const { return m_hasAlpha; } + void put(xcb_window_t window, const QPoint &dst, const QRect &source); void preparePaint(const QRegion ®ion); @@ -84,6 +86,8 @@ private: xcb_window_t m_gc_window; QRegion m_dirty; + + bool m_hasAlpha; }; class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer @@ -173,7 +177,8 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed"; } - if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::IgnoresAlpha) + m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; + if (!m_hasAlpha) format = qt_alphaVersionForPainting(format); m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); @@ -324,7 +329,7 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) m_paintRegion = region; m_image->preparePaint(m_paintRegion); - if (m_image->image()->hasAlphaChannel()) { + if (m_image->hasAlpha()) { QPainter p(paintDevice()); p.setCompositionMode(QPainter::CompositionMode_Source); const QVector rects = m_paintRegion.rects(); -- cgit v1.2.3 From b6c086ad6cc3525013abc225d96c53c392a04756 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 14 Jan 2016 15:57:54 +0100 Subject: Windows/Direct2D QPA plugins: Fix overrides. Fix warnings found by clang. Change-Id: Ia8e7a271e9d33011eded1e63e61dbcaeaf692600 Reviewed-by: Joerg Bornemann --- .../direct2d/qwindowsdirect2dbackingstore.h | 4 +- .../direct2d/qwindowsdirect2dplatformpixmap.h | 3 +- .../platforms/windows/qwindowsdialoghelpers.cpp | 52 +++++++++++----------- src/plugins/platforms/windows/qwindowsdrag.cpp | 2 +- .../platforms/windows/qwindowsfontdatabase_ft.h | 11 +++-- src/plugins/platforms/windows/qwindowsfontengine.h | 2 +- .../windows/qwindowsfontenginedirectwrite.h | 42 ++++++++--------- .../platforms/windows/qwindowsintegration.h | 8 ++-- src/plugins/platforms/windows/qwindowsmime.cpp | 48 ++++++++++---------- src/plugins/platforms/windows/qwindowstheme.h | 4 +- src/plugins/platforms/windows/qwindowswindow.h | 12 ++--- 11 files changed, 95 insertions(+), 93 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h index 1c7f65a12d..08bfaa1240 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h @@ -48,8 +48,8 @@ public: QWindowsDirect2DBackingStore(QWindow *window); ~QWindowsDirect2DBackingStore(); - void beginPaint(const QRegion &); - void endPaint(); + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + void endPaint() Q_DECL_OVERRIDE; QPaintDevice *paintDevice() Q_DECL_OVERRIDE; void flush(QWindow *targetWindow, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h index 5720f84853..a9591a493a 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h @@ -54,8 +54,7 @@ public: ~QWindowsDirect2DPlatformPixmap(); void resize(int width, int height) Q_DECL_OVERRIDE; - virtual void fromImage(const QImage &image, - Qt::ImageConversionFlags flags); + void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE; int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE; void fill(const QColor &color) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index b983ba3354..9211fd1320 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -876,12 +876,12 @@ public: inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &title); + void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options); inline void setDirectory(const QUrl &directory); inline void updateDirectory() { setDirectory(m_data.directory()); } inline QString directory() const; - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; virtual void setNameFilters(const QStringList &f); inline void selectNameFilter(const QString &filter); inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); } @@ -910,7 +910,7 @@ signals: void filterSelected(const QString & filter); public slots: - virtual void close(); + void close() Q_DECL_OVERRIDE; protected: explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data); @@ -1460,9 +1460,9 @@ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual void setNameFilters(const QStringList &f); - virtual QList selectedFiles() const; - virtual QList dialogResult() const; + void setNameFilters(const QStringList &f) Q_DECL_OVERRIDE; + QList selectedFiles() const Q_DECL_OVERRIDE; + QList dialogResult() const Q_DECL_OVERRIDE; }; // Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo". @@ -1531,8 +1531,8 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual QList selectedFiles() const; - virtual QList dialogResult() const; + QList selectedFiles() const Q_DECL_OVERRIDE; + QList dialogResult() const Q_DECL_OVERRIDE; private: inline IFileOpenDialog *openFileDialog() const @@ -1616,7 +1616,7 @@ public: virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsNativeFileDialogBase *nativeFileDialog() const { return static_cast(nativeDialog()); } @@ -1744,14 +1744,13 @@ public: static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &t) { m_title = t; } - virtual void doExec(HWND owner = 0); - virtual QPlatformDialogHelper::DialogCode result() const { return m_result; } + void setWindowTitle(const QString &t) Q_DECL_OVERRIDE { m_title = t; } + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam); public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW); @@ -1987,19 +1986,19 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase selectedFiles() const Q_DECL_OVERRIDE; - virtual void setFilter() Q_DECL_OVERRIDE {} - virtual void selectNameFilter(const QString &) Q_DECL_OVERRIDE; - virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; + void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; + QUrl directory() const Q_DECL_OVERRIDE; + void selectFile(const QUrl &url) Q_DECL_OVERRIDE; + QList selectedFiles() const Q_DECL_OVERRIDE; + void setFilter() Q_DECL_OVERRIDE {} + void selectNameFilter(const QString &) Q_DECL_OVERRIDE; + QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsXpNativeFileDialog *nativeFileDialog() const { return static_cast(nativeDialog()); } @@ -2073,14 +2072,13 @@ public: explicit QWindowsNativeColorDialog(const SharedPointerColor &color); - virtual void setWindowTitle(const QString &) {} - virtual QPlatformDialogHelper::DialogCode result() const { return m_code; } + void setWindowTitle(const QString &) Q_DECL_OVERRIDE {} public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; COLORREF m_customColors[CustomColorCount]; QPlatformDialogHelper::DialogCode m_code; diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 021058fa33..16079576a2 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -78,7 +78,7 @@ public: void setPixmap(const QPixmap &p); protected: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE { QPainter painter(this); painter.drawPixmap(0, 0, m_pixmap); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index ad5c005ffa..f65dc38801 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -43,12 +43,15 @@ QT_BEGIN_NAMESPACE class QWindowsFontDatabaseFT : public QBasicFontDatabase { public: - void populateFontDatabase(); + void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, + QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const Q_DECL_OVERRIDE; QString fontDir() const Q_DECL_OVERRIDE; QFont defaultFont() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 409b44264e..5317368455 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -84,7 +84,7 @@ public: void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; HGDIOBJ selectDesignFont() const; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index cee8691d69..07e040ed33 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -61,35 +61,37 @@ public: void initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font); - QFixed lineThickness() const; - QFixed underlinePosition() const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - QFixed emSquareSize() const; + QFixed lineThickness() const Q_DECL_OVERRIDE; + QFixed underlinePosition() const Q_DECL_OVERRIDE; + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE; + QFixed emSquareSize() const Q_DECL_OVERRIDE; glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const; - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const; + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, + ShaperFlags flags) const Q_DECL_OVERRIDE; + void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE; void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - glyph_metrics_t boundingBox(glyph_t g); - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat); + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE; + glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE; + glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, + const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE; - QFixed ascent() const; - QFixed descent() const; - QFixed leading() const; - QFixed xHeight() const; - qreal maxCharWidth() const; + QFixed ascent() const Q_DECL_OVERRIDE; + QFixed descent() const Q_DECL_OVERRIDE; + QFixed leading() const Q_DECL_OVERRIDE; + QFixed xHeight() const Q_DECL_OVERRIDE; + qreal maxCharWidth() const Q_DECL_OVERRIDE; - bool supportsSubPixelPositions() const; + bool supportsSubPixelPositions() const Q_DECL_OVERRIDE; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t); - QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform); + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE; + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE; - QFontEngine *cloneWithSize(qreal pixelSize) const; + QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; const QSharedPointer &fontEngineData() const { return m_fontEngineData; } diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index cb10bf08f5..da20d9261a 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -60,12 +60,12 @@ public: explicit QWindowsIntegration(const QStringList ¶mList); virtual ~QWindowsIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QOpenGLContext::OpenGLModuleType openGLModuleType(); + QOpenGLContext::OpenGLModuleType openGLModuleType() Q_DECL_OVERRIDE; static QWindowsStaticOpenGLContext *staticOpenGLContext(); #endif QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; @@ -83,7 +83,7 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QStringList themeNames() const Q_DECL_OVERRIDE; QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; - QPlatformServices *services() const; + QPlatformServices *services() const Q_DECL_OVERRIDE; QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 0a2ba9b0e7..171ace5c20 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -897,14 +897,14 @@ public: QWindowsMimeHtml(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: int CF_HTML; @@ -1029,14 +1029,14 @@ class QWindowsMimeImage : public QWindowsMime public: QWindowsMimeImage(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: bool hasOriginalDIBV5(IDataObject *pDataObj) const; UINT CF_PNG; @@ -1183,14 +1183,14 @@ public: QBuiltInMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap outFormats; @@ -1303,14 +1303,14 @@ public: QLastResortMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap formats; diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index b2f8e13b64..fc004b68c8 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -51,9 +51,9 @@ public: bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE; QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE; QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE; - virtual const QPalette *palette(Palette type = SystemPalette) const + const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE { return m_palettes[type]; } - virtual const QFont *font(Font type = SystemFont) const + const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE { return m_fonts[type]; } QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 710cab8597..6fffa1e6e9 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -171,7 +171,7 @@ public: void raise() Q_DECL_OVERRIDE; void lower() Q_DECL_OVERRIDE; - void windowEvent(QEvent *event); + void windowEvent(QEvent *event) Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE; static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp); @@ -189,8 +189,8 @@ public: bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE; - void setFrameStrutEventsEnabled(bool enabled); - bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); } + void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE; + bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); } QMargins customMargins() const { return m_data.customMargins; } void setCustomMargins(const QMargins &m); @@ -237,15 +237,15 @@ public: void setEnabled(bool enabled); bool isEnabled() const; - void setWindowIcon(const QIcon &icon); + void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; void *surface(void *nativeConfig, int *err); void invalidateSurface() Q_DECL_OVERRIDE; void aboutToMakeCurrent(); #ifndef Q_OS_WINCE - void setAlertState(bool enabled); - bool isAlertState() const { return testFlag(AlertState); } + void setAlertState(bool enabled) Q_DECL_OVERRIDE; + bool isAlertState() const Q_DECL_OVERRIDE { return testFlag(AlertState); } void alertWindow(int durationMs = 0); void stopAlertWindow(); #endif -- cgit v1.2.3 From 1172e18c3c180f2f3641e6c29688199eb5c46650 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 14 Jan 2016 17:48:38 +0100 Subject: Promote backingstore image format to alpha Like xcb does since 1bcfc3de7586ddb9f5d1b778b97b26ae3dc9584d. For TranslucentBackground (ARGB32_Premultiplied) there is no change in practice. For RGB32 we will promote to ARGB32_Premultiplied but everything should behave like before, except that we do not rely on undefined behavior anymore when QOpenGL/QuickWidget is in use. For RGB16 this will enable QOpenGL/QuickWidget since there the hole punching mechanism needs an alpha channel always. Change-Id: Id04ea548cee245ec91642f1358a5e501b62ff64c Reviewed-by: Friedemann Kleint Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/windows/qwindowsbackingstore.cpp | 18 ++++++++++++++---- src/plugins/platforms/windows/qwindowsbackingstore.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 135c9eb601..a6b1d0af26 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -52,7 +53,8 @@ QT_BEGIN_NAMESPACE */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : - QPlatformBackingStore(window) + QPlatformBackingStore(window), + m_alphaNeedsFill(false) { qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window; } @@ -144,8 +146,16 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) << " from: " << (m_image.isNull() ? QSize() : m_image->image().size()); } #endif - const QImage::Format format = window()->format().hasAlpha() ? - QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + QImage::Format format = window()->format().hasAlpha() ? + QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + + // The backingstore composition (enabling render-to-texture widgets) + // punches holes in the backingstores using the alpha channel. Hence + // the need for a true alpha format. + if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha) + m_alphaNeedsFill = true; + else // upgrade but here we know app painting does not rely on alpha hence no need to fill + format = qt_alphaVersionForPainting(format); QWindowsNativeImage *oldwni = m_image.data(); QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format); @@ -186,7 +196,7 @@ void QWindowsBackingStore::beginPaint(const QRegion ®ion) if (QWindowsContext::verbose > 1) qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region; - if (m_image->image().hasAlphaChannel()) { + if (m_alphaNeedsFill) { QPainter p(&m_image->image()); p.setCompositionMode(QPainter::CompositionMode_Source); const QColor blank = Qt::transparent; diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h index 4badcf1b09..1d644923bb 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.h +++ b/src/plugins/platforms/windows/qwindowsbackingstore.h @@ -65,6 +65,7 @@ public: private: QScopedPointer m_image; + bool m_alphaNeedsFill; }; QT_END_NAMESPACE -- cgit v1.2.3 From bfd367c6ec37c9d883c51316a149447b63005011 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 10 Dec 2015 11:01:29 +0100 Subject: Mirclient: update with upstream changes Merge in the changes up to revision 306 of the lp:qtubuntu repo. Change-Id: I55dcb9e06e0a3503d6abe4b0894d5ef5a785b6bb Reviewed-by: Christian Stromme --- src/plugins/platforms/mirclient/mirclient.pro | 2 + .../platforms/mirclient/qmirclientclipboard.cpp | 51 +- .../platforms/mirclient/qmirclientcursor.cpp | 201 ++++++ src/plugins/platforms/mirclient/qmirclientcursor.h | 61 ++ .../platforms/mirclient/qmirclientglcontext.cpp | 14 +- .../platforms/mirclient/qmirclientglcontext.h | 2 +- .../platforms/mirclient/qmirclientinput.cpp | 95 ++- src/plugins/platforms/mirclient/qmirclientinput.h | 13 +- .../platforms/mirclient/qmirclientintegration.cpp | 62 +- .../platforms/mirclient/qmirclientintegration.h | 5 +- .../mirclient/qmirclientnativeinterface.cpp | 29 +- .../mirclient/qmirclientnativeinterface.h | 5 +- .../mirclient/qmirclientorientationchangeevent_p.h | 10 +- .../platforms/mirclient/qmirclientplugin.cpp | 4 +- .../platforms/mirclient/qmirclientscreen.cpp | 21 +- src/plugins/platforms/mirclient/qmirclientscreen.h | 12 +- .../platforms/mirclient/qmirclientwindow.cpp | 710 +++++++++++++-------- src/plugins/platforms/mirclient/qmirclientwindow.h | 33 +- 18 files changed, 956 insertions(+), 374 deletions(-) create mode 100644 src/plugins/platforms/mirclient/qmirclientcursor.cpp create mode 100644 src/plugins/platforms/mirclient/qmirclientcursor.h (limited to 'src/plugins') diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro index 033ce579b9..0851e8d719 100644 --- a/src/plugins/platforms/mirclient/mirclient.pro +++ b/src/plugins/platforms/mirclient/mirclient.pro @@ -21,6 +21,7 @@ PKGCONFIG += egl mirclient ubuntu-platform-api SOURCES = \ qmirclientbackingstore.cpp \ qmirclientclipboard.cpp \ + qmirclientcursor.cpp \ qmirclientglcontext.cpp \ qmirclientinput.cpp \ qmirclientintegration.cpp \ @@ -34,6 +35,7 @@ SOURCES = \ HEADERS = \ qmirclientbackingstore.h \ qmirclientclipboard.h \ + qmirclientcursor.h \ qmirclientglcontext.h \ qmirclientinput.h \ qmirclientintegration.h \ diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp index aa2ddf2103..53246f66c0 100644 --- a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp +++ b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp @@ -87,12 +87,12 @@ void QMirClientClipboard::requestDBusClipboardContents() if (!mPendingGetContentsCall.isNull()) return; - QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents"); + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("GetContents")); mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); - QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*))); + QObject::connect(mPendingGetContentsCall.data(), &QDBusPendingCallWatcher::finished, + this, &QMirClientClipboard::onDBusClipboardGetContentsFinished); } void QMirClientClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call) @@ -143,18 +143,18 @@ void QMirClientClipboard::setupDBus() QDBusConnection dbusConnection = QDBusConnection::sessionBus(); bool ok = dbusConnection.connect( - "com.canonical.QtMir", - "/com/canonical/QtMir/Clipboard", - "com.canonical.QtMir.Clipboard", - "ContentsChanged", + QStringLiteral("com.canonical.QtMir"), + QStringLiteral("/com/canonical/QtMir/Clipboard"), + QStringLiteral("com.canonical.QtMir.Clipboard"), + QStringLiteral("ContentsChanged"), this, SLOT(updateMimeData(QByteArray))); if (!ok) { qCritical("QMirClientClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard."); } - mDBusClipboard = new QDBusInterface("com.canonical.QtMir", - "/com/canonical/QtMir/Clipboard", - "com.canonical.QtMir.Clipboard", + mDBusClipboard = new QDBusInterface(QStringLiteral("com.canonical.QtMir"), + QStringLiteral("/com/canonical/QtMir/Clipboard"), + QStringLiteral("com.canonical.QtMir.Clipboard"), dbusConnection); mDBusSetupDone = true; @@ -162,6 +162,8 @@ void QMirClientClipboard::setupDBus() QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const { + Q_ASSERT(mimeData != nullptr); + const QStringList formats = mimeData->formats(); const int formatCount = qMin(formats.size(), maxFormatsCount); const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int)); @@ -180,12 +182,13 @@ QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const int offset = headerSize; header[0] = formatCount; for (int i = 0; i < formatCount; i++) { + const QByteArray data = mimeData->data(formats[i]); const int formatOffset = offset; const int formatSize = formats[i].size(); const int dataOffset = offset + formatSize; - const int dataSize = mimeData->data(formats[i]).size(); + const int dataSize = data.size(); memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize); - memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize); + memcpy(&buffer[dataOffset], data.data(), dataSize); header[i*4+1] = formatOffset; header[i*4+2] = formatSize; header[i*4+3] = dataOffset; @@ -265,13 +268,15 @@ void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode delete mPendingGetContentsCall.data(); } - QByteArray serializedMimeData = serializeMimeData(mimeData); - if (!serializedMimeData.isEmpty()) { - setDBusClipboardContents(serializedMimeData); - } + if (mimeData != nullptr) { + QByteArray serializedMimeData = serializeMimeData(mimeData); + if (!serializedMimeData.isEmpty()) { + setDBusClipboardContents(serializedMimeData); + } - mMimeData = mimeData; - emitChanged(QClipboard::Clipboard); + mMimeData = mimeData; + emitChanged(QClipboard::Clipboard); + } } bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const @@ -287,6 +292,10 @@ bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardContents) { + if (!mDBusSetupDone) { + setupDBus(); + } + if (!mPendingSetContentsCall.isNull()) { // Ignore any previous set call as we are going to overwrite it anyway QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0); @@ -296,10 +305,10 @@ void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardCo delete mPendingSetContentsCall.data(); } - QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents); + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("SetContents"), clipboardContents); mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); - QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*))); + QObject::connect(mPendingSetContentsCall.data(), &QDBusPendingCallWatcher::finished, + this, &QMirClientClipboard::onDBusClipboardSetContentsFinished); } diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.cpp b/src/plugins/platforms/mirclient/qmirclientcursor.cpp new file mode 100644 index 0000000000..1d6ec8391e --- /dev/null +++ b/src/plugins/platforms/mirclient/qmirclientcursor.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Canonical, Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qmirclientcursor.h" + +#include "qmirclientlogging.h" +#include "qmirclientwindow.h" + +#include + +QMirClientCursor::QMirClientCursor(MirConnection *connection) + : mConnection(connection) +{ + mShapeToCursorName[Qt::ArrowCursor] = "left_ptr"; + mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow"; + mShapeToCursorName[Qt::CrossCursor] = "cross"; + mShapeToCursorName[Qt::WaitCursor] = "watch"; + mShapeToCursorName[Qt::IBeamCursor] = "xterm"; + mShapeToCursorName[Qt::SizeVerCursor] = "size_ver"; + mShapeToCursorName[Qt::SizeHorCursor] = "size_hor"; + mShapeToCursorName[Qt::SizeBDiagCursor] = "size_bdiag"; + mShapeToCursorName[Qt::SizeFDiagCursor] = "size_fdiag"; + mShapeToCursorName[Qt::SizeAllCursor] = "size_all"; + mShapeToCursorName[Qt::BlankCursor] = "blank"; + mShapeToCursorName[Qt::SplitVCursor] = "split_v"; + mShapeToCursorName[Qt::SplitHCursor] = "split_h"; + mShapeToCursorName[Qt::PointingHandCursor] = "hand"; + mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden"; + mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this"; + mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch"; + mShapeToCursorName[Qt::OpenHandCursor] = "openhand"; + mShapeToCursorName[Qt::ClosedHandCursor] = "closedhand"; + mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy"; + mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move"; + mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link"; +} + +namespace { +#if !defined(QT_NO_DEBUG) +const char *qtCursorShapeToStr(Qt::CursorShape shape) +{ + switch (shape) { + case Qt::ArrowCursor: + return "Arrow"; + case Qt::UpArrowCursor: + return "UpArrow"; + case Qt::CrossCursor: + return "Cross"; + case Qt::WaitCursor: + return "Wait"; + case Qt::IBeamCursor: + return "IBeam"; + case Qt::SizeVerCursor: + return "SizeVer"; + case Qt::SizeHorCursor: + return "SizeHor"; + case Qt::SizeBDiagCursor: + return "SizeBDiag"; + case Qt::SizeFDiagCursor: + return "SizeFDiag"; + case Qt::SizeAllCursor: + return "SizeAll"; + case Qt::BlankCursor: + return "Blank"; + case Qt::SplitVCursor: + return "SplitV"; + case Qt::SplitHCursor: + return "SplitH"; + case Qt::PointingHandCursor: + return "PointingHand"; + case Qt::ForbiddenCursor: + return "Forbidden"; + case Qt::WhatsThisCursor: + return "WhatsThis"; + case Qt::BusyCursor: + return "Busy"; + case Qt::OpenHandCursor: + return "OpenHand"; + case Qt::ClosedHandCursor: + return "ClosedHand"; + case Qt::DragCopyCursor: + return "DragCopy"; + case Qt::DragMoveCursor: + return "DragMove"; + case Qt::DragLinkCursor: + return "DragLink"; + case Qt::BitmapCursor: + return "Bitmap"; + default: + return "???"; + } +} +#endif // !defined(QT_NO_DEBUG) +} // anonymous namespace + +void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window) +{ + if (!window) { + return; + } + + MirSurface *surface = static_cast(window->handle())->mirSurface(); + + if (!surface) { + return; + } + + + if (windowCursor) { + DLOG("[ubuntumirclient QPA] changeCursor shape=%s, window=%p\n", qtCursorShapeToStr(windowCursor->shape()), window); + if (!windowCursor->pixmap().isNull()) { + configureMirCursorWithPixmapQCursor(surface, *windowCursor); + } else if (windowCursor->shape() == Qt::BitmapCursor) { + // TODO: Implement bitmap cursor support + applyDefaultCursorConfiguration(surface); + } else { + const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr")); + auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data()); + mir_surface_configure_cursor(surface, cursorConfiguration); + mir_cursor_configuration_destroy(cursorConfiguration); + } + } else { + applyDefaultCursorConfiguration(surface); + } + +} + +void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor) +{ + QImage image = cursor.pixmap().toImage(); + + if (image.format() != QImage::Format_ARGB32) { + image.convertToFormat(QImage::Format_ARGB32); + } + + MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection, + image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software); + + { + MirGraphicsRegion region; + mir_buffer_stream_get_graphics_region(bufferStream, ®ion); + + char *regionLine = region.vaddr; + Q_ASSERT(image.bytesPerLine() <= region.stride); + for (int i = 0; i < image.height(); ++i) { + memcpy(regionLine, image.scanLine(i), image.bytesPerLine()); + regionLine += region.stride; + } + } + + mir_buffer_stream_swap_buffers_sync(bufferStream); + + { + auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y()); + mir_surface_configure_cursor(surface, configuration); + mir_cursor_configuration_destroy(configuration); + } + + mir_buffer_stream_release_sync(bufferStream); +} + +void QMirClientCursor::applyDefaultCursorConfiguration(MirSurface *surface) +{ + auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr"); + mir_surface_configure_cursor(surface, cursorConfiguration); + mir_cursor_configuration_destroy(cursorConfiguration); +} diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.h b/src/plugins/platforms/mirclient/qmirclientcursor.h new file mode 100644 index 0000000000..8bb151ddda --- /dev/null +++ b/src/plugins/platforms/mirclient/qmirclientcursor.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Canonical, Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QMIRCLIENTCURSOR_H +#define QMIRCLIENTCURSOR_H + +#include + +#include +#include + +struct MirConnection; +struct MirSurface; + +class QMirClientCursor : public QPlatformCursor +{ +public: + QMirClientCursor(MirConnection *connection); + void changeCursor(QCursor *windowCursor, QWindow *window) override; +private: + void configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor); + void applyDefaultCursorConfiguration(MirSurface *surface); + QMap mShapeToCursorName; + MirConnection *mConnection; +}; + +#endif // QMIRCLIENTCURSOR_H diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp index bfba5051e5..01db3b8d61 100644 --- a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp +++ b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp @@ -130,19 +130,7 @@ void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface) ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE); #endif - // "Technique" copied from mir, in examples/eglapp.c around line 96 - EGLint newBufferWidth = -1; - EGLint newBufferHeight = -1; - /* - * Querying the surface (actually the current buffer) dimensions here is - * the only truly safe way to be sure that the dimensions we think we - * have are those of the buffer being rendered to. But this should be - * improved in future; https://bugs.launchpad.net/mir/+bug/1194384 - */ - eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &newBufferWidth); - eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &newBufferHeight); - - ubuntuWindow->onBuffersSwapped_threadSafe(newBufferWidth, newBufferHeight); + ubuntuWindow->onSwapBuffersDone(); } void (*QMirClientOpenGLContext::getProcAddress(const QByteArray& procName)) () diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/plugins/platforms/mirclient/qmirclientglcontext.h index cc40298259..29c196ce5c 100644 --- a/src/plugins/platforms/mirclient/qmirclientglcontext.h +++ b/src/plugins/platforms/mirclient/qmirclientglcontext.h @@ -53,7 +53,7 @@ public: bool makeCurrent(QPlatformSurface* surface) override; void doneCurrent() override; bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; } - void (*getProcAddress(const QByteArray& procName)) (); + void (*getProcAddress(const QByteArray& procName)) () override; EGLContext eglContext() const { return mEglContext; } diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp index 56bc21f420..addeda634c 100644 --- a/src/plugins/platforms/mirclient/qmirclientinput.cpp +++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp @@ -163,6 +163,7 @@ QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration) , mEventFilterType(static_cast( integration->nativeInterface())->genericEventFilterType()) , mEventType(static_cast(QEvent::registerEventType())) + , mLastFocusedWindow(nullptr) { // Initialize touch device. mTouchDevice = new QTouchDevice; @@ -234,7 +235,7 @@ void QMirClientInput::customEvent(QEvent* event) switch (mir_event_get_type(nativeEvent)) { case mir_event_type_input: - dispatchInputEvent(ubuntuEvent->window->window(), mir_event_get_input_event(nativeEvent)); + dispatchInputEvent(ubuntuEvent->window, mir_event_get_input_event(nativeEvent)); break; case mir_event_type_resize: { @@ -246,7 +247,7 @@ void QMirClientInput::customEvent(QEvent* event) mir_resize_event_get_width(resizeEvent), mir_resize_event_get_height(resizeEvent)); - ubuntuEvent->window->handleSurfaceResize(mir_resize_event_get_width(resizeEvent), + ubuntuEvent->window->handleSurfaceResized(mir_resize_event_get_width(resizeEvent), mir_resize_event_get_height(resizeEvent)); break; } @@ -254,8 +255,24 @@ void QMirClientInput::customEvent(QEvent* event) { auto surfaceEvent = mir_event_get_surface_event(nativeEvent); if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) { - ubuntuEvent->window->handleSurfaceFocusChange(mir_surface_event_get_attribute_value(surfaceEvent) == - mir_surface_focused); + const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused; + // Mir may have sent a pair of focus lost/gained events, so we need to "peek" into the queue + // so that we don't deactivate windows prematurely. + if (focused) { + mPendingFocusGainedEvents--; + ubuntuEvent->window->handleSurfaceFocused(); + QWindowSystemInterface::handleWindowActivated(ubuntuEvent->window->window(), Qt::ActiveWindowFocusReason); + + // NB: Since processing of system events is queued, never check qGuiApp->applicationState() + // as it might be outdated. Always call handleApplicationStateChanged() with the latest + // state regardless. + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + + } else if (!mPendingFocusGainedEvents) { + DLOG("[ubuntumirclient QPA] No windows have focus"); + QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + } } break; } @@ -274,6 +291,17 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent { QWindow *window = platformWindow->window(); + const auto eventType = mir_event_get_type(event); + if (mir_event_type_surface == eventType) { + auto surfaceEvent = mir_event_get_surface_event(event); + if (mir_surface_attrib_focus == mir_surface_event_get_attribute(surfaceEvent)) { + const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused; + if (focused) { + mPendingFocusGainedEvents++; + } + } + } + QCoreApplication::postEvent(this, new QMirClientEvent( platformWindow, event, mEventType)); @@ -284,7 +312,7 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent } } -void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *ev) { switch (mir_input_event_get_type(ev)) { @@ -302,7 +330,7 @@ void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *e } } -void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev) { const MirTouchEvent *tev = mir_input_event_get_touch_event(ev); @@ -333,6 +361,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e switch (touch_action) { case mir_touch_action_down: + mLastFocusedWindow = window; touchPoint.state = Qt::TouchPointPressed; break; case mir_touch_action_up: @@ -347,7 +376,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e } ulong timestamp = mir_input_event_get_event_time(ev) / 1000000; - QWindowSystemInterface::handleTouchEvent(window, timestamp, + QWindowSystemInterface::handleTouchEvent(window->window(), timestamp, mTouchDevice, touchPoints); } @@ -390,7 +419,7 @@ Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers) } } -void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event) +void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event) { const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event); @@ -404,6 +433,9 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve QEvent::Type keyType = action == mir_keyboard_action_up ? QEvent::KeyRelease : QEvent::KeyPress; + if (action == mir_keyboard_action_down) + mLastFocusedWindow = window; + char s[2]; int sym = translateKeysym(xk_sym, s, sizeof(s)); QString text = QString::fromLatin1(s); @@ -420,7 +452,7 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve } } - QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text, is_auto_rep); + QWindowSystemInterface::handleKeyEvent(window->window(), timestamp, keyType, sym, modifiers, text, is_auto_rep); } namespace @@ -433,27 +465,54 @@ Qt::MouseButtons extract_buttons(const MirPointerEvent *pev) if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary)) buttons |= Qt::RightButton; if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary)) - buttons |= Qt::MidButton; + buttons |= Qt::MiddleButton; + if (mir_pointer_event_button_state(pev, mir_pointer_button_back)) + buttons |= Qt::BackButton; + if (mir_pointer_event_button_state(pev, mir_pointer_button_forward)) + buttons |= Qt::ForwardButton; - // TODO: Should mir back and forward buttons exist? - // should they be Qt::X button 1 and 2? return buttons; } } -void QMirClientInput::dispatchPointerEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev) { + auto window = platformWindow->window(); auto timestamp = mir_input_event_get_event_time(ev) / 1000000; auto pev = mir_input_event_get_pointer_event(ev); + auto action = mir_pointer_event_action(pev); + auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), + mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev)); - auto buttons = extract_buttons(pev); - auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), - mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); + switch (action) { + case mir_pointer_action_button_up: + case mir_pointer_action_button_down: + case mir_pointer_action_motion: + { + const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll); + const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll); - QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */, - buttons, modifiers); + if (hDelta != 0 || vDelta != 0) { + const QPoint angleDelta = QPoint(hDelta * 15, vDelta * 15); + QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint, + QPoint(), angleDelta, modifiers, Qt::ScrollUpdate); + } + auto buttons = extract_buttons(pev); + QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */, + buttons, modifiers); + break; + } + case mir_pointer_action_enter: + QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint); + break; + case mir_pointer_action_leave: + QWindowSystemInterface::handleLeaveEvent(window); + break; + default: + DLOG("Unrecognized pointer event"); + } } #if (LOG_EVENTS != 0) diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h index c987d18c12..3ed887419e 100644 --- a/src/plugins/platforms/mirclient/qmirclientinput.h +++ b/src/plugins/platforms/mirclient/qmirclientinput.h @@ -40,6 +40,7 @@ // Qt #include +#include #include @@ -59,12 +60,13 @@ public: void postEvent(QMirClientWindow* window, const MirEvent *event); QMirClientClientIntegration* integration() const { return mIntegration; } + QMirClientWindow *lastFocusedWindow() const {return mLastFocusedWindow; } protected: - void dispatchKeyEvent(QWindow *window, const MirInputEvent *event); - void dispatchPointerEvent(QWindow *window, const MirInputEvent *event); - void dispatchTouchEvent(QWindow *window, const MirInputEvent *event); - void dispatchInputEvent(QWindow *window, const MirInputEvent *event); + void dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchPointerEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *event); void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event); @@ -73,6 +75,9 @@ private: QTouchDevice* mTouchDevice; const QByteArray mEventFilterType; const QEvent::Type mEventType; + + QMirClientWindow *mLastFocusedWindow; + QAtomicInt mPendingFocusGainedEvents; }; #endif // QMIRCLIENTINPUT_H diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp index a234f4eac6..4b2572ce0d 100644 --- a/src/plugins/platforms/mirclient/qmirclientintegration.cpp +++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp @@ -35,28 +35,28 @@ ****************************************************************************/ -// Qt -#include -#include -#include -#include -#include -#include -#include -#include - // Local +#include "qmirclientintegration.h" #include "qmirclientbackingstore.h" #include "qmirclientclipboard.h" #include "qmirclientglcontext.h" #include "qmirclientinput.h" -#include "qmirclientintegration.h" #include "qmirclientlogging.h" #include "qmirclientnativeinterface.h" #include "qmirclientscreen.h" #include "qmirclienttheme.h" #include "qmirclientwindow.h" +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + // platform-api #include #include @@ -67,8 +67,11 @@ static void resumedCallback(const UApplicationOptions *options, void* context) Q_UNUSED(options) Q_UNUSED(context) DASSERT(context != NULL); - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::ApplicationActivate)); + if (qGuiApp->focusWindow()) { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + } else { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + } } static void aboutToStopCallback(UApplicationArchive *archive, void* context) @@ -76,9 +79,13 @@ static void aboutToStopCallback(UApplicationArchive *archive, void* context) Q_UNUSED(archive) DASSERT(context != NULL); QMirClientClientIntegration* integration = static_cast(context); - integration->inputContext()->hideInputPanel(); - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::ApplicationDeactivate)); + QPlatformInputContext *inputContext = integration->inputContext(); + if (inputContext) { + inputContext->hideInputPanel(); + } else { + qWarning("QMirClientClientIntegration aboutToStopCallback(): no input context"); + } + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended); } QMirClientClientIntegration::QMirClientClientIntegration() @@ -100,6 +107,8 @@ QMirClientClientIntegration::QMirClientClientIntegration() "running, and the correct socket is being used and is accessible. The shell may have\n" "rejected the incoming connection, so check its log file"); + mNativeInterface->setMirConnection(u_application_instance_get_mir_connection(mInstance)); + // Create default screen. mScreen = new QMirClientScreen(u_application_instance_get_mir_connection(mInstance)); screenAdded(mScreen); @@ -176,10 +185,8 @@ QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* wind QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) { - QPlatformWindow* platformWindow = new QMirClientWindow( - window, mClipboard, static_cast(mScreen), mInput, u_application_instance_get_mir_connection(mInstance)); - platformWindow->requestActivateWindow(); - return platformWindow; + return new QMirClientWindow(window, mClipboard, static_cast(mScreen), + mInput, u_application_instance_get_mir_connection(mInstance)); } bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -187,11 +194,12 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability switch (cap) { case ThreadedPixmaps: return true; - break; case OpenGL: return true; - break; + + case ApplicationState: + return true; case ThreadedOpenGL: if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) { @@ -200,8 +208,9 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability DLOG("ubuntumirclient: disabled threaded OpenGL"); return false; } - break; - + case MultipleWindows: + case NonFullScreenWindows: + return true; default: return QPlatformIntegration::hasCapability(cap); } @@ -262,3 +271,8 @@ QPlatformClipboard* QMirClientClientIntegration::clipboard() const { return mClipboard.data(); } + +QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const +{ + return mNativeInterface; +} diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h index 2960209691..e41cbe2cee 100644 --- a/src/plugins/platforms/mirclient/qmirclientintegration.h +++ b/src/plugins/platforms/mirclient/qmirclientintegration.h @@ -49,6 +49,7 @@ class QMirClientClipboard; class QMirClientInput; +class QMirClientNativeInterface; class QMirClientScreen; class QMirClientClientIntegration : public QPlatformIntegration { @@ -59,7 +60,7 @@ public: // QPlatformIntegration methods. bool hasCapability(QPlatformIntegration::Capability cap) const override; QAbstractEventDispatcher *createEventDispatcher() const override; - QPlatformNativeInterface* nativeInterface() const override { return mNativeInterface; } + QPlatformNativeInterface* nativeInterface() const override; QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override; QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override; QPlatformFontDatabase* fontDatabase() const override { return mFontDb; } @@ -79,7 +80,7 @@ private: void setupOptions(); void setupDescription(); - QPlatformNativeInterface* mNativeInterface; + QMirClientNativeInterface* mNativeInterface; QPlatformFontDatabase* mFontDb; QMirClientPlatformServices* mServices; diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp index a0bb932df3..1b4c20153b 100644 --- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp +++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp @@ -35,17 +35,17 @@ ****************************************************************************/ +// Local +#include "qmirclientnativeinterface.h" +#include "qmirclientscreen.h" +#include "qmirclientglcontext.h" + // Qt #include #include #include #include -// Local -#include "qmirclientnativeinterface.h" -#include "qmirclientscreen.h" -#include "qmirclientglcontext.h" - class QMirClientResourceMap : public QMap { public: @@ -55,6 +55,7 @@ public: insert("eglcontext", QMirClientNativeInterface::EglContext); insert("nativeorientation", QMirClientNativeInterface::NativeOrientation); insert("display", QMirClientNativeInterface::Display); + insert("mirconnection", QMirClientNativeInterface::MirConnection); } }; @@ -63,6 +64,7 @@ Q_GLOBAL_STATIC(QMirClientResourceMap, ubuntuResourceMap) QMirClientNativeInterface::QMirClientNativeInterface() : mGenericEventFilterType(QByteArrayLiteral("Event")) , mNativeOrientation(nullptr) + , mMirConnection(nullptr) { } @@ -72,6 +74,23 @@ QMirClientNativeInterface::~QMirClientNativeInterface() mNativeOrientation = nullptr; } +void* QMirClientNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) +{ + const QByteArray lowerCaseResource = resourceString.toLower(); + + if (!ubuntuResourceMap()->contains(lowerCaseResource)) { + return nullptr; + } + + const ResourceType resourceType = ubuntuResourceMap()->value(lowerCaseResource); + + if (resourceType == QMirClientNativeInterface::MirConnection) { + return mMirConnection; + } else { + return nullptr; + } +} + void* QMirClientNativeInterface::nativeResourceForContext( const QByteArray& resourceString, QOpenGLContext* context) { diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h index 84f03bb915..7df646e73a 100644 --- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h +++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h @@ -42,12 +42,13 @@ class QMirClientNativeInterface : public QPlatformNativeInterface { public: - enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display }; + enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display, MirConnection }; QMirClientNativeInterface(); ~QMirClientNativeInterface(); // QPlatformNativeInterface methods. + void* nativeResourceForIntegration(const QByteArray &resource) override; void* nativeResourceForContext(const QByteArray& resourceString, QOpenGLContext* context) override; void* nativeResourceForWindow(const QByteArray& resourceString, @@ -57,10 +58,12 @@ public: // New methods. const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; } + void setMirConnection(void *mirConnection) { mMirConnection = mirConnection; } private: const QByteArray mGenericEventFilterType; Qt::ScreenOrientation* mNativeOrientation; + void *mMirConnection; }; #endif // QMIRCLIENTNATIVEINTERFACE_H diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h index 24d7307faa..2a1ed9c09f 100644 --- a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h +++ b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h @@ -43,15 +43,7 @@ class OrientationChangeEvent : public QEvent { public: - enum Orientation { - Undefined = 0, - TopUp, - TopDown, - LeftUp, - RightUp, - FaceUp, - FaceDown - }; + enum Orientation { TopUp, LeftUp, TopDown, RightUp }; OrientationChangeEvent(QEvent::Type type, Orientation orientation) : QEvent(type) diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp index 203a1cbfd8..75561f7fd3 100644 --- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp +++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp @@ -41,14 +41,14 @@ QStringList QMirClientIntegrationPlugin::keys() const { QStringList list; - list << "mirclient"; + list << QStringLiteral("mirclient"); return list; } QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system, const QStringList &) { - if (system.toLower() == "mirclient") { + if (system.toLower() == QLatin1String("mirclient")) { return new QMirClientClientIntegration; } else { return 0; diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp index 5c4b1cd0d6..3eb01f816a 100644 --- a/src/plugins/platforms/mirclient/qmirclientscreen.cpp +++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Canonical, Ltd. +** Copyright (C) 2014-2015 Canonical, Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -35,6 +35,11 @@ ****************************************************************************/ +// local +#include "qmirclientscreen.h" +#include "qmirclientlogging.h" +#include "qmirclientorientationchangeevent_p.h" + #include // Qt @@ -45,12 +50,7 @@ #include #include -// local -#include "qmirclientscreen.h" -#include "qmirclientlogging.h" -#include "qmirclientorientationchangeevent_p.h" - -#include "memory" +#include static const int kSwapInterval = 1; @@ -149,9 +149,11 @@ static const MirDisplayOutput *find_active_output( QMirClientScreen::QMirClientScreen(MirConnection *connection) : mFormat(QImage::Format_RGB32) , mDepth(32) + , mOutputId(0) , mSurfaceFormat() , mEglDisplay(EGL_NO_DISPLAY) , mEglConfig(nullptr) + , mCursor(connection) { // Initialize EGL. ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE); @@ -203,6 +205,11 @@ QMirClientScreen::QMirClientScreen(MirConnection *connection) auto const displayOutput = find_active_output(displayConfig.get()); ASSERT(displayOutput != nullptr); + mOutputId = displayOutput->output_id; + + mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm); + DLOG("ubuntumirclient: screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height()); + const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode]; const int kScreenWidth = mode->horizontal_resolution; const int kScreenHeight = mode->vertical_resolution; diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h index 5d9325354f..a6b4f442da 100644 --- a/src/plugins/platforms/mirclient/qmirclientscreen.h +++ b/src/plugins/platforms/mirclient/qmirclientscreen.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Canonical, Ltd. +** Copyright (C) 2014-2015 Canonical, Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -42,6 +42,8 @@ #include #include +#include "qmirclientcursor.h" + struct MirConnection; class QMirClientScreen : public QObject, public QPlatformScreen @@ -56,8 +58,10 @@ public: int depth() const override { return mDepth; } QRect geometry() const override { return mGeometry; } QRect availableGeometry() const override { return mGeometry; } + QSizeF physicalSize() const override { return mPhysicalSize; } Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; } Qt::ScreenOrientation orientation() const override { return mNativeOrientation; } + QPlatformCursor *cursor() const override { return const_cast(&mCursor); } // New methods. QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; } @@ -65,20 +69,24 @@ public: EGLConfig eglConfig() const { return mEglConfig; } EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; } void handleWindowSurfaceResize(int width, int height); + uint32_t mirOutputId() const { return mOutputId; } // QObject methods. - void customEvent(QEvent* event); + void customEvent(QEvent* event) override; private: QRect mGeometry; + QSizeF mPhysicalSize; Qt::ScreenOrientation mNativeOrientation; Qt::ScreenOrientation mCurrentOrientation; QImage::Format mFormat; int mDepth; + uint32_t mOutputId; QSurfaceFormat mSurfaceFormat; EGLDisplay mEglDisplay; EGLConfig mEglConfig; EGLNativeDisplayType mEglNativeDisplay; + QMirClientCursor mCursor; }; #endif // QMIRCLIENTSCREEN_H diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp index 3d1e5377e5..9a72c2f9dc 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp +++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp @@ -36,16 +36,16 @@ // Local +#include "qmirclientwindow.h" #include "qmirclientclipboard.h" #include "qmirclientinput.h" -#include "qmirclientwindow.h" #include "qmirclientscreen.h" #include "qmirclientlogging.h" +#include + // Qt #include -#include -#include #include #include #include @@ -55,25 +55,46 @@ #include -#define IS_OPAQUE_FLAG 1 - namespace { + +// FIXME: this used to be defined by platform-api, but it's been removed in v3. Change ubuntu-keyboard to use +// a different enum for window roles. +enum UAUiWindowRole { + U_MAIN_ROLE = 1, + U_DASH_ROLE, + U_INDICATOR_ROLE, + U_NOTIFICATIONS_ROLE, + U_GREETER_ROLE, + U_LAUNCHER_ROLE, + U_ON_SCREEN_KEYBOARD_ROLE, + U_SHUTDOWN_DIALOG_ROLE, +}; + +struct MirSpecDeleter +{ + void operator()(MirSurfaceSpec *spec) { mir_surface_spec_release(spec); } +}; + +using Spec = std::unique_ptr; + +EGLNativeWindowType nativeWindowFor(MirSurface *surf) +{ + auto stream = mir_surface_get_buffer_stream(surf); + return reinterpret_cast(mir_buffer_stream_get_egl_native_window(stream)); +} + MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state) { switch (state) { case Qt::WindowNoState: return mir_surface_state_restored; - case Qt::WindowFullScreen: return mir_surface_state_fullscreen; - case Qt::WindowMaximized: return mir_surface_state_maximized; - case Qt::WindowMinimized: return mir_surface_state_minimized; - default: LOG("Unexpected Qt::WindowState: %d", state); return mir_surface_state_restored; @@ -86,117 +107,137 @@ const char *qtWindowStateToStr(Qt::WindowState state) switch (state) { case Qt::WindowNoState: return "NoState"; - case Qt::WindowFullScreen: return "FullScreen"; - case Qt::WindowMaximized: return "Maximized"; - case Qt::WindowMinimized: return "Minimized"; - default: return "!?"; } } #endif -} // anonymous namespace - -class QMirClientWindowPrivate +WId makeId() { -public: - void createEGLSurface(EGLNativeWindowType nativeWindow); - void destroyEGLSurface(); - int panelHeight(); - - QMirClientScreen* screen; - EGLSurface eglSurface; - WId id; - QMirClientInput* input; - Qt::WindowState state; - MirConnection *connection; - MirSurface* surface; - QSize bufferSize; - QMutex mutex; - QSharedPointer clipboard; -}; - -static void eventCallback(MirSurface* surface, const MirEvent *event, void* context) -{ - (void) surface; - DASSERT(context != NULL); - QMirClientWindow* platformWindow = static_cast(context); - platformWindow->priv()->input->postEvent(platformWindow, event); + static int id = 1; + return id++; } -static void surfaceCreateCallback(MirSurface* surface, void* context) +MirPixelFormat defaultPixelFormatFor(MirConnection *connection) { - DASSERT(context != NULL); - QMirClientWindow* platformWindow = static_cast(context); - platformWindow->priv()->surface = surface; - - mir_surface_set_event_handler(surface, eventCallback, context); + MirPixelFormat format; + unsigned int nformats; + mir_connection_get_available_surface_formats(connection, &format, 1, &nformats); + return format; } -QMirClientWindow::QMirClientWindow(QWindow* w, QSharedPointer clipboard, QMirClientScreen* screen, - QMirClientInput* input, MirConnection* connection) - : QObject(nullptr), QPlatformWindow(w) +UAUiWindowRole roleFor(QWindow *window) { - DASSERT(screen != NULL); + QVariant roleVariant = window->property("role"); + if (!roleVariant.isValid()) + return U_MAIN_ROLE; - d = new QMirClientWindowPrivate; - d->screen = screen; - d->eglSurface = EGL_NO_SURFACE; - d->input = input; - d->state = window()->windowState(); - d->connection = connection; - d->clipboard = clipboard; + uint role = roleVariant.toUInt(); + if (role < U_MAIN_ROLE || role > U_SHUTDOWN_DIALOG_ROLE) + return U_MAIN_ROLE; - static int id = 1; - d->id = id++; - - // Use client geometry if set explicitly, use available screen geometry otherwise. - QPlatformWindow::setGeometry(window()->geometry().isValid() && window()->geometry() != screen->geometry() ? - window()->geometry() : screen->availableGeometry()); - createWindow(); - DLOG("QMirClientWindow::QMirClientWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input); + return static_cast(role); } -QMirClientWindow::~QMirClientWindow() +QMirClientWindow *transientParentFor(QWindow *window) { - DLOG("QMirClientWindow::~QMirClientWindow"); - d->destroyEGLSurface(); - - mir_surface_release_sync(d->surface); - - delete d; + QWindow *parent = window->transientParent(); + return parent ? static_cast(parent->handle()) : nullptr; } -void QMirClientWindowPrivate::createEGLSurface(EGLNativeWindowType nativeWindow) +Spec makeSurfaceSpec(QWindow *window, QMirClientInput *input, MirConnection *connection) { - DLOG("QMirClientWindowPrivate::createEGLSurface (this=%p, nativeWindow=%p)", - this, reinterpret_cast(nativeWindow)); - - eglSurface = eglCreateWindowSurface(screen->eglDisplay(), screen->eglConfig(), - nativeWindow, nullptr); + const auto geom = window->geometry(); + const int width = geom.width() > 0 ? geom.width() : 1; + const int height = geom.height() > 0 ? geom.height() : 1; + const auto pixelFormat = defaultPixelFormatFor(connection); + + if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); + return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)}; + } + + const Qt::WindowType type = window->type(); + if (type == Qt::Popup) { + auto parent = transientParentFor(window); + if (parent == nullptr) { + //NOTE: We cannot have a parentless popup - + //try using the last surface to receive input as that will most likely be + //the one that caused this popup to be created + parent = input->lastFocusedWindow(); + } + if (parent) { + auto pos = geom.topLeft(); + pos -= parent->geometry().topLeft(); + MirRectangle location{pos.x(), pos.y(), 0, 0}; + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height); + return Spec{mir_connection_create_spec_for_menu( + connection, width, height, pixelFormat, parent->mirSurface(), + &location, mir_edge_attachment_any)}; + } else { + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window); + } + } else if (type == Qt::Dialog) { + auto parent = transientParentFor(window); + if (parent) { + // Modal dialog + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height); + return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())}; + } else { + // TODO: do Qt parentless dialogs have the same semantics as mir? + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height); + return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)}; + } + } + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height); + return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)}; +} - DASSERT(eglSurface != EGL_NO_SURFACE); +void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment) +{ + mir_surface_spec_set_min_width(spec, minSize.width()); + mir_surface_spec_set_min_height(spec, minSize.height()); + if (maxSize.width() >= minSize.width()) { + mir_surface_spec_set_max_width(spec, maxSize.width()); + } + if (maxSize.height() >= minSize.height()) { + mir_surface_spec_set_max_height(spec, maxSize.height()); + } + if (increment.width() > 0) { + mir_surface_spec_set_width_increment(spec, increment.width()); + } + if (increment.height() > 0) { + mir_surface_spec_set_height_increment(spec, increment.height()); + } } -void QMirClientWindowPrivate::destroyEGLSurface() +MirSurface *createMirSurface(QWindow *window, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection) { - DLOG("QMirClientWindowPrivate::destroyEGLSurface (this=%p)", this); - if (eglSurface != EGL_NO_SURFACE) { - eglDestroySurface(screen->eglDisplay(), eglSurface); - eglSurface = EGL_NO_SURFACE; + auto spec = makeSurfaceSpec(window, input, connection); + const auto title = window->title().toUtf8(); + mir_surface_spec_set_name(spec.get(), title.constData()); + + setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement()); + + if (window->windowState() == Qt::WindowFullScreen) { + mir_surface_spec_set_fullscreen_on_output(spec.get(), screen->mirOutputId()); } + + auto surface = mir_surface_create_sync(spec.get()); + Q_ASSERT(mir_surface_is_valid(surface)); + return surface; } // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 -// we need to guess the panel height (3GU + 2DP) -int QMirClientWindowPrivate::panelHeight() +// we need to guess the panel height (3GU) +int panelHeight() { if (qEnvironmentVariableIsSet("QT_MIRCLIENT_IGNORE_PANEL")) return 0; @@ -210,245 +251,412 @@ int QMirClientWindowPrivate::panelHeight() gridUnit = defaultGridUnit; } } - qreal densityPixelRatio = static_cast(gridUnit) / defaultGridUnit; - return gridUnit * 3 + qFloor(densityPixelRatio) * 2; + return gridUnit * 3; } -namespace +} //namespace + +class QMirClientSurface { -static MirPixelFormat -mir_choose_default_pixel_format(MirConnection *connection) +public: + QMirClientSurface(QMirClientWindow *platformWindow, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection) + : mWindow(platformWindow->window()) + , mPlatformWindow(platformWindow) + , mInput(input) + , mConnection(connection) + , mMirSurface(createMirSurface(mWindow, screen, input, connection)) + , mEglDisplay(screen->eglDisplay()) + , mEglSurface(eglCreateWindowSurface(mEglDisplay, screen->eglConfig(), nativeWindowFor(mMirSurface), nullptr)) + , mVisible(false) + , mNeedsRepaint(false) + , mParented(mWindow->transientParent() || mWindow->parent()) + , mWindowState(mWindow->windowState()) + + { + mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this); + + // Window manager can give us a final size different from what we asked for + // so let's check what we ended up getting + MirSurfaceParameters parameters; + mir_surface_get_parameters(mMirSurface, ¶meters); + + auto geom = mWindow->geometry(); + geom.setWidth(parameters.width); + geom.setHeight(parameters.height); + if (mWindowState == Qt::WindowFullScreen) { + geom.setY(0); + } else { + geom.setY(panelHeight()); + } + + // Assume that the buffer size matches the surface size at creation time + mBufferSize = geom.size(); + platformWindow->QPlatformWindow::setGeometry(geom); + QWindowSystemInterface::handleGeometryChange(mWindow, geom); + + DLOG("[ubuntumirclient QPA] created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n", + geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow)); + } + + ~QMirClientSurface() + { + if (mEglSurface != EGL_NO_SURFACE) + eglDestroySurface(mEglDisplay, mEglSurface); + if (mMirSurface) + mir_surface_release_sync(mMirSurface); + } + + QMirClientSurface(QMirClientSurface const&) = delete; + QMirClientSurface& operator=(QMirClientSurface const&) = delete; + + void resize(const QSize& newSize); + void setState(Qt::WindowState newState); + void setVisible(bool state); + void updateTitle(const QString& title); + void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment); + + void onSwapBuffersDone(); + void handleSurfaceResized(int width, int height); + int needsRepaint() const; + + EGLSurface eglSurface() const { return mEglSurface; } + MirSurface *mirSurface() const { return mMirSurface; } + +private: + static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context); + void postEvent(const MirEvent *event); + void updateSurface(); + + QWindow * const mWindow; + QMirClientWindow * const mPlatformWindow; + QMirClientInput * const mInput; + MirConnection * const mConnection; + + MirSurface * const mMirSurface; + const EGLDisplay mEglDisplay; + const EGLSurface mEglSurface; + + bool mVisible; + bool mNeedsRepaint; + bool mParented; + Qt::WindowState mWindowState; + QSize mBufferSize; + + QMutex mTargetSizeMutex; + QSize mTargetSize; +}; + +void QMirClientSurface::resize(const QSize& size) { - MirPixelFormat format[mir_pixel_formats]; - unsigned int nformats; + DLOG("[ubuntumirclient QPA] resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height()); + + if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) { + DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow); + return; + } - mir_connection_get_available_surface_formats(connection, - format, mir_pixel_formats, &nformats); + if (size.isEmpty()) { + DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, size is empty", mWindow); + return; + } - return format[0]; + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_width(spec.get(), size.width()); + mir_surface_spec_set_height(spec.get(), size.height()); + mir_surface_apply_spec(mMirSurface, spec.get()); } + +void QMirClientSurface::setState(Qt::WindowState newState) +{ + mir_wait_for(mir_surface_set_state(mMirSurface, qtWindowStateToMirSurfaceState(newState))); + mWindowState = newState; } -void QMirClientWindow::createWindow() +void QMirClientSurface::setVisible(bool visible) { - DLOG("QMirClientWindow::createWindow (this=%p)", this); + if (mVisible == visible) + return; - // FIXME: remove this remnant of an old platform-api enum - needs ubuntu-keyboard update - const int SCREEN_KEYBOARD_ROLE = 7; - // Get surface role and flags. - QVariant roleVariant = window()->property("role"); - int role = roleVariant.isValid() ? roleVariant.toUInt() : 1; // 1 is the default role for apps. - QVariant opaqueVariant = window()->property("opaque"); - uint flags = opaqueVariant.isValid() ? - opaqueVariant.toUInt() ? static_cast(IS_OPAQUE_FLAG) : 0 : 0; + mVisible = visible; - // FIXME(loicm) Opaque flag is forced for now for non-system sessions (applications) for - // performance reasons. - flags |= static_cast(IS_OPAQUE_FLAG); + if (mVisible) + updateSurface(); + + // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized. + // Will have to change qtmir and unity8 for that. + const auto newState = visible ? qtWindowStateToMirSurfaceState(mWindowState) : mir_surface_state_minimized; + mir_wait_for(mir_surface_set_state(mMirSurface, newState)); +} + +void QMirClientSurface::updateTitle(const QString& newTitle) +{ + const auto title = newTitle.toUtf8(); + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_name(spec.get(), title.constData()); + mir_surface_apply_spec(mMirSurface, spec.get()); +} - const QByteArray title = (!window()->title().isNull()) ? window()->title().toUtf8() : "Window 1"; // legacy title - const int panelHeight = d->panelHeight(); +void QMirClientSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment) +{ + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + ::setSizingConstraints(spec.get(), minSize, maxSize, increment); + mir_surface_apply_spec(mMirSurface, spec.get()); +} + +void QMirClientSurface::handleSurfaceResized(int width, int height) +{ + QMutexLocker lock(&mTargetSizeMutex); + + // mir's resize event is mainly a signal that we need to redraw our content. We use the + // width/height as identifiers to figure out if this is the latest surface resize event + // that has posted, discarding any old ones. This avoids issuing too many redraw events. + // see TODO in postEvent as the ideal way we should handle this. + // The actual buffer size may or may have not changed at this point, so let the rendering + // thread drive the window geometry updates. + mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height; +} + +int QMirClientSurface::needsRepaint() const +{ + if (mNeedsRepaint) { + if (mTargetSize != mBufferSize) { + //If the buffer hasn't changed yet, we need at least two redraws, + //once to get the new buffer size and propagate the geometry changes + //and the second to redraw the content at the new size + return 2; + } else { + // The buffer size has already been updated so we only need one redraw + // to render at the new size + return 1; + } + } + return 0; +} +void QMirClientSurface::onSwapBuffersDone() +{ #if !defined(QT_NO_DEBUG) - LOG("panelHeight: '%d'", panelHeight); - LOG("role: '%d'", role); - LOG("flags: '%s'", (flags & static_cast(1)) ? "Opaque" : "NotOpaque"); - LOG("title: '%s'", title.constData()); + static int sFrameNumber = 0; + ++sFrameNumber; #endif - // Get surface geometry. - QRect geometry; - if (d->state == Qt::WindowFullScreen) { - printf("QMirClientWindow - fullscreen geometry\n"); - geometry = screen()->geometry(); - } else if (d->state == Qt::WindowMaximized) { - printf("QMirClientWindow - maximized geometry\n"); - geometry = screen()->availableGeometry(); - /* - * FIXME: Autopilot relies on being able to convert coordinates relative of the window - * into absolute screen coordinates. Mir does not allow this, see bug lp:1346633 - * Until there's a correct way to perform this transformation agreed, this horrible hack - * guesses the transformation heuristically. - * - * Assumption: this method only used on phone devices! - */ - geometry.setY(panelHeight); - } else { - printf("QMirClientWindow - regular geometry\n"); - geometry = this->geometry(); - geometry.setY(panelHeight); - } + EGLint eglSurfaceWidth = -1; + EGLint eglSurfaceHeight = -1; + eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth); + eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight); - DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with size (%d, %d) with title '%s'\n", - geometry.x(), geometry.y(), geometry.width(), geometry.height(), title.data()); + const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0; - MirSurfaceSpec *spec; - if (role == SCREEN_KEYBOARD_ROLE) - { - spec = mir_connection_create_spec_for_input_method(d->connection, geometry.width(), - geometry.height(), mir_choose_default_pixel_format(d->connection)); - } - else - { - spec = mir_connection_create_spec_for_normal_surface(d->connection, geometry.width(), - geometry.height(), mir_choose_default_pixel_format(d->connection)); - } - mir_surface_spec_set_name(spec, title.data()); + if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) { - // Create platform window - mir_wait_for(mir_surface_create(spec, surfaceCreateCallback, this)); - mir_surface_spec_release(spec); + DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)", + mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight); - DASSERT(d->surface != NULL); - d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface))); + mBufferSize.rwidth() = eglSurfaceWidth; + mBufferSize.rheight() = eglSurfaceHeight; - if (d->state == Qt::WindowFullScreen) { - // TODO: We could set this on creation once surface spec supports it (mps already up) - mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_fullscreen)); + QRect newGeometry = mPlatformWindow->geometry(); + newGeometry.setSize(mBufferSize); + + mPlatformWindow->QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry); + } else { +#if 0 + DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)", + mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height()); +#endif } +} - // Window manager can give us a final size different from what we asked for - // so let's check what we ended up getting - { - MirSurfaceParameters parameters; - mir_surface_get_parameters(d->surface, ¶meters); +void QMirClientSurface::surfaceEventCallback(MirSurface *surface, const MirEvent *event, void* context) +{ + Q_UNUSED(surface); + Q_ASSERT(context != nullptr); - geometry.setWidth(parameters.width); - geometry.setHeight(parameters.height); - } + auto s = static_cast(context); + s->postEvent(event); +} - DLOG("[ubuntumirclient QPA] created surface has size (%d, %d)", - geometry.width(), geometry.height()); +void QMirClientSurface::postEvent(const MirEvent *event) +{ + if (mir_event_type_resize == mir_event_get_type(event)) { + // TODO: The current event queue just accumulates all resize events; + // It would be nicer if we could update just one event if that event has not been dispatched. + // As a workaround, we use the width/height as an identifier of this latest event + // so the event handler (handleSurfaceResized) can discard/ignore old ones. + const auto resizeEvent = mir_event_get_resize_event(event); + const auto width = mir_resize_event_get_width(resizeEvent); + const auto height = mir_resize_event_get_height(resizeEvent); + DLOG("[ubuntumirclient QPA] resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height); + + QMutexLocker lock(&mTargetSizeMutex); + mTargetSize.rwidth() = width; + mTargetSize.rheight() = height; + } - // Assume that the buffer size matches the surface size at creation time - d->bufferSize = geometry.size(); + mInput->postEvent(mPlatformWindow, event); +} - // Tell Qt about the geometry. - QWindowSystemInterface::handleGeometryChange(window(), geometry); - QPlatformWindow::setGeometry(geometry); +void QMirClientSurface::updateSurface() +{ + DLOG("[ubuntumirclient QPA] updateSurface(window=%p)", mWindow); + + if (!mParented && mWindow->type() == Qt::Dialog) { + // The dialog may have been parented after creation time + // so morph it into a modal dialog + auto parent = transientParentFor(mWindow); + if (parent) { + DLOG("[ubuntumirclient QPA] updateSurface(window=%p) dialog now parented", mWindow); + mParented = true; + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_parent(spec.get(), parent->mirSurface()); + mir_surface_apply_spec(mMirSurface, spec.get()); + } + } } -void QMirClientWindow::moveResize(const QRect& rect) +QMirClientWindow::QMirClientWindow(QWindow *w, const QSharedPointer &clipboard, QMirClientScreen *screen, + QMirClientInput *input, MirConnection *connection) + : QObject(nullptr) + , QPlatformWindow(w) + , mId(makeId()) + , mClipboard(clipboard) + , mSurface(new QMirClientSurface{this, screen, input, connection}) { - (void) rect; - // TODO: Not yet supported by mir. + DLOG("[ubuntumirclient QPA] QMirClientWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get()); } -void QMirClientWindow::handleSurfaceResize(int width, int height) +QMirClientWindow::~QMirClientWindow() { - QMutexLocker(&d->mutex); - LOG("QMirClientWindow::handleSurfaceResize(width=%d, height=%d)", width, height); + DLOG("[ubuntumirclient QPA] ~QMirClientWindow(window=%p)", this); +} - // The current buffer size hasn't actually changed. so just render on it and swap - // buffers in the hope that the next buffer will match the surface size advertised - // in this event. - // But since this event is processed by a thread different from the one that swaps - // buffers, you can never know if this information is already outdated as there's - // no synchronicity whatsoever between the processing of resize events and the - // consumption of buffers. - if (d->bufferSize.width() != width || d->bufferSize.height() != height) { - QWindowSystemInterface::handleExposeEvent(window(), geometry()); - QWindowSystemInterface::flushWindowSystemEvents(); +void QMirClientWindow::handleSurfaceResized(int width, int height) +{ + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height); + + mSurface->handleSurfaceResized(width, height); + + // This resize event could have occurred just after the last buffer swap for this window. + // This means the client may still be holding a buffer with the older size. The first redraw call + // will then render at the old size. After swapping the client now will get a new buffer with the + // updated size but it still needs re-rendering so another redraw may be needed. + // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice + auto const numRepaints = mSurface->needsRepaint(); + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints); + for (int i = 0; i < numRepaints; i++) { + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height()); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } } -void QMirClientWindow::handleSurfaceFocusChange(bool focused) +void QMirClientWindow::handleSurfaceFocused() { - LOG("QMirClientWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false"); - QWindow *activatedWindow = focused ? window() : nullptr; + DLOG("[ubuntumirclient QPA] handleSurfaceFocused(window=%p)", window()); - // System clipboard contents might have changed while this window was unfocused and wihtout + // System clipboard contents might have changed while this window was unfocused and without // this process getting notified about it because it might have been suspended (due to // application lifecycle policies), thus unable to listen to any changes notified through // D-Bus. // Therefore let's ensure we are up to date with the system clipboard now that we are getting // focused again. - if (focused) { - d->clipboard->requestDBusClipboardContents(); - } - - QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason); + mClipboard->requestDBusClipboardContents(); } void QMirClientWindow::setWindowState(Qt::WindowState state) { - QMutexLocker(&d->mutex); - DLOG("QMirClientWindow::setWindowState (this=%p, %s)", this, qtWindowStateToStr(state)); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setWindowState(window=%p, %s)", this, qtWindowStateToStr(state)); + mSurface->setState(state); - if (state == d->state) - return; + updatePanelHeightHack(state); +} - // TODO: Perhaps we should check if the states are applied? - mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(state))); - d->state = state; +/* + FIXME: Mir does not let clients know the position of their windows in the virtual + desktop space. So we have this ugly hack that assumes a phone situation where the + window is always on the top-left corner, right below the indicators panel if not + in fullscreen. + */ +void QMirClientWindow::updatePanelHeightHack(Qt::WindowState state) +{ + if (state == Qt::WindowFullScreen && geometry().y() != 0) { + QRect newGeometry = geometry(); + newGeometry.setY(0); + QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(window(), newGeometry); + } else if (geometry().y() == 0) { + QRect newGeometry = geometry(); + newGeometry.setY(panelHeight()); + QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(window(), newGeometry); + } } void QMirClientWindow::setGeometry(const QRect& rect) { - DLOG("QMirClientWindow::setGeometry (this=%p)", this); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)", + window(), rect.x(), rect.y(), rect.width(), rect.height()); - bool doMoveResize; + //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates + const auto newSize = rect.size(); + auto newGeometry = geometry(); + newGeometry.setSize(newSize); + QPlatformWindow::setGeometry(newGeometry); - { - QMutexLocker(&d->mutex); - QPlatformWindow::setGeometry(rect); - doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized; - } - - if (doMoveResize) { - moveResize(rect); - } + mSurface->resize(newSize); } void QMirClientWindow::setVisible(bool visible) { - QMutexLocker(&d->mutex); - DLOG("QMirClientWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false"); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false"); - if (visible) { - mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(d->state))); + mSurface->setVisible(visible); + const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect(); - QWindowSystemInterface::handleExposeEvent(window(), QRect()); - QWindowSystemInterface::flushWindowSystemEvents(); - } else { - // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized. - // Will have to change qtmir and unity8 for that. - mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_minimized)); - } + lock.unlock(); + QWindowSystemInterface::handleExposeEvent(window(), exposeRect); + QWindowSystemInterface::flushWindowSystemEvents(); } -void* QMirClientWindow::eglSurface() const +void QMirClientWindow::setWindowTitle(const QString& title) { - return d->eglSurface; + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData()); + mSurface->updateTitle(title); } -WId QMirClientWindow::winId() const +void QMirClientWindow::propagateSizeHints() { - return d->id; + QMutexLocker lock(&mMutex); + const auto win = window(); + DLOG("[ubuntumirclient QPA] propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)", + win, win->minimumSize().width(), win->minimumSize().height(), + win->maximumSize().width(), win->maximumSize().height(), + win->sizeIncrement().width(), win->sizeIncrement().height()); + mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement()); } -void QMirClientWindow::onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight) +void* QMirClientWindow::eglSurface() const { - QMutexLocker(&d->mutex); - - bool sizeKnown = newBufferWidth > 0 && newBufferHeight > 0; - - if (sizeKnown && (d->bufferSize.width() != newBufferWidth || - d->bufferSize.height() != newBufferHeight)) { - - DLOG("QMirClientWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)", - d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight); - - d->bufferSize.rwidth() = newBufferWidth; - d->bufferSize.rheight() = newBufferHeight; + return mSurface->eglSurface(); +} - QRect newGeometry; +MirSurface *QMirClientWindow::mirSurface() const +{ + return mSurface->mirSurface(); +} - newGeometry = geometry(); - newGeometry.setWidth(d->bufferSize.width()); - newGeometry.setHeight(d->bufferSize.height()); +WId QMirClientWindow::winId() const +{ + return mId; +} - QPlatformWindow::setGeometry(newGeometry); - QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect()); - } +void QMirClientWindow::onSwapBuffersDone() +{ + QMutexLocker lock(&mMutex); + mSurface->onSwapBuffersDone(); } diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h index f342669544..4ec7879949 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.h +++ b/src/plugins/platforms/mirclient/qmirclientwindow.h @@ -40,20 +40,23 @@ #include #include +#include -#include +#include class QMirClientClipboard; class QMirClientInput; class QMirClientScreen; -class QMirClientWindowPrivate; +class QMirClientSurface; +struct MirConnection; +struct MirSurface; class QMirClientWindow : public QObject, public QPlatformWindow { Q_OBJECT public: - QMirClientWindow(QWindow *w, QSharedPointer clipboard, QMirClientScreen *screen, - QMirClientInput *input, MirConnection *mir_connection); + QMirClientWindow(QWindow *w, const QSharedPointer &clipboard, QMirClientScreen *screen, + QMirClientInput *input, MirConnection *mirConnection); virtual ~QMirClientWindow(); // QPlatformWindow methods. @@ -61,20 +64,22 @@ public: void setGeometry(const QRect&) override; void setWindowState(Qt::WindowState state) override; void setVisible(bool visible) override; + void setWindowTitle(const QString &title) override; + void propagateSizeHints() override; // New methods. - void* eglSurface() const; - void handleSurfaceResize(int width, int height); - void handleSurfaceFocusChange(bool focused); - void onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight); - - QMirClientWindowPrivate* priv() { return d; } + void *eglSurface() const; + MirSurface *mirSurface() const; + void handleSurfaceResized(int width, int height); + void handleSurfaceFocused(); + void onSwapBuffersDone(); private: - void createWindow(); - void moveResize(const QRect& rect); - - QMirClientWindowPrivate *d; + void updatePanelHeightHack(Qt::WindowState); + mutable QMutex mMutex; + const WId mId; + const QSharedPointer mClipboard; + std::unique_ptr mSurface; }; #endif // QMIRCLIENTWINDOW_H -- cgit v1.2.3 From bc81a28554a256563e7df8860d17f10a63e45a2b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 8 Jan 2016 16:22:12 +0100 Subject: Passing parameters to convertLineOffset by pointer instead of reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is aligned with our coding style and it should have been this way from the start. Change-Id: I23a00eb220dd9f17d9239c811b556885a2c0186a Reviewed-by: Fredrik de Vibe Reviewed-by: Jan Arve Sæther --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index b55393c7dc..608a7583c0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -44,11 +44,11 @@ QT_USE_NAMESPACE #ifndef QT_NO_ACCESSIBILITY -static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0) +static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *offset, NSUInteger *start = 0, NSUInteger *end = 0) { - Q_ASSERT(line == -1 || offset == -1); - Q_ASSERT(line != -1 || offset != -1); - Q_ASSERT(offset <= text->characterCount()); + Q_ASSERT(*line == -1 || *offset == -1); + Q_ASSERT(*line != -1 || *offset != -1); + Q_ASSERT(*offset <= text->characterCount()); int curLine = -1; int curStart = 0, curEnd = 0; @@ -75,14 +75,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (nextEnd == curEnd) ++curEnd; } - } while ((line == -1 || curLine < line) && (offset == -1 || (curEnd <= offset)) && curEnd <= text->characterCount()); + } while ((*line == -1 || curLine < *line) && (*offset == -1 || (curEnd <= *offset)) && curEnd <= text->characterCount()); curEnd = qMin(curEnd, text->characterCount()); - if (line == -1) - line = curLine; - if (offset == -1) - offset = curStart; + if (*line == -1) + *line = curLine; + if (*offset == -1) + *offset = curStart; Q_ASSERT(curStart >= 0); Q_ASSERT(curEnd >= 0); @@ -338,7 +338,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (QAccessibleTextInterface *text = iface->textInterface()) { int line = -1; int position = text->cursorPosition(); - convertLineOffset(text, line, position); + convertLineOffset(text, &line, &position); return [NSNumber numberWithInt: line]; } return nil; @@ -397,7 +397,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (index < 0 || index > iface->textInterface()->characterCount()) return nil; int line = -1; - convertLineOffset(iface->textInterface(), line, index); + convertLineOffset(iface->textInterface(), &line, &index); return [NSNumber numberWithInt:line]; } if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) { @@ -407,7 +407,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of int lineOffset = -1; NSUInteger startOffset = 0; NSUInteger endOffset = 0; - convertLineOffset(iface->textInterface(), line, lineOffset, &startOffset, &endOffset); + convertLineOffset(iface->textInterface(), &line, &lineOffset, &startOffset, &endOffset); return [NSValue valueWithRange:NSMakeRange(startOffset, endOffset - startOffset)]; } if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) { -- cgit v1.2.3 From e8ad49d6cba6521f20b1b08bf65d92fc81c158e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sat, 16 Jan 2016 00:57:54 +0100 Subject: xcb: Fallback to Xlib screen when glXGetCurrentDisplay() returns NULL Change-Id: Ie25b3fac4c0224f847c77c0515894a9df84077a2 Reviewed-by: Laszlo Agocs --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 9 ++++++--- .../platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/plugins') 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 3412f3f3fc..22e68e3db7 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -645,9 +645,12 @@ void QGLXContext::queryDummyContext() QScopedPointer surface; Display *display = glXGetCurrentDisplay(); - const char *glxvendor = 0; - if (display) - glxvendor = glXGetClientString(display, GLX_VENDOR); + if (!display) { + // FIXME: Since Qt 5.6 we don't need to check whether primary screen is NULL + if (QScreen *screen = QGuiApplication::primaryScreen()) + display = DISPLAY_FROM_XCB(static_cast(screen->handle())); + } + const char *glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) { QWindow *window = new QWindow; window->resize(64, 64); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index cd4949af5c..a3a8aa259b 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -196,9 +196,11 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO if (!vendorChecked) { vendorChecked = true; Display *display = glXGetCurrentDisplay(); - const char *glxvendor = 0; - if (display) - glxvendor = glXGetClientString(display, GLX_VENDOR); +#ifdef XCB_USE_XLIB + if (!display) + display = static_cast(m_connection->xlib_display()); +#endif + const char *glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) glxPbufferUsable = false; } -- cgit v1.2.3 From a87dfdb19683cd106aa81d4053c255251a5e37a0 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 14 Jul 2015 12:44:17 +0200 Subject: WinCE: Build accessibility support on WinCE7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build the QPlatformAccessibility support on WinCE7, so that QtQuickControls, which depend on the availability of QPlatformAccessibility, can be used on WinCE7 as well. Change-Id: Ice7370b891a2963483bbfe1af8b219717541e64b Reviewed-by: Björn Breitmeyer Reviewed-by: Jan Arve Sæther Reviewed-by: Frederik Gladhorn --- .../platforms/windows/accessible/accessible.pri | 17 ++++++----- .../windows/accessible/qwindowsaccessibility.cpp | 34 +++++++++++++++------- 2 files changed, 34 insertions(+), 17 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index e26c6614e2..0774d907f2 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -1,17 +1,20 @@ SOURCES += \ - $$PWD/qwindowsmsaaaccessible.cpp \ $$PWD/qwindowsaccessibility.cpp \ $$PWD/comutils.cpp HEADERS += \ - $$PWD/qwindowsmsaaaccessible.h \ $$PWD/qwindowsaccessibility.h \ $$PWD/comutils.h -!mingw: { - SOURCES += $$PWD/iaccessible2.cpp - HEADERS += $$PWD/iaccessible2.h - include(../../../../3rdparty/iaccessible2/iaccessible2.pri) +!wince: { + SOURCES += $$PWD/qwindowsmsaaaccessible.cpp + HEADERS += $$PWD/qwindowsmsaaaccessible.h + + !mingw: { + SOURCES += $$PWD/iaccessible2.cpp + HEADERS += $$PWD/iaccessible2.h + include(../../../../3rdparty/iaccessible2/iaccessible2.pri) + } } -mingw: LIBS *= -luuid \ No newline at end of file +mingw: LIBS *= -luuid diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index 7015424f47..0437290dcb 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -50,10 +50,12 @@ #include #include "qwindowsaccessibility.h" -#ifdef Q_CC_MINGW -# include "qwindowsmsaaaccessible.h" -#else -# include "iaccessible2.h" +#if !defined(Q_OS_WINCE) +# ifdef Q_CC_MINGW +# include "qwindowsmsaaaccessible.h" +# else +# include "iaccessible2.h" +# endif #endif #include "comutils.h" @@ -68,8 +70,9 @@ #if !defined(WINABLEAPI) # if defined(Q_OS_WINCE) # include +# else +# include # endif -# include #endif #include @@ -193,6 +196,11 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) */ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) { +#if defined(Q_OS_WINCE) + Q_UNUSED(acc); + + return 0; +#else if (!acc) return 0; @@ -200,14 +208,15 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) if (!QAccessible::uniqueId(acc)) QAccessible::registerAccessibleInterface(acc); -#ifdef Q_CC_MINGW +# ifdef Q_CC_MINGW QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc); -#else +# else QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); -#endif +# endif IAccessible *iacc = 0; wacc->QueryInterface(IID_IAccessible, (void**)&iacc); return iacc; +#endif // defined(Q_OS_WINCE) } /* @@ -230,6 +239,7 @@ void QWindowsAccessibility::cleanup() bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) { +#if !defined(Q_OS_WINCE) if (static_cast(lParam) == static_cast(UiaRootObjectId)) { /* For UI Automation */ } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { @@ -248,9 +258,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (!oleaccChecked) { oleaccChecked = true; -#if !defined(Q_OS_WINCE) ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); -#endif } if (ptrLresultFromObject) { @@ -269,6 +277,12 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W } } } +#else + Q_UNUSED(hwnd); + Q_UNUSED(wParam); + Q_UNUSED(lParam); + Q_UNUSED(lResult); +#endif // !defined(Q_OS_WINCE) return false; } -- cgit v1.2.3 From 30bff91c3920fdf92d81d42983e31e8d0766969f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 15 Jan 2016 14:15:51 +0100 Subject: OS X: Ensure system tray icon is prepared even when menu bar is hidden On OS X 10.11 (El Capitan) the system menu bar can be automatically hidden, in which case the menu bar height is reported to be 0 when using the menuBarHeight API. This resulted in failing to prepare an image for the system tray icon item, making the tray item "invisible". Instead we now use the [[NSStatusBar systemStatusBar] thickness] API, which returns the correct height regardless of the menu bar being hidden or not. Task-number: QTBUG-48960 Change-Id: I208fb8df13754964a6f254cadfbff06dd56c6bab Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index a3ffb5be66..8152c57ffd 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -198,7 +198,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) // current OS X versions is 22 points. Provide some future-proofing // by deriving the icon height from the menu height. const int padding = 4; - const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; const int maxImageHeight = menuHeight - padding; // Select pixmap based on the device pixel height. Ideally we would use -- cgit v1.2.3 From b9bd83c9c2992a156583f5e211eed9adb7f23d6b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 18 Jan 2016 15:04:06 +0100 Subject: Fix transformed text with DirectWrite engine This is a port of f54c5d9133d7aa7636988db36fa6cc51d26434b6 from Qt 4.8 which was lost in the transition to Qt 5. It makes sure we use the correct bounding box for the transformed glyph by getting from DirectWrite itself. [ChangeLog][Windows] Fixed transformed text when using the DirectWrite font engine. Task-number: QTBUG-50009 Change-Id: I416ab64253165b878af6b9837348134fede8092e Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- .../windows/qwindowsfontenginedirectwrite.cpp | 145 ++++++++++++++------- 1 file changed, 98 insertions(+), 47 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index a50ee60975..bb4f4b1abd 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -520,13 +520,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, int margin, const QTransform &xform) { - glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform); - // This needs to be kept in sync with alphaMapBoundingBox - int width = (metrics.width + margin * 2).ceil().toInt() ; - int height = (metrics.height + margin * 2).ceil().toInt(); - UINT16 glyphIndex = t; - FLOAT glyphAdvance = metrics.xoff.toReal(); + FLOAT glyphAdvance = 0; DWRITE_GLYPH_OFFSET glyphOffset; glyphOffset.advanceOffset = 0; @@ -542,12 +537,9 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.bidiLevel = 0; glyphRun.glyphOffsets = &glyphOffset; - QFixed x = margin - metrics.x.floor() + subPixelPosition; - QFixed y = margin - metrics.y.floor(); - DWRITE_MATRIX transform; - transform.dx = x.toReal(); - transform.dy = y.toReal(); + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; transform.m11 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); @@ -571,46 +563,56 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, if (SUCCEEDED(hr)) { RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - int size = width * height * 3; - BYTE *alphaValues = new BYTE[size]; - memset(alphaValues, 0, size); + rect.left -= margin; + rect.top -= margin; + rect.right += margin; + rect.bottom += margin; - hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); + const int width = rect.right - rect.left; + const int height = rect.bottom - rect.top; - if (SUCCEEDED(hr)) { - QImage img(width, height, QImage::Format_RGB32); - img.fill(0xffffffff); + const int size = width * height * 3; + if (size > 0) { + BYTE *alphaValues = new BYTE[size]; + memset(alphaValues, 0, size); - for (int y=0; y(img.scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; + hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, + &rect, + alphaValues, + size); - for (int x=0; x(img.scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; + + for (int x=0; xRelease(); + delete[] alphaValues; + glyphAnalysis->Release(); + + return img; + } else { + delete[] alphaValues; + glyphAnalysis->Release(); - return img; + qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + } } else { - delete[] alphaValues; glyphAnalysis->Release(); - - qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + qWarning("%s: Glyph has no bounds", __FUNCTION__); } } else { @@ -724,16 +726,65 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN return QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString(); } -glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) +glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, + QFixed subPixelPosition, + const QTransform &matrix, + GlyphFormat format) { - Q_UNUSED(pos); Q_UNUSED(format); + glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance + + UINT16 glyphIndex = glyph; + FLOAT glyphAdvance = 0; + + DWRITE_GLYPH_OFFSET glyphOffset; + glyphOffset.advanceOffset = 0; + glyphOffset.ascenderOffset = 0; + + DWRITE_GLYPH_RUN glyphRun; + glyphRun.fontFace = m_directWriteFontFace; + glyphRun.fontEmSize = fontDef.pixelSize; + glyphRun.glyphCount = 1; + glyphRun.glyphIndices = &glyphIndex; + glyphRun.glyphAdvances = &glyphAdvance; + glyphRun.isSideways = false; + glyphRun.bidiLevel = 0; + glyphRun.glyphOffsets = &glyphOffset; + + DWRITE_MATRIX transform; + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; + transform.m11 = matrix.m11(); + transform.m12 = matrix.m12(); + transform.m21 = matrix.m21(); + transform.m22 = matrix.m22(); + + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; + HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( + &glyphRun, + 1.0f, + &transform, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, + 0.0, 0.0, + &glyphAnalysis + ); - int margin = glyphMargin(QFontEngine::Format_A32); - glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix); - gm.width += margin * 2; - gm.height += margin * 2; - return gm; + if (SUCCEEDED(hr)) { + RECT rect; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); + glyphAnalysis->Release(); + + int margin = glyphMargin(QFontEngine::Format_A32); + + return glyph_metrics_t(rect.left, + rect.top, + rect.right - rect.left + margin * 2, + rect.bottom - rect.top + margin * 2, + bbox.xoff, bbox.yoff); + } else { + return glyph_metrics_t(); + } } QT_END_NAMESPACE -- cgit v1.2.3