From 223fc10cdee20ecb97337f0a3e6e3b9cc10fff75 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 17 Aug 2014 13:58:02 +0200 Subject: [PATCH 01/32] QWaylandWindow: Add a missing shell surface null check. Caught by tst_QWidget::mapFromAndTo. Change-Id: I36e08ebfa3bae1ac8667ee828b1762867d71c66d Reviewed-by: Giulio Camuffo --- .../platforms/wayland/qwaylandwindow.cpp | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 6ebe610abef..1e40998a60f 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -657,18 +657,21 @@ bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state) // here. We use then this mState variable. mState = state; createDecoration(); - switch (state) { - case Qt::WindowFullScreen: - mShellSurface->setFullscreen(); - break; - case Qt::WindowMaximized: - mShellSurface->setMaximized(); - break; - case Qt::WindowMinimized: - mShellSurface->setMinimized(); - break; - default: - mShellSurface->setNormal(); + + if (mShellSurface) { + switch (state) { + case Qt::WindowFullScreen: + mShellSurface->setFullscreen(); + break; + case Qt::WindowMaximized: + mShellSurface->setMaximized(); + break; + case Qt::WindowMinimized: + mShellSurface->setMinimized(); + break; + default: + mShellSurface->setNormal(); + } } QWindowSystemInterface::handleWindowStateChanged(window(), mState); From e03a21353c965e79ff9295454bffffc4351b96d9 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 17 Aug 2014 15:39:27 +0200 Subject: [PATCH 02/32] Remove qPlatformScreenForWindow from header. Use of this was removed in 02e50ef592f28ec05654acf3f6c9b84d31736269. Change-Id: I729282bfa9536380fc0d5b2702448cc54a90e37d Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylandnativeinterface_p.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandnativeinterface_p.h b/src/plugins/platforms/wayland/qwaylandnativeinterface_p.h index 536cbe8dd53..6c0be2d3c8d 100644 --- a/src/plugins/platforms/wayland/qwaylandnativeinterface_p.h +++ b/src/plugins/platforms/wayland/qwaylandnativeinterface_p.h @@ -68,8 +68,6 @@ public: void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value); void emitWindowPropertyChanged(QPlatformWindow *window, const QString &name); -private: - static QWaylandScreen *qPlatformScreenForWindow(QWindow *window); private: QWaylandIntegration *m_integration; From 131ccbd4cd44a401603a537421f4f803217e7a3d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 17 Aug 2014 16:07:21 +0200 Subject: [PATCH 03/32] QWaylandDisplay: Remove unused static. Change-Id: I868168dee716103962217b5ceb38185090f82e09 Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 5764d3110fd..88e4e4a5ba4 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -116,8 +116,6 @@ void QWaylandDisplay::setLastKeyboardFocusInputDevice(QWaylandInputDevice *devic mLastKeyboardFocusInputDevice = device; } -static QWaylandDisplay *display = 0; - QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) : mWaylandIntegration(waylandIntegration) , mLastKeyboardFocusInputDevice(0) @@ -130,7 +128,6 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) , mTextInputManager(0) , mHardwareIntegration(0) { - display = this; qRegisterMetaType("uint32_t"); mEventThreadObject = new QWaylandEventThread(0); From 132cbe541433d6b4d0bb00c64095519d0779d13a Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 17 Aug 2014 16:07:47 +0200 Subject: [PATCH 04/32] QWaylandDisplay: Destroy screens when destroying the display. Fixes a crash in tst_QApplication. Change-Id: Ibfc7aded10609cff9c7a20b7193f44d1c73bc893 Reviewed-by: Gunnar Sletta --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 88e4e4a5ba4..242a13a155a 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -156,6 +156,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) QWaylandDisplay::~QWaylandDisplay(void) { + qDeleteAll(mScreens); + mScreens.clear(); delete mDndSelectionHandler.take(); mEventThread->quit(); mEventThread->wait(); From 34d69d9b4de50857ce645e8f414743c339ff61b6 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Sun, 17 Aug 2014 16:08:45 +0200 Subject: [PATCH 05/32] QWaylandScreen: Also call QPlatformScreen constructor. Change-Id: Iae63ea5b15f2422ea28f2f9c8d7abeb30d23c86f Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylandscreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 3432f247595..fde5751dc0f 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) - : QtWayland::wl_output(waylandDisplay->wl_registry(), id) + : QPlatformScreen() + , QtWayland::wl_output(waylandDisplay->wl_registry(), id) , mWaylandDisplay(waylandDisplay) , mExtendedOutput(0) , mDepth(32) From 2efc3bcf4da08acd36df45ec4afce0d17187956e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 16 Aug 2014 12:48:38 -0700 Subject: [PATCH 06/32] Fix warning about use of uninitialized variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qwaylandwindow.cpp:443:25: warning: ‘transform’ may be used uninitialized in this function [-Wmaybe-uninitialized] Change-Id: Ic0a96cfda35d331c9957a527eea7f8b987191b5f Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylandwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 1e40998a60f..b7f3c4c7ef7 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -438,6 +438,8 @@ void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orient case Qt::InvertedPortraitOrientation: transform = isPortrait ? WL_OUTPUT_TRANSFORM_180 : WL_OUTPUT_TRANSFORM_270; break; + default: + Q_UNREACHABLE(); } set_buffer_transform(transform); // set_buffer_transform is double buffered, we need to commit. From 76f5ad1784718abee46b5659baa45ef5331b4236 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Tue, 19 Aug 2014 16:19:12 +0300 Subject: [PATCH 07/32] Make the test client more robust and make valgrind happy Change-Id: I39ce667123391b946711cc2d16d12799e8b7dd2d Reviewed-by: Robin Burchell --- tests/auto/wayland/mockcompositor.cpp | 19 +++---- tests/auto/wayland/mockcompositor.h | 2 - tests/auto/wayland/mockinput.cpp | 4 ++ tests/auto/wayland/mockshell.cpp | 3 ++ tests/auto/wayland/mocksurface.cpp | 75 ++++++++++++++++----------- tests/auto/wayland/mocksurface.h | 7 ++- tests/auto/wayland/tst_client.cpp | 4 -- 7 files changed, 63 insertions(+), 51 deletions(-) diff --git a/tests/auto/wayland/mockcompositor.cpp b/tests/auto/wayland/mockcompositor.cpp index bb4f10fd942..70fa5f23265 100644 --- a/tests/auto/wayland/mockcompositor.cpp +++ b/tests/auto/wayland/mockcompositor.cpp @@ -135,8 +135,13 @@ QSharedPointer MockCompositor::surface() QSharedPointer result; lock(); QVector surfaces = m_compositor->surfaces(); - if (!surfaces.isEmpty()) - result = surfaces.first()->mockSurface(); + foreach (Impl::Surface *surface, surfaces) { + // we don't want to mistake the cursor surface for a window surface + if (surface->isMapped()) { + result = surface->mockSurface(); + break; + } + } unlock(); return result; } @@ -189,11 +194,6 @@ void *MockCompositor::run(void *data) return 0; } -void MockCompositor::discardSurfaces() -{ - m_compositor->discardSurfaces(); -} - namespace Impl { Compositor::Compositor() @@ -298,10 +298,5 @@ void Compositor::removeSurface(Surface *surface) m_pointer->setFocus(0, QPoint()); } -void Compositor::discardSurfaces() -{ - m_surfaces.clear(); -} - } diff --git a/tests/auto/wayland/mockcompositor.h b/tests/auto/wayland/mockcompositor.h index 68e55d3562c..7f3e2268312 100644 --- a/tests/auto/wayland/mockcompositor.h +++ b/tests/auto/wayland/mockcompositor.h @@ -81,7 +81,6 @@ public: void addSurface(Surface *surface); void removeSurface(Surface *surface); - void discardSurfaces(); static void setKeyboardFocus(void *data, const QList ¶meters); static void sendMousePress(void *data, const QList ¶meters); @@ -155,7 +154,6 @@ public: void sendKeyRelease(const QSharedPointer &surface, uint code); QSharedPointer surface(); - void discardSurfaces(); void lock(); void unlock(); diff --git a/tests/auto/wayland/mockinput.cpp b/tests/auto/wayland/mockinput.cpp index 7dbb735ed22..bd85ad6c897 100644 --- a/tests/auto/wayland/mockinput.cpp +++ b/tests/auto/wayland/mockinput.cpp @@ -130,6 +130,8 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id) Keyboard::Keyboard(Compositor *compositor) : wl_keyboard() , m_compositor(compositor) + , m_focusResource(Q_NULLPTR) + , m_focus(Q_NULLPTR) { } @@ -174,6 +176,8 @@ void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) Pointer::Pointer(Compositor *compositor) : wl_pointer() , m_compositor(compositor) + , m_focusResource(Q_NULLPTR) + , m_focus(Q_NULLPTR) { } diff --git a/tests/auto/wayland/mockshell.cpp b/tests/auto/wayland/mockshell.cpp index 0d841f64c24..2a5969f70de 100644 --- a/tests/auto/wayland/mockshell.cpp +++ b/tests/auto/wayland/mockshell.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "mockcompositor.h" +#include "mocksurface.h" namespace Impl { @@ -173,6 +174,8 @@ static void get_shell_surface(wl_client *client, wl_resource *compositorResource Q_UNUSED(compositorResource); wl_client_add_object(client, &wl_shell_surface_interface, &shellSurfaceInterface, id, surfaceResource->data); + Surface *surf = Surface::fromResource(surfaceResource); + surf->map(); } void Compositor::bindShell(wl_client *client, void *compositorData, uint32_t version, uint32_t id) diff --git a/tests/auto/wayland/mocksurface.cpp b/tests/auto/wayland/mocksurface.cpp index d5e0367a080..2e4c2bc73a4 100644 --- a/tests/auto/wayland/mocksurface.cpp +++ b/tests/auto/wayland/mocksurface.cpp @@ -46,10 +46,11 @@ namespace Impl { Surface::Surface(wl_client *client, uint32_t id, Compositor *compositor) : QtWaylandServer::wl_surface(client, id) + , m_buffer(Q_NULLPTR) , m_compositor(compositor) , m_mockSurface(new MockSurface(this)) + , m_mapped(false) { - wl_list_init(&m_frameCallbackList); } Surface::~Surface() @@ -57,6 +58,21 @@ Surface::~Surface() m_mockSurface->m_surface = 0; } +void Surface::map() +{ + m_mapped = true; +} + +bool Surface::isMapped() const +{ + return m_mapped; +} + +Surface *Surface::fromResource(struct ::wl_resource *resource) +{ + return static_cast(Resource::fromResource(resource)->surface_object); +} + void Surface::surface_destroy_resource(Resource *) { compositor()->removeSurface(this); @@ -88,47 +104,44 @@ void Surface::surface_damage(Resource *resource, Q_UNUSED(y); Q_UNUSED(width); Q_UNUSED(height); - - if (!m_buffer) - return; - -#if WAYLAND_VERSION_CHECK(1, 2, 0) - struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer); -#else - struct ::wl_buffer *shm_buffer = 0; - if (wl_buffer_is_shm(static_cast(m_buffer->data))) - shm_buffer = static_cast(m_buffer->data); -#endif - - if (shm_buffer) { - int stride = wl_shm_buffer_get_stride(shm_buffer); - uint format = wl_shm_buffer_get_format(shm_buffer); - Q_UNUSED(format); - void *data = wl_shm_buffer_get_data(shm_buffer); - const uchar *char_data = static_cast(data); - QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied); - m_mockSurface->image = img; - } - - wl_resource *frameCallback; - wl_list_for_each(frameCallback, &m_frameCallbackList, link) { - wl_callback_send_done(frameCallback, m_compositor->time()); - wl_resource_destroy(frameCallback); - } - - wl_list_init(&m_frameCallbackList); } void Surface::surface_frame(Resource *resource, uint32_t callback) { wl_resource *frameCallback = wl_client_add_object(resource->client(), &wl_callback_interface, 0, callback, this); - wl_list_insert(&m_frameCallbackList, &frameCallback->link); + m_frameCallbackList << frameCallback; } void Surface::surface_commit(Resource *resource) { Q_UNUSED(resource); + + if (m_buffer) { +#if WAYLAND_VERSION_CHECK(1, 2, 0) + struct ::wl_shm_buffer *shm_buffer = wl_shm_buffer_get(m_buffer); +#else + struct ::wl_buffer *shm_buffer = 0; + if (wl_buffer_is_shm(static_cast(m_buffer->data))) + shm_buffer = static_cast(m_buffer->data); +#endif + + if (shm_buffer) { + int stride = wl_shm_buffer_get_stride(shm_buffer); + uint format = wl_shm_buffer_get_format(shm_buffer); + Q_UNUSED(format); + void *data = wl_shm_buffer_get_data(shm_buffer); + const uchar *char_data = static_cast(data); + QImage img(char_data, wl_shm_buffer_get_width(shm_buffer), wl_shm_buffer_get_height(shm_buffer), stride, QImage::Format_ARGB32_Premultiplied); + m_mockSurface->image = img; + } + } + + foreach (wl_resource *frameCallback, m_frameCallbackList) { + wl_callback_send_done(frameCallback, m_compositor->time()); + wl_resource_destroy(frameCallback); + } + m_frameCallbackList.clear(); } } diff --git a/tests/auto/wayland/mocksurface.h b/tests/auto/wayland/mocksurface.h index 49260f51b38..f2a2f4eb355 100644 --- a/tests/auto/wayland/mocksurface.h +++ b/tests/auto/wayland/mocksurface.h @@ -54,6 +54,9 @@ public: ~Surface(); Compositor *compositor() const { return m_compositor; } + static Surface *fromResource(struct ::wl_resource *resource); + void map(); + bool isMapped() const; QSharedPointer mockSurface() const { return m_mockSurface; } @@ -74,8 +77,8 @@ private: Compositor *m_compositor; QSharedPointer m_mockSurface; - - wl_list m_frameCallbackList; + QList m_frameCallbackList; + bool m_mapped; }; } diff --git a/tests/auto/wayland/tst_client.cpp b/tests/auto/wayland/tst_client.cpp index 9c3138bcb09..e13d738dc34 100644 --- a/tests/auto/wayland/tst_client.cpp +++ b/tests/auto/wayland/tst_client.cpp @@ -149,11 +149,7 @@ private: void tst_WaylandClient::screen() { - QCoreApplication::processEvents(QEventLoop::AllEvents); - QTRY_COMPARE(QGuiApplication::primaryScreen()->size(), screenSize); - // discard the cursor surface created by the QWaylandInputDevice - compositor->discardSurfaces(); } void tst_WaylandClient::createDestroyWindow() From c6766fe4f4c6b7145131ea6210fbb601571e961d Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 19 Aug 2014 18:24:56 +0200 Subject: [PATCH 08/32] QWaylandDisplay: Correctly intercept all errors when dispatching. A connection reset isn't the only form of error we may run into, so make sure we check for other exceptional circumstances through wl_display_get_error. This fixes my case of e.g. wl_drm throwing an error but QtWayland never quitting the client. Change-Id: I8c76dd7913640e58d03bd2fe52eb054a4daa0235 Reviewed-by: Giulio Camuffo --- .../platforms/wayland/qwaylanddisplay.cpp | 21 +++++++++++++++---- .../platforms/wayland/qwaylandeventthread.cpp | 10 +++++++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 242a13a155a..74efbfda4c2 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -166,18 +166,31 @@ QWaylandDisplay::~QWaylandDisplay(void) void QWaylandDisplay::flushRequests() { - if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) == -1 && (errno == EPIPE || errno == ECONNRESET)) { - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) { + int ecode = wl_display_get_error(mDisplay); + if ((ecode == EPIPE || ecode == ECONNRESET)) { + // special case this to provide a nicer error + qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + } else { + qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); + } ::exit(1); } + wl_display_flush(mDisplay); } void QWaylandDisplay::blockingReadEvents() { - if (wl_display_dispatch_queue(mDisplay, mEventQueue) == -1 && (errno == EPIPE || errno == ECONNRESET)) { - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) { + int ecode = wl_display_get_error(mDisplay); + if ((ecode == EPIPE || ecode == ECONNRESET)) { + // special case this to provide a nicer error + qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + } else { + qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); + } ::exit(1); } } diff --git a/src/plugins/platforms/wayland/qwaylandeventthread.cpp b/src/plugins/platforms/wayland/qwaylandeventthread.cpp index c6ac42bba8f..979aa6e0ebf 100644 --- a/src/plugins/platforms/wayland/qwaylandeventthread.cpp +++ b/src/plugins/platforms/wayland/qwaylandeventthread.cpp @@ -73,8 +73,14 @@ void QWaylandEventThread::displayConnect() void QWaylandEventThread::readWaylandEvents() { - if (wl_display_dispatch(m_display) == -1 && (errno == EPIPE || errno == ECONNRESET)) { - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + if (wl_display_dispatch(m_display) < 0) { + int ecode = wl_display_get_error(m_display); + if ((ecode == EPIPE || ecode == ECONNRESET)) { + // special case this to provide a nicer error + qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + } else { + qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); + } ::exit(1); } emit newEventsRead(); From bb360fce60e6632661d210edef6ade136e6064b9 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 19 Aug 2014 18:40:19 +0200 Subject: [PATCH 09/32] QWaylandDisplay: Centralize error handling in one place. Change-Id: Ifba23e349a4006cea501480a7230408f0fafd1b7 Reviewed-by: Giulio Camuffo --- .../platforms/wayland/qwaylanddisplay.cpp | 24 +++-------------- .../platforms/wayland/qwaylandeventthread.cpp | 27 ++++++++++++------- .../platforms/wayland/qwaylandeventthread_p.h | 2 ++ 3 files changed, 23 insertions(+), 30 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 74efbfda4c2..94bfa88bc1b 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -166,16 +166,8 @@ QWaylandDisplay::~QWaylandDisplay(void) void QWaylandDisplay::flushRequests() { - if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) { - int ecode = wl_display_get_error(mDisplay); - if ((ecode == EPIPE || ecode == ECONNRESET)) { - // special case this to provide a nicer error - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); - } else { - qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); - } - ::exit(1); - } + if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) + mEventThreadObject->checkErrorAndExit(); wl_display_flush(mDisplay); } @@ -183,16 +175,8 @@ void QWaylandDisplay::flushRequests() void QWaylandDisplay::blockingReadEvents() { - if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) { - int ecode = wl_display_get_error(mDisplay); - if ((ecode == EPIPE || ecode == ECONNRESET)) { - // special case this to provide a nicer error - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); - } else { - qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); - } - ::exit(1); - } + if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) + mEventThreadObject->checkErrorAndExit(); } QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const diff --git a/src/plugins/platforms/wayland/qwaylandeventthread.cpp b/src/plugins/platforms/wayland/qwaylandeventthread.cpp index 979aa6e0ebf..b7266765e61 100644 --- a/src/plugins/platforms/wayland/qwaylandeventthread.cpp +++ b/src/plugins/platforms/wayland/qwaylandeventthread.cpp @@ -71,18 +71,25 @@ void QWaylandEventThread::displayConnect() QMetaObject::invokeMethod(this, "waylandDisplayConnect", Qt::QueuedConnection); } +// ### be careful what you do, this function may also be called from other +// threads to clean up & exit. +void QWaylandEventThread::checkErrorAndExit() +{ + int ecode = wl_display_get_error(m_display); + if ((ecode == EPIPE || ecode == ECONNRESET)) { + // special case this to provide a nicer error + qWarning("The Wayland connection broke. Did the Wayland compositor die?"); + } else { + qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); + } + ::exit(1); +} + void QWaylandEventThread::readWaylandEvents() { - if (wl_display_dispatch(m_display) < 0) { - int ecode = wl_display_get_error(m_display); - if ((ecode == EPIPE || ecode == ECONNRESET)) { - // special case this to provide a nicer error - qWarning("The Wayland connection broke. Did the Wayland compositor die?"); - } else { - qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); - } - ::exit(1); - } + if (wl_display_dispatch(m_display) < 0) + checkErrorAndExit(); + emit newEventsRead(); } diff --git a/src/plugins/platforms/wayland/qwaylandeventthread_p.h b/src/plugins/platforms/wayland/qwaylandeventthread_p.h index 0d2758c4c67..d51d627b962 100644 --- a/src/plugins/platforms/wayland/qwaylandeventthread_p.h +++ b/src/plugins/platforms/wayland/qwaylandeventthread_p.h @@ -63,6 +63,8 @@ public: wl_display *display() const; + void checkErrorAndExit(); + private slots: void readWaylandEvents(); From 8975683c37fb721371f72cd0c1542059f9e0e1de Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Aug 2014 15:51:04 +0200 Subject: [PATCH 10/32] QWaylandDecoration: Remove some unused members Change-Id: Ia98190adbd3f710de6734c10062792ce3f4547d9 Reviewed-by: Giulio Camuffo --- .../platforms/wayland/qwaylanddecoration.cpp | 12 +----------- .../platforms/wayland/qwaylanddecoration_p.h | 16 ---------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/qwaylanddecoration.cpp index 8e7d03143a1..b288debe9eb 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylanddecoration.cpp @@ -186,7 +186,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) // Title bar QPoint gradCenter(top.center()+ QPoint(30, 60)); QLinearGradient grad(top.topLeft(), top.bottomLeft()); - QColor base(backgroundColor()); + QColor base(m_backgroundColor); grad.setColorAt(0, base.lighter(100)); grad.setColorAt(1, base.darker(180)); QPainterPath roundedRect; @@ -446,14 +446,4 @@ QRectF QWaylandDecoration::minimizeButtonRect() const (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -void QWaylandDecoration::setForegroundColor(const QColor &c) -{ - m_foregroundColor = c; -} - -void QWaylandDecoration::setBackgroundColor(const QColor &c) -{ - m_backgroundColor = c; -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddecoration_p.h b/src/plugins/platforms/wayland/qwaylanddecoration_p.h index 3f53721f75d..14bf4a92d68 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration_p.h +++ b/src/plugins/platforms/wayland/qwaylanddecoration_p.h @@ -84,12 +84,6 @@ public: QWaylandWindow *waylandWindow() const; const QImage &contentImage(); - void setForegroundColor(const QColor &c); - inline QColor foregroundColor() const; - - void setBackgroundColor(const QColor &c); - inline QColor backgroundColor() const; - protected: void paint(QPaintDevice *device); @@ -140,16 +134,6 @@ inline QWaylandWindow *QWaylandDecoration::waylandWindow() const return m_wayland_window; } -inline QColor QWaylandDecoration::foregroundColor() const -{ - return m_foregroundColor; -} - -inline QColor QWaylandDecoration::backgroundColor() const -{ - return m_backgroundColor; -} - QT_END_NAMESPACE #endif // QWAYLANDDECORATION_H From 9ac0da7c31647e05913eb856feea54328469a255 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Wed, 20 Aug 2014 21:33:55 +0200 Subject: [PATCH 11/32] Fix window decorations being leaked. Change-Id: If0483f5e81a033b275ddc14eb1e44ff82fa1ce65 Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylandwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index b7f3c4c7ef7..8679463ec6b 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -130,6 +130,8 @@ QWaylandWindow::QWaylandWindow(QWindow *window) QWaylandWindow::~QWaylandWindow() { + delete mWindowDecoration; + if (isInitialized()) { delete mShellSurface; destroy(); From f4e576fbe93c155db448787315f126e8d3b3d5b5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Aug 2014 17:04:04 +0200 Subject: [PATCH 12/32] Fix typo Change-Id: Idd4351b2650e8869d0e6038d11be5da37f4bdbb1 Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylandintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 88eeed842ad..0c90626964c 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -291,7 +291,7 @@ void QWaylandIntegration::initializeClientBufferIntegration() } if (targetKey.isEmpty()) { - qWarning("Failed to determin what client buffer integration to use"); + qWarning("Failed to determine what client buffer integration to use"); return; } From 611716293c80bcf5b6fcbc57b869ce2cf853add1 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sat, 23 Aug 2014 20:00:03 +0300 Subject: [PATCH 13/32] Explicitly define the interface versions Currently a global is bound with the version the interface has in the xml file. This is a problem for apps that explicitly link to libwayland-client because they may link to a newer libwayland, so the version of some interface may be higher than the one that it is actually implemented. Change-Id: Id0dbe6c0f1e05fe91954b9d8d9472d42d2053cdc Reviewed-by: Laszlo Agocs --- .../qwaylandhardwareintegration.cpp | 2 +- .../platforms/wayland/qwaylanddatadevicemanager.cpp | 2 +- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 12 ++++++------ .../platforms/wayland/qwaylandinputdevice.cpp | 2 +- src/plugins/platforms/wayland/qwaylandqtkey.cpp | 2 +- src/plugins/platforms/wayland/qwaylandscreen.cpp | 2 +- src/plugins/platforms/wayland/qwaylandtouch.cpp | 2 +- .../wayland/qwaylandwindowmanagerintegration.cpp | 2 +- src/plugins/platforms/wayland/qwaylandxdgshell.cpp | 2 +- src/tools/qtwaylandscanner/qtwaylandscanner.cpp | 12 ++++++------ 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/wayland/hardwareintegration/qwaylandhardwareintegration.cpp b/src/plugins/platforms/wayland/hardwareintegration/qwaylandhardwareintegration.cpp index a7269ce9e54..469f80360f3 100644 --- a/src/plugins/platforms/wayland/hardwareintegration/qwaylandhardwareintegration.cpp +++ b/src/plugins/platforms/wayland/hardwareintegration/qwaylandhardwareintegration.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE QWaylandHardwareIntegration::QWaylandHardwareIntegration(struct ::wl_registry *registry, int id) - : qt_hardware_integration(registry, id) + : qt_hardware_integration(registry, id, 1) { } diff --git a/src/plugins/platforms/wayland/qwaylanddatadevicemanager.cpp b/src/plugins/platforms/wayland/qwaylanddatadevicemanager.cpp index 1aef773490f..ea578ff7b1d 100644 --- a/src/plugins/platforms/wayland/qwaylanddatadevicemanager.cpp +++ b/src/plugins/platforms/wayland/qwaylanddatadevicemanager.cpp @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id) - : wl_data_device_manager(display->wl_registry(), id) + : wl_data_device_manager(display->wl_registry(), id, 1) , m_display(display) { // Create transfer devices for all input devices. diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 94bfa88bc1b..595d2ce77ee 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -219,33 +219,33 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin // We need to get the output events before creating surfaces forceRoundTrip(); } else if (interface == QStringLiteral("wl_compositor")) { - mCompositor.init(registry, id); + mCompositor.init(registry, id, 3); } else if (interface == QStringLiteral("wl_shm")) { mShm = static_cast(wl_registry_bind(registry, id, &wl_shm_interface,1)); } else if (interface == QStringLiteral("xdg_shell") && qEnvironmentVariableIsSet("QT_WAYLAND_USE_XDG_SHELL")) { mShellXdg.reset(new QWaylandXdgShell(registry,id)); } else if (interface == QStringLiteral("wl_shell")){ - mShell.reset(new QtWayland::wl_shell(registry, id)); + mShell.reset(new QtWayland::wl_shell(registry, id, 1)); } else if (interface == QStringLiteral("wl_seat")) { QWaylandInputDevice *inputDevice = new QWaylandInputDevice(this, id); mInputDevices.append(inputDevice); } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); } else if (interface == QStringLiteral("qt_output_extension")) { - mOutputExtension.reset(new QtWayland::qt_output_extension(registry, id)); + mOutputExtension.reset(new QtWayland::qt_output_extension(registry, id, 1)); foreach (QPlatformScreen *screen, screens()) static_cast(screen)->createExtendedOutput(); } else if (interface == QStringLiteral("qt_surface_extension")) { - mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id)); + mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1)); } else if (interface == QStringLiteral("qt_sub_surface_extension")) { - mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id)); + mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id, 1)); } else if (interface == QStringLiteral("qt_touch_extension")) { mTouchExtension.reset(new QWaylandTouchExtension(this, id)); } else if (interface == QStringLiteral("qt_key_extension")) { mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id)); } else if (interface == QStringLiteral("wl_text_input_manager")) { - mTextInputManager.reset(new QtWayland::wl_text_input_manager(registry, id)); + mTextInputManager.reset(new QtWayland::wl_text_input_manager(registry, id, 1)); } else if (interface == QStringLiteral("qt_hardware_integration")) { mHardwareIntegration.reset(new QWaylandHardwareIntegration(registry, id)); // make a roundtrip here since we need to receive the events sent by diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 145ef608d28..6c132010268 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -228,7 +228,7 @@ public: QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) : QObject() - , QtWayland::wl_seat(display->wl_registry(), id) + , QtWayland::wl_seat(display->wl_registry(), id, 2) , mQDisplay(display) , mDisplay(display->wl_display()) , mCaps(0) diff --git a/src/plugins/platforms/wayland/qwaylandqtkey.cpp b/src/plugins/platforms/wayland/qwaylandqtkey.cpp index 197914b0b9c..16562357f00 100644 --- a/src/plugins/platforms/wayland/qwaylandqtkey.cpp +++ b/src/plugins/platforms/wayland/qwaylandqtkey.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE QWaylandQtKeyExtension::QWaylandQtKeyExtension(QWaylandDisplay *display, uint32_t id) - : QtWayland::qt_key_extension(display->wl_registry(), id) + : QtWayland::qt_key_extension(display->wl_registry(), id, 2) , m_display(display) { } diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index fde5751dc0f..19c3e5d46e5 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) : QPlatformScreen() - , QtWayland::wl_output(waylandDisplay->wl_registry(), id) + , QtWayland::wl_output(waylandDisplay->wl_registry(), id, 2) , mWaylandDisplay(waylandDisplay) , mExtendedOutput(0) , mDepth(32) diff --git a/src/plugins/platforms/wayland/qwaylandtouch.cpp b/src/plugins/platforms/wayland/qwaylandtouch.cpp index 71cc1c3cc98..3dabd1ea504 100644 --- a/src/plugins/platforms/wayland/qwaylandtouch.cpp +++ b/src/plugins/platforms/wayland/qwaylandtouch.cpp @@ -46,7 +46,7 @@ QT_BEGIN_NAMESPACE QWaylandTouchExtension::QWaylandTouchExtension(QWaylandDisplay *display, uint32_t id) - : QtWayland::qt_touch_extension(display->wl_registry(), id), + : QtWayland::qt_touch_extension(display->wl_registry(), id, 1), mDisplay(display), mTouchDevice(0), mPointsLeft(0), diff --git a/src/plugins/platforms/wayland/qwaylandwindowmanagerintegration.cpp b/src/plugins/platforms/wayland/qwaylandwindowmanagerintegration.cpp index c2e0153a55a..174ef93a548 100644 --- a/src/plugins/platforms/wayland/qwaylandwindowmanagerintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindowmanagerintegration.cpp @@ -95,7 +95,7 @@ void QWaylandWindowManagerIntegration::wlHandleListenerGlobal(void *data, wl_reg { Q_UNUSED(version); if (interface == QStringLiteral("qt_windowmanager")) - static_cast(data)->init(registry, id); + static_cast(data)->init(registry, id, 1); } void QWaylandWindowManagerIntegration::windowmanager_hints(int32_t showIsFullScreen) diff --git a/src/plugins/platforms/wayland/qwaylandxdgshell.cpp b/src/plugins/platforms/wayland/qwaylandxdgshell.cpp index eb9f91c435f..8a96a0304b7 100644 --- a/src/plugins/platforms/wayland/qwaylandxdgshell.cpp +++ b/src/plugins/platforms/wayland/qwaylandxdgshell.cpp @@ -57,7 +57,7 @@ QWaylandXdgShell::QWaylandXdgShell(struct ::xdg_shell *shell) } QWaylandXdgShell::QWaylandXdgShell(struct ::wl_registry *registry, uint32_t id) - : QtWayland::xdg_shell(registry, id) + : QtWayland::xdg_shell(registry, id, 1) { use_unstable_version(QtWayland::xdg_shell::version_current); } diff --git a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp index 475b9fec2c4..c99bf2b4815 100644 --- a/src/tools/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/tools/qtwaylandscanner/qtwaylandscanner.cpp @@ -822,13 +822,13 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" class %s %s\n {\n", clientExport.constData(), interfaceName); printf(" public:\n"); - printf(" %s(struct ::wl_registry *registry, int id);\n", interfaceName); + printf(" %s(struct ::wl_registry *registry, int id, int version);\n", interfaceName); printf(" %s(struct ::%s *object);\n", interfaceName, interfaceName); printf(" %s();\n", interfaceName); printf("\n"); printf(" virtual ~%s();\n", interfaceName); printf("\n"); - printf(" void init(struct ::wl_registry *registry, int id);\n"); + printf(" void init(struct ::wl_registry *registry, int id, int version);\n"); printf(" void init(struct ::%s *object);\n", interfaceName); printf("\n"); printf(" struct ::%s *object() { return m_%s; }\n", interfaceName, interfaceName); @@ -908,9 +908,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr bool hasEvents = !interface.events.isEmpty(); - printf(" %s::%s(struct ::wl_registry *registry, int id)\n", interfaceName, interfaceName); + printf(" %s::%s(struct ::wl_registry *registry, int id, int version)\n", interfaceName, interfaceName); printf(" {\n"); - printf(" init(registry, id);\n"); + printf(" init(registry, id, version);\n"); printf(" }\n"); printf("\n"); @@ -933,9 +933,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" }\n"); printf("\n"); - printf(" void %s::init(struct ::wl_registry *registry, int id)\n", interfaceName); + printf(" void %s::init(struct ::wl_registry *registry, int id, int version)\n", interfaceName); printf(" {\n"); - printf(" m_%s = static_cast(wl_registry_bind(registry, id, &%s_interface, %s_interface.version));\n", interfaceName, interfaceName, interfaceName, interfaceName); + printf(" m_%s = static_cast(wl_registry_bind(registry, id, &%s_interface, version));\n", interfaceName, interfaceName, interfaceName); if (hasEvents) printf(" init_listener();\n"); printf(" }\n"); From 5d49d5a224f8bee7edabd73bcac43f7bdb9f0bed Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 22 Aug 2014 12:41:42 +0200 Subject: [PATCH 14/32] Support RasterGLSurface windows In an attempt to make QOpenGLWidget and QQuickWidget working on Wayland. Since Qt 5.3 all widget windows are of type RasterGLSurface (given that the plugin reports this capability which wayland will, with this patch). Such a window can behave either like a raster or an OpenGL window. This concept maps badly to platform plugins that have a rigid separation between raster and OpenGL platform window implementations. From now on, the OpenGL window implementation, that is used pretty much always, except for raw RasterSurface windows, must be prepared to behave like a raster window too, which involves having a backingstore. Change-Id: I0226704b8d5893843fcae68059c5fe9ad2f5e761 Reviewed-by: Robin Burchell --- .../qwaylandclientbufferintegration_p.h | 2 + .../platforms/wayland/qwaylandintegration.cpp | 10 ++-- .../wayland/qwaylandshmbackingstore.cpp | 47 ++++++++++++------- .../wayland/qwaylandshmbackingstore_p.h | 7 ++- .../platforms/wayland/qwaylandshmwindow.cpp | 7 --- .../platforms/wayland/qwaylandshmwindow_p.h | 13 ----- .../platforms/wayland/qwaylandwindow_p.h | 6 +++ 7 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h index 7d79f326330..be594984b56 100644 --- a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h +++ b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h @@ -62,6 +62,8 @@ public: virtual void initialize(QWaylandDisplay *display) = 0; + virtual bool isValid() const { return true; } + virtual bool supportsThreadedOpenGL() const { return false; } virtual QWaylandWindow *createEglWindow(QWindow *window) = 0; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 0c90626964c..3b6d4acf944 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -42,9 +42,9 @@ #include "qwaylandintegration_p.h" #include "qwaylanddisplay_p.h" +#include "qwaylandshmwindow_p.h" #include "qwaylandinputcontext_p.h" #include "qwaylandshmbackingstore_p.h" -#include "qwaylandshmwindow_p.h" #include "qwaylandnativeinterface_p.h" #include "qwaylandclipboard_p.h" #include "qwaylanddnd_p.h" @@ -162,14 +162,18 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co case MultipleWindows: case NonFullScreenWindows: return true; + case RasterGLSurface: + return true; default: return QPlatformIntegration::hasCapability(cap); } } QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const { - if (window->surfaceType() == QWindow::OpenGLSurface && mDisplay->clientBufferIntegration()) + if ((window->surfaceType() == QWindow::OpenGLSurface || window->surfaceType() == QWindow::RasterGLSurface) + && mDisplay->clientBufferIntegration()) return mDisplay->clientBufferIntegration()->createEglWindow(window); + return new QWaylandShmWindow(window); } @@ -255,7 +259,7 @@ QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() if (!mClientBufferIntegrationInitialized) const_cast(this)->initializeClientBufferIntegration(); - return mClientBufferIntegration; + return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration : 0; } QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp index 0677ed0d398..14e1285d37b 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore.cpp @@ -39,14 +39,12 @@ ** ****************************************************************************/ #include "qwaylandshmbackingstore_p.h" - -#include - +#include "qwaylandwindow_p.h" #include "qwaylanddisplay_p.h" -#include "qwaylandshmwindow_p.h" #include "qwaylandscreen_p.h" #include "qwaylanddecoration_p.h" +#include #include #include @@ -156,9 +154,7 @@ QWaylandShmBackingStore::~QWaylandShmBackingStore() QPaintDevice *QWaylandShmBackingStore::paintDevice() { - if (!windowDecoration()) - return mBackBuffer->image(); - return mBackBuffer->imageInsideMargins(windowDecorationMargins()); + return contentSurface(); } void QWaylandShmBackingStore::beginPaint(const QRegion &) @@ -166,13 +162,11 @@ void QWaylandShmBackingStore::beginPaint(const QRegion &) mPainting = true; ensureSize(); - if (waylandWindow()->attached() && mBackBuffer == waylandWindow()->attached() && mFrameCallback) { - QWaylandShmWindow *waylandWindow = static_cast(window()->handle()); - Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); - waylandWindow->waitForFrameSync(); - } + QWaylandWindow *window = waylandWindow(); + if (window->attached() && mBackBuffer == window->attached() && mFrameCallback) + window->waitForFrameSync(); - waylandWindow()->setCanResize(false); + window->setCanResize(false); } void QWaylandShmBackingStore::endPaint() @@ -190,9 +184,15 @@ void QWaylandShmBackingStore::ensureSize() void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { + // Invoked when the window is of type RasterSurface or when the window is + // RasterGLSurface and there are no child widgets requiring OpenGL composition. + + // For the case of RasterGLSurface + having to compose, the composeAndFlush() is + // called instead. The default implementation from QPlatformBackingStore is sufficient + // however so no need to reimplement that. + Q_UNUSED(window); Q_UNUSED(offset); - Q_ASSERT(waylandWindow()->windowType() == QWaylandWindow::Shm); if (windowDecoration() && windowDecoration()->isDirty()) updateDecorations(); @@ -260,6 +260,11 @@ QImage *QWaylandShmBackingStore::entireSurface() const return mBackBuffer->image(); } +QImage *QWaylandShmBackingStore::contentSurface() const +{ + return windowDecoration() ? mBackBuffer->imageInsideMargins(windowDecorationMargins()) : mBackBuffer->image(); +} + void QWaylandShmBackingStore::updateDecorations() { QPainter decorationPainter(entireSurface()); @@ -302,11 +307,19 @@ QMargins QWaylandShmBackingStore::windowDecorationMargins() const return QMargins(); } -QWaylandShmWindow *QWaylandShmBackingStore::waylandWindow() const +QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const { - return static_cast(window()->handle()); + return static_cast(window()->handle()); } +QImage QWaylandShmBackingStore::toImage() const +{ + // Invoked from QPlatformBackingStore::composeAndFlush() that is called + // instead of flush() for widgets that have renderToTexture children + // (QOpenGLWidget, QQuickWidget). + + return *contentSurface(); +} void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time) { @@ -315,7 +328,7 @@ void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t t static_cast(data); if (callback != self->mFrameCallback) // others, like QWaylandWindow, may trigger callbacks too return; - QWaylandShmWindow *window = self->waylandWindow(); + QWaylandWindow *window = self->waylandWindow(); wl_callback_destroy(self->mFrameCallback); self->mFrameCallback = 0; diff --git a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h index 6097b5282c8..33f363f6873 100644 --- a/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmbackingstore_p.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QWaylandDisplay; class QWaylandDecoration; -class QWaylandShmWindow; +class QWaylandWindow; class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer { public: @@ -87,11 +87,14 @@ public: QMargins windowDecorationMargins() const; QImage *entireSurface() const; + QImage *contentSurface() const; void ensureSize(); - QWaylandShmWindow *waylandWindow() const; + QWaylandWindow *waylandWindow() const; void iterateBuffer(); + QImage toImage() const Q_DECL_OVERRIDE; + private: void updateDecorations(); diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp index de87682ce70..431ed2fdb97 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -51,13 +51,11 @@ QT_BEGIN_NAMESPACE QWaylandShmWindow::QWaylandShmWindow(QWindow *window) : QWaylandWindow(window) - , mBackingStore(0) { } QWaylandShmWindow::~QWaylandShmWindow() { - } QWaylandWindow::WindowType QWaylandShmWindow::windowType() const @@ -65,9 +63,4 @@ QWaylandWindow::WindowType QWaylandShmWindow::windowType() const return QWaylandWindow::Shm; } -void QWaylandShmWindow::setBackingStore(QWaylandShmBackingStore *backingStore) -{ - mBackingStore = backingStore; -} - QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow_p.h b/src/plugins/platforms/wayland/qwaylandshmwindow_p.h index 83479f31303..47ee742699d 100644 --- a/src/plugins/platforms/wayland/qwaylandshmwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandshmwindow_p.h @@ -47,8 +47,6 @@ QT_BEGIN_NAMESPACE -class QWaylandShmBackingStore; - class Q_WAYLAND_CLIENT_EXPORT QWaylandShmWindow : public QWaylandWindow { public: @@ -57,19 +55,8 @@ public: WindowType windowType() const; QSurfaceFormat format() const { return QSurfaceFormat(); } - - void setBackingStore(QWaylandShmBackingStore *backingStore); - QWaylandShmBackingStore *backingStore() const; - -private: - QWaylandShmBackingStore *mBackingStore; }; -inline QWaylandShmBackingStore *QWaylandShmWindow::backingStore() const -{ - return mBackingStore; -} - QT_END_NAMESPACE #endif // QWAYLANDSHMWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 9c0be84c6a5..0d0833e54eb 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -63,6 +63,7 @@ class QWaylandSubSurface; class QWaylandDecoration; class QWaylandInputDevice; class QWaylandScreen; +class QWaylandShmBackingStore; class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure { @@ -179,6 +180,9 @@ public: QVariant property(const QString &name); QVariant property(const QString &name, const QVariant &defaultValue); + void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; } + QWaylandShmBackingStore *backingStore() const { return mBackingStore; } + public slots: void requestResize(); @@ -216,6 +220,8 @@ protected: Qt::WindowState mState; + QWaylandShmBackingStore *mBackingStore; + private: bool setWindowStateInternal(Qt::WindowState flags); void setGeometry_helper(const QRect &rect); From 2f329b4696ba06b5ac3dd1445cc5f0973ab2ccb2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 23 Aug 2014 15:12:24 +0200 Subject: [PATCH 15/32] Indicate from the client buffer integration if decorations are supported Custom client buffer integrations may not care about window decorations. Setting QT_WAYLAND_DISABLE_WINDOWDECORATION is tedious and error-prone. And it cannot be omitted since things like input events will be off if the common client code thinks decorations are in use but the client buffer integration does not render them at all. Therefore add a supportsWindowDecoration() virtual in addition to the environment variable. Change-Id: If8f621182d5c230f4d8d679c050f5d27aed6c2fb Reviewed-by: Giulio Camuffo --- .../hardwareintegration/qwaylandclientbufferintegration_p.h | 1 + src/plugins/platforms/wayland/qwaylandwindow.cpp | 5 ++++- tests/auto/wayland/tst_client.cpp | 5 +++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h index be594984b56..bbe42eb261f 100644 --- a/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h +++ b/src/plugins/platforms/wayland/hardwareintegration/qwaylandclientbufferintegration_p.h @@ -65,6 +65,7 @@ public: virtual bool isValid() const { return true; } virtual bool supportsThreadedOpenGL() const { return false; } + virtual bool supportsWindowDecoration() const { return false; } virtual QWaylandWindow *createEglWindow(QWindow *window) = 0; virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0; diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 8679463ec6b..fb3095d4b51 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -52,6 +52,7 @@ #include "qwaylanddecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" +#include "qwaylandclientbufferintegration_p.h" #include #include @@ -482,7 +483,9 @@ bool QWaylandWindow::createDecoration() } } - static bool disableWaylandDecorations = !qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").isEmpty(); + static bool disableWaylandDecorations = !qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").isEmpty() + || (mDisplay->clientBufferIntegration() && !mDisplay->clientBufferIntegration()->supportsWindowDecoration()); + if (disableWaylandDecorations) return false; diff --git a/tests/auto/wayland/tst_client.cpp b/tests/auto/wayland/tst_client.cpp index e13d738dc34..113f9d9a850 100644 --- a/tests/auto/wayland/tst_client.cpp +++ b/tests/auto/wayland/tst_client.cpp @@ -248,6 +248,11 @@ int main(int argc, char **argv) setenv("XDG_RUNTIME_DIR", ".", 1); setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin + // wayland-egl hangs in the test setup when we try to initialize. Until it gets + // figured out, avoid clientBufferIntegration() from being called in + // QWaylandWindow::createDecorations(). + setenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1", 1); + MockCompositor compositor; compositor.setOutputGeometry(QRect(QPoint(), screenSize)); From 6a0d904dda41ac6e78e6ec7dc2093669c1897da4 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 29 Aug 2014 20:43:20 +0200 Subject: [PATCH 16/32] Fix touch with Weston Work around the missing touch_frame after the last touch_up. Task-number: QTBUG-36602 Change-Id: Iccb03bdc8b430c7cefc097c3c84e50be676c7fe7 Reviewed-by: Robin Burchell Reviewed-by: Shawn Rutledge --- .../platforms/wayland/qwaylandinputdevice.cpp | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 6c132010268..4a100f79a43 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -220,6 +220,8 @@ public: void touch_frame() Q_DECL_OVERRIDE; void touch_cancel() Q_DECL_OVERRIDE; + bool allTouchPointsReleased(); + QWaylandInputDevice *mParent; QWaylandWindow *mFocus; QList mTouchPoints; @@ -863,6 +865,13 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_ Q_UNUSED(time); mFocus = 0; mParent->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased); + + // As of Weston 1.5.90 there is no touch_frame after the last touch_up + // (i.e. when the last finger is released). To accommodate for this, issue a + // touch_frame. This cannot hurt since it is safe to call the touch_frame + // handler multiple times when there are no points left. + if (allTouchPointsReleased()) + touch_frame(); } void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y) @@ -921,6 +930,15 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch mTouch->mTouchPoints.append(tp); } +bool QWaylandInputDevice::Touch::allTouchPointsReleased() +{ + for (int i = 0; i < mTouchPoints.count(); ++i) + if (mTouchPoints.at(i).state != Qt::TouchPointReleased) + return false; + + return true; +} + void QWaylandInputDevice::Touch::touch_frame() { // Copy all points, that are in the previous but not in the current list, as stationary. @@ -950,13 +968,7 @@ void QWaylandInputDevice::Touch::touch_frame() QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints); - bool allReleased = true; - for (int i = 0; i < mTouchPoints.count(); ++i) - if (mTouchPoints.at(i).state != Qt::TouchPointReleased) { - allReleased = false; - break; - } - + const bool allReleased = allTouchPointsReleased(); mPrevTouchPoints = mTouchPoints; mTouchPoints.clear(); From c15ee9f0e3549448a19eeb54d5b6c6ae1a9127fa Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 1 Sep 2014 15:30:42 +0200 Subject: [PATCH 17/32] Wayland: correct touch location The window margins were offsetting the touch point in the wrong direction. Task-number: QTBUG-36602 Change-Id: Id8b31d2de4051f36d3ff4e088bbc9bd7cc84ca13 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 4a100f79a43..014303f76fa 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -921,7 +921,7 @@ void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::Touch tp.area = QRectF(0, 0, 8, 8); QMargins margins = win->frameMargins(); - tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x+margins.left(), y+margins.top()))); + tp.area.moveCenter(win->window()->mapToGlobal(QPoint(x - margins.left(), y - margins.top()))); } tp.state = state; From 76c98e7671856bc2e919b4dadf358c2ec2192321 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 1 Sep 2014 17:04:09 +0200 Subject: [PATCH 18/32] Wayland: can drag a window by its titlebar using the touchscreen It was already possible to drag it via the mouse but not via touch. Task-number: QTBUG-41085 Change-Id: Ia52c7124fb2f1aa0331897bd072fcf09fb78aa1a Reviewed-by: Laszlo Agocs --- .../platforms/wayland/qwaylanddecoration.cpp | 13 +++++++++++++ .../platforms/wayland/qwaylanddecoration_p.h | 1 + .../platforms/wayland/qwaylandinputdevice.cpp | 10 ++++++++-- src/plugins/platforms/wayland/qwaylandwindow.cpp | 7 +++++++ src/plugins/platforms/wayland/qwaylandwindow_p.h | 3 +++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/qwaylanddecoration.cpp index b288debe9eb..c9ab23c001b 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylanddecoration.cpp @@ -335,6 +335,19 @@ bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPo return true; } +bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +{ + Q_UNUSED(inputDevice); + Q_UNUSED(global); + Q_UNUSED(mods); + + if (state == Qt::TouchPointPressed && local.y() <= m_margins.top()) { + m_wayland_window->shellSurface()->move(inputDevice); + return true; + } + return false; +} + bool QWaylandDecoration::inMouseButtonPressedState() const { return m_mouseButtons & Qt::NoButton; diff --git a/src/plugins/platforms/wayland/qwaylanddecoration_p.h b/src/plugins/platforms/wayland/qwaylanddecoration_p.h index 14bf4a92d68..c240b9c9d45 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration_p.h +++ b/src/plugins/platforms/wayland/qwaylanddecoration_p.h @@ -75,6 +75,7 @@ public: bool isDirty() const; bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods); + bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods); bool inMouseButtonPressedState() const; void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 014303f76fa..5be76d90e19 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -853,8 +853,8 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t serial, wl_fixed_t x, wl_fixed_t y) { - Q_UNUSED(serial); - Q_UNUSED(time); + mParent->mTime = time; + mParent->mSerial = serial; mFocus = QWaylandWindow::fromWlSurface(surface); mParent->handleTouchPoint(id, wl_fixed_to_double(x), wl_fixed_to_double(y), Qt::TouchPointPressed); } @@ -966,6 +966,12 @@ void QWaylandInputDevice::Touch::touch_frame() QWindow *window = mFocus ? mFocus->window() : 0; + if (mFocus) { + const QWindowSystemInterface::TouchPoint &tp = mTouchPoints.last(); + QPointF localPos(window->mapFromGlobal(tp.area.center().toPoint())); + if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers())) + return; + } QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints); const bool allReleased = allTouchPointsReleased(); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index fb3095d4b51..278825e83c7 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -583,6 +583,13 @@ void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice) restoreMouseCursor(inputDevice); } +bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +{ + if (!mWindowDecoration) + return false; + return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods); +} + void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { if (mWindowDecoration->handleMouse(inputDevice,local,global,b,mods)) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index 0d0833e54eb..db0b59458bf 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -156,6 +156,9 @@ public: void handleMouseEnter(QWaylandInputDevice *inputDevice); void handleMouseLeave(QWaylandInputDevice *inputDevice); + bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, + Qt::TouchPointState state, Qt::KeyboardModifiers mods); + bool createDecoration(); inline bool isMaximized() const { return mState == Qt::WindowMaximized; } From 45fdcd48184733e39703e72a25a9f4ff6ca211c0 Mon Sep 17 00:00:00 2001 From: Li Qiu Date: Tue, 2 Sep 2014 17:25:39 +0300 Subject: [PATCH 19/32] Fix crash of test client No wl_data_device_manager created in Mock compositor Change-Id: If80f71165c28678f296bc18f0fea572dcb1a2f77 Reviewed-by: Giulio Camuffo --- tests/auto/wayland/mockcompositor.cpp | 2 ++ tests/auto/wayland/mockcompositor.h | 2 ++ tests/auto/wayland/mockinput.cpp | 31 +++++++++++++++++++++++++++ tests/auto/wayland/mockinput.h | 25 +++++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/tests/auto/wayland/mockcompositor.cpp b/tests/auto/wayland/mockcompositor.cpp index 70fa5f23265..cb0e6576e90 100644 --- a/tests/auto/wayland/mockcompositor.cpp +++ b/tests/auto/wayland/mockcompositor.cpp @@ -209,6 +209,8 @@ Compositor::Compositor() wl_display_add_global(m_display, &wl_compositor_interface, this, bindCompositor); + m_data_device_manager.reset(new DataDeviceManager(this, m_display)); + wl_display_init_shm(m_display); m_seat.reset(new Seat(this, m_display)); diff --git a/tests/auto/wayland/mockcompositor.h b/tests/auto/wayland/mockcompositor.h index 7f3e2268312..03d3a96a354 100644 --- a/tests/auto/wayland/mockcompositor.h +++ b/tests/auto/wayland/mockcompositor.h @@ -61,6 +61,7 @@ typedef void (**Implementation)(void); class Keyboard; class Pointer; class Seat; +class DataDeviceManager; class Surface; class Compositor @@ -111,6 +112,7 @@ private: QScopedPointer m_seat; Pointer *m_pointer; Keyboard *m_keyboard; + QScopedPointer m_data_device_manager; QVector m_surfaces; }; diff --git a/tests/auto/wayland/mockinput.cpp b/tests/auto/wayland/mockinput.cpp index bd85ad6c897..fbe44de41cd 100644 --- a/tests/auto/wayland/mockinput.cpp +++ b/tests/auto/wayland/mockinput.cpp @@ -227,4 +227,35 @@ void Pointer::pointer_destroy_resource(wl_pointer::Resource *resource) m_focusResource = 0; } +DataDevice::DataDevice(Compositor *compositor) + : wl_data_device() + , m_compositor(compositor) +{ + +} + +DataDevice::~DataDevice() +{ + +} + +DataDeviceManager::DataDeviceManager(Compositor *compositor, wl_display *display) + : wl_data_device_manager(display) + , m_compositor(compositor) +{ + +} + +DataDeviceManager::~DataDeviceManager() +{ + +} + +void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) +{ + if (!m_data_device) + m_data_device.reset(new DataDevice(m_compositor)); + m_data_device->add(resource->client(), id); +} + } diff --git a/tests/auto/wayland/mockinput.h b/tests/auto/wayland/mockinput.h index 128758cad93..16b19b4fb2a 100644 --- a/tests/auto/wayland/mockinput.h +++ b/tests/auto/wayland/mockinput.h @@ -120,6 +120,31 @@ private: Surface *m_focus; }; +class DataDevice : public QtWaylandServer::wl_data_device +{ +public: + DataDevice(Compositor *compositor); + ~DataDevice(); + +private: + Compositor *m_compositor; +}; + +class DataDeviceManager : public QtWaylandServer::wl_data_device_manager +{ +public: + DataDeviceManager(Compositor *compositor, struct ::wl_display *display); + ~DataDeviceManager(); + +protected: + void data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) Q_DECL_OVERRIDE; + +private: + Compositor *m_compositor; + + QScopedPointer m_data_device; +}; + } #endif // MOCKINPUT_H From 421b3bb9e12155dde993aa424f04b0d12a8db005 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Wed, 3 Sep 2014 23:16:27 +0300 Subject: [PATCH 20/32] Destroy the QScreen when its wl_output is removed Change-Id: I4532d05cca44c88fe38c14eacbe90c190f272b2c Reviewed-by: Robin Burchell Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 12 +++++++++++- src/plugins/platforms/wayland/qwaylanddisplay_p.h | 4 ++-- .../platforms/wayland/qwaylandintegration.cpp | 3 ++- src/plugins/platforms/wayland/qwaylandscreen.cpp | 1 + src/plugins/platforms/wayland/qwaylandscreen_p.h | 2 ++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 595d2ce77ee..a037bb9627b 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -262,7 +262,17 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin void QWaylandDisplay::registry_global_remove(uint32_t id) { for (int i = 0, ie = mGlobals.count(); i != ie; ++i) { - if (mGlobals[i].id == id) { + RegistryGlobal &global = mGlobals[i]; + if (global.id == id) { + if (global.interface == QStringLiteral("wl_output")) { + foreach (QWaylandScreen *screen, mScreens) { + if (screen->outputId() == id) { + delete screen; + mScreens.removeOne(screen); + break; + } + } + } mGlobals.removeAt(i); break; } diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 6ed30d195a4..64c020546b7 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -97,7 +97,7 @@ public: QWaylandDisplay(QWaylandIntegration *waylandIntegration); ~QWaylandDisplay(void); - QList screens() const { return mScreens; } + QList screens() const { return mScreens; } QWaylandScreen *screenForOutput(struct wl_output *output) const; @@ -176,7 +176,7 @@ private: QWaylandEventThread *mEventThreadObject; QScopedPointer mShell; QScopedPointer mShellXdg; - QList mScreens; + QList mScreens; QList mInputDevices; QList mRegistryListeners; QWaylandIntegration *mWaylandIntegration; diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 3b6d4acf944..224466cc44c 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -49,6 +49,7 @@ #include "qwaylandclipboard_p.h" #include "qwaylanddnd_p.h" #include "qwaylandwindowmanagerintegration_p.h" +#include "qwaylandscreen_p.h" #include "QtPlatformSupport/private/qgenericunixfontdatabase_p.h" #include @@ -127,7 +128,7 @@ QWaylandIntegration::QWaylandIntegration() mClipboard = new QWaylandClipboard(mDisplay); mDrag = new QWaylandDrag(mDisplay); - foreach (QPlatformScreen *screen, mDisplay->screens()) + foreach (QWaylandScreen *screen, mDisplay->screens()) screenAdded(screen); mInputContext.reset(new QWaylandInputContext(mDisplay)); diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 19c3e5d46e5..2cc719776ea 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -56,6 +56,7 @@ QT_BEGIN_NAMESPACE QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) : QPlatformScreen() , QtWayland::wl_output(waylandDisplay->wl_registry(), id, 2) + , m_outputId(id) , mWaylandDisplay(waylandDisplay) , mExtendedOutput(0) , mDepth(32) diff --git a/src/plugins/platforms/wayland/qwaylandscreen_p.h b/src/plugins/platforms/wayland/qwaylandscreen_p.h index 5d06227a5d3..90b8fc903ee 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen_p.h +++ b/src/plugins/platforms/wayland/qwaylandscreen_p.h @@ -77,6 +77,7 @@ public: QPlatformCursor *cursor() const; QWaylandCursor *waylandCursor() const { return mWaylandCursor; }; + uint32_t outputId() const { return m_outputId; } ::wl_output *output() { return object(); } QWaylandExtendedOutput *extendedOutput() const; @@ -93,6 +94,7 @@ private: const QString &model, int32_t transform) Q_DECL_OVERRIDE; + int m_outputId; QWaylandDisplay *mWaylandDisplay; QWaylandExtendedOutput *mExtendedOutput; QRect mGeometry; From 03e95c8b8c6594f0d37f8a00324504e5eda07e7b Mon Sep 17 00:00:00 2001 From: Li Qiu Date: Wed, 27 Aug 2014 18:24:52 +0300 Subject: [PATCH 21/32] DataOffer not invalidated when client loses keyboard focus The data_offer object should be invalidated when client loses keyboard focus. Otherwise in following scenario, it will become zombie object: start app1 -> copy text -> start app2 -> paste text -> close app1 -> paste again in app2 -> seg fault in qtwayland. The root cause is that when app2 takes focus the first time, data_device.data_offer event was sent to it from DataDevice::setFocus. When app1 is closed, the data source reference in data offer becomes invalid. so when trying to paste again in app2, segmentation faults Change-Id: I16a584e80fddaadd269b00cdf39eb405dd95b622 Task-number: QTBUG-41005 Reviewed-by: Giulio Camuffo --- src/plugins/platforms/wayland/qwaylanddatadevice.cpp | 5 +++++ src/plugins/platforms/wayland/qwaylanddatadevice_p.h | 1 + src/plugins/platforms/wayland/qwaylandinputdevice.cpp | 5 +++++ src/plugins/platforms/wayland/qwaylandwindow.cpp | 9 +++++++++ src/plugins/platforms/wayland/qwaylandwindow_p.h | 1 + 5 files changed, 21 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylanddatadevice.cpp b/src/plugins/platforms/wayland/qwaylanddatadevice.cpp index 8f690aae0fc..74f879f972d 100644 --- a/src/plugins/platforms/wayland/qwaylanddatadevice.cpp +++ b/src/plugins/platforms/wayland/qwaylanddatadevice.cpp @@ -77,6 +77,11 @@ QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const return m_selectionOffer.data(); } +void QWaylandDataDevice::invalidateSelectionOffer() +{ + m_selectionOffer.reset(); +} + QWaylandDataSource *QWaylandDataDevice::selectionSource() const { return m_selectionSource.data(); diff --git a/src/plugins/platforms/wayland/qwaylanddatadevice_p.h b/src/plugins/platforms/wayland/qwaylanddatadevice_p.h index f5fad17723f..dae91290ebf 100644 --- a/src/plugins/platforms/wayland/qwaylanddatadevice_p.h +++ b/src/plugins/platforms/wayland/qwaylanddatadevice_p.h @@ -65,6 +65,7 @@ public: ~QWaylandDataDevice(); QWaylandDataOffer *selectionOffer() const; + void invalidateSelectionOffer(); QWaylandDataSource *selectionSource() const; void setSelectionSource(QWaylandDataSource *source); diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 5be76d90e19..c04067688d9 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -717,6 +717,11 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf Q_UNUSED(time); Q_UNUSED(surface); + if (surface) { + QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); + window->unfocus(); + } + mFocus = NULL; // Use a callback to set the focus because we may get a leave/enter pair, and diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 278825e83c7..0905cb3a224 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -42,6 +42,7 @@ #include "qwaylandwindow_p.h" #include "qwaylandbuffer_p.h" +#include "qwaylanddatadevice_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandinputdevice_p.h" #include "qwaylandscreen_p.h" @@ -642,6 +643,14 @@ void QWaylandWindow::requestActivateWindow() // we rely on compositor setting keyboard focus based on window stacking. } +void QWaylandWindow::unfocus() +{ + QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice(); + if (inputDevice && inputDevice->dataDevice()) { + inputDevice->dataDevice()->invalidateSelectionOffer(); + } +} + bool QWaylandWindow::isExposed() const { if (mShellSurface) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index db0b59458bf..a69af9c0e40 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -142,6 +142,7 @@ public: void requestActivateWindow() Q_DECL_OVERRIDE; bool isExposed() const Q_DECL_OVERRIDE; + void unfocus(); QWaylandDecoration *decoration() const; void setDecoration(QWaylandDecoration *decoration); From 4ca2fc4d1b7b6dd7be7b6c46fe36d7b9efc2b49b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 5 Sep 2014 17:01:56 +0200 Subject: [PATCH 22/32] Avoid unused parameter Change-Id: Icfc7e4e2d6cd030fc0509ad4724b577f88c4e850 Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylandshellsurface.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/platforms/wayland/qwaylandshellsurface.cpp b/src/plugins/platforms/wayland/qwaylandshellsurface.cpp index d68ae1b5d16..a3855dac0d6 100644 --- a/src/plugins/platforms/wayland/qwaylandshellsurface.cpp +++ b/src/plugins/platforms/wayland/qwaylandshellsurface.cpp @@ -50,6 +50,7 @@ QWaylandShellSurface::QWaylandShellSurface(QWaylandWindow *window) void QWaylandShellSurface::setWindowFlags(Qt::WindowFlags flags) { + Q_UNUSED(flags); } void QWaylandShellSurface::sendProperty(const QString &name, const QVariant &value) From 1bb22c40a341253fdd9c3468aa20a9496fbc9589 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sat, 6 Sep 2014 17:15:00 +0300 Subject: [PATCH 23/32] Advertise new screens created after startup Change-Id: I995f49e52ec888830b478f1e1f9cc82132776725 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 4 +++- src/plugins/platforms/wayland/qwaylandintegration.cpp | 3 --- src/plugins/platforms/wayland/qwaylandintegration_p.h | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index a037bb9627b..264528f6caf 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -215,9 +215,11 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin struct ::wl_registry *registry = object(); if (interface == QStringLiteral("wl_output")) { - mScreens.append(new QWaylandScreen(this, id)); + QWaylandScreen *screen = new QWaylandScreen(this, id); + mScreens.append(screen); // We need to get the output events before creating surfaces forceRoundTrip(); + mWaylandIntegration->screenAdded(screen); } else if (interface == QStringLiteral("wl_compositor")) { mCompositor.init(registry, id, 3); } else if (interface == QStringLiteral("wl_shm")) { diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 224466cc44c..d9bf82e4f98 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -128,9 +128,6 @@ QWaylandIntegration::QWaylandIntegration() mClipboard = new QWaylandClipboard(mDisplay); mDrag = new QWaylandDrag(mDisplay); - foreach (QWaylandScreen *screen, mDisplay->screens()) - screenAdded(screen); - mInputContext.reset(new QWaylandInputContext(mDisplay)); } diff --git a/src/plugins/platforms/wayland/qwaylandintegration_p.h b/src/plugins/platforms/wayland/qwaylandintegration_p.h index 025e0b4df61..bbe98285389 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration_p.h +++ b/src/plugins/platforms/wayland/qwaylandintegration_p.h @@ -110,6 +110,8 @@ private: bool mClientBufferIntegrationInitialized; bool mServerBufferIntegrationInitialized; bool mShellIntegrationInitialized; + + friend class QWaylandDisplay; }; QT_END_NAMESPACE From c1ed1596535c4c1592ecafd9adfe1acae67d83a9 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 5 Sep 2014 13:46:56 +0200 Subject: [PATCH 24/32] Fix window decorations for GL apps You cannot have rounded corners with an alpha-less config. To make OpenGL applications appearing with the correct decoration, alpha must be enabled. With this fix the OpenGL apps' decoration will now look identical to the SHM apps'. Change-Id: I24431ddab63146f7f697c85277f00f41e5c55e85 Reviewed-by: Shawn Rutledge Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylanddisplay.cpp | 13 +++++++++++++ src/plugins/platforms/wayland/qwaylanddisplay_p.h | 2 ++ src/plugins/platforms/wayland/qwaylandwindow.cpp | 6 +----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 264528f6caf..3eac985f6ed 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -56,6 +56,7 @@ #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandshellintegration_p.h" +#include "qwaylandclientbufferintegration_p.h" #include "qwaylandextendedoutput_p.h" #include "qwaylandextendedsurface_p.h" @@ -335,4 +336,16 @@ QtWayland::xdg_shell *QWaylandDisplay::shellXdg() return mShellXdg.data(); } +bool QWaylandDisplay::supportsWindowDecoration() const +{ + static bool disabled = qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").toInt(); + // Stop early when disabled via the environment. Do not try to load the integration in + // order to play nice with SHM-only, buffer integration-less systems. + if (disabled) + return false; + + static bool integrationSupport = clientBufferIntegration() && clientBufferIntegration()->supportsWindowDecoration(); + return integrationSupport; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index 64c020546b7..b0142004e8b 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -156,6 +156,8 @@ public: void forceRoundTrip(); + bool supportsWindowDecoration() const; + public slots: void blockingReadEvents(); void flushRequests(); diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp index 0905cb3a224..aaef58d997a 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow.cpp +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -53,7 +53,6 @@ #include "qwaylanddecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" -#include "qwaylandclientbufferintegration_p.h" #include #include @@ -484,10 +483,7 @@ bool QWaylandWindow::createDecoration() } } - static bool disableWaylandDecorations = !qgetenv("QT_WAYLAND_DISABLE_WINDOWDECORATION").isEmpty() - || (mDisplay->clientBufferIntegration() && !mDisplay->clientBufferIntegration()->supportsWindowDecoration()); - - if (disableWaylandDecorations) + if (!mDisplay->supportsWindowDecoration()) return false; bool decoration = false; From 0fdbe40ad4b38b313c1f1587ee63c5b7669f096e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 6 Sep 2014 21:44:18 +0200 Subject: [PATCH 25/32] Allow activating decoration buttons with touch Task-number: QTBUG-41142 Change-Id: Ifad600d375d3b5ba197c384ece54a93db9aa0d2d Reviewed-by: Giulio Camuffo --- .../platforms/wayland/qwaylanddecoration.cpp | 19 ++++++++++++++----- .../platforms/wayland/qwaylandinputdevice.cpp | 6 +++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddecoration.cpp b/src/plugins/platforms/wayland/qwaylanddecoration.cpp index c9ab23c001b..ed4978725a4 100644 --- a/src/plugins/platforms/wayland/qwaylanddecoration.cpp +++ b/src/plugins/platforms/wayland/qwaylanddecoration.cpp @@ -340,12 +340,21 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo Q_UNUSED(inputDevice); Q_UNUSED(global); Q_UNUSED(mods); - - if (state == Qt::TouchPointPressed && local.y() <= m_margins.top()) { - m_wayland_window->shellSurface()->move(inputDevice); - return true; + bool handled = state == Qt::TouchPointPressed; + if (handled) { + if (closeButtonRect().contains(local)) + QWindowSystemInterface::handleCloseEvent(m_window); + else if (maximizeButtonRect().contains(local)) + m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + else if (minimizeButtonRect().contains(local)) + m_window->setWindowState(Qt::WindowMinimized); + else if (local.y() <= m_margins.top()) + m_wayland_window->shellSurface()->move(inputDevice); + else + handled = false; } - return false; + + return handled; } bool QWaylandDecoration::inMouseButtonPressedState() const diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index c04067688d9..9e3fbabb12f 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -973,7 +973,11 @@ void QWaylandInputDevice::Touch::touch_frame() if (mFocus) { const QWindowSystemInterface::TouchPoint &tp = mTouchPoints.last(); - QPointF localPos(window->mapFromGlobal(tp.area.center().toPoint())); + // When the touch event is received, the global pos is calculated with the margins + // in mind. Now we need to adjust again to get the correct local pos back. + QMargins margins = window->frameMargins(); + QPoint p = tp.area.center().toPoint(); + QPointF localPos(window->mapFromGlobal(QPoint(p.x() + margins.left(), p.y() + margins.top()))); if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers())) return; } From 767cc05e57e4e2ed5a89319a6f605449c4725479 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 6 Sep 2014 21:28:01 +0200 Subject: [PATCH 26/32] Avoid useless handleTouchEvent call The call when allReleased is true is a historical artifact: Originally the call was necessary to generate a TouchEnd. Later the determination of the event type got moved to QWindowSystemInterface. As a result the call is completely superfluous since it will bail out immediately. Task-number: QTBUG-36473 Change-Id: If1a270445a620e6f795912873c60fb1a05384964 Reviewed-by: Shawn Rutledge --- .../platforms/wayland/qwaylandinputdevice.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 9e3fbabb12f..5198a9e31ea 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -983,14 +983,12 @@ void QWaylandInputDevice::Touch::touch_frame() } QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints); - const bool allReleased = allTouchPointsReleased(); - mPrevTouchPoints = mTouchPoints; - mTouchPoints.clear(); - - if (allReleased) { - QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mTouchPoints); + if (allTouchPointsReleased()) mPrevTouchPoints.clear(); - } + else + mPrevTouchPoints = mTouchPoints; + + mTouchPoints.clear(); } QT_END_NAMESPACE From f58e56ccf900674f6f6b7945c70a6506ecc80b14 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 6 Sep 2014 21:51:46 +0200 Subject: [PATCH 27/32] Silence warnings about keyboard grab and size hint propagation These two unimplemented functions often result in showing warnings from the default implementations. This is not quite ideal since the warning is useless for users and pollutes the standard output (which f.ex. Creator captures as-is) Change-Id: Ic05ff1590ed351738f0390a94ed5203a05664d4a Reviewed-by: Shawn Rutledge --- src/plugins/platforms/wayland/qwaylandwindow_p.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/wayland/qwaylandwindow_p.h b/src/plugins/platforms/wayland/qwaylandwindow_p.h index a69af9c0e40..dbb0af2e0aa 100644 --- a/src/plugins/platforms/wayland/qwaylandwindow_p.h +++ b/src/plugins/platforms/wayland/qwaylandwindow_p.h @@ -187,6 +187,9 @@ public: void setBackingStore(QWaylandShmBackingStore *backingStore) { mBackingStore = backingStore; } QWaylandShmBackingStore *backingStore() const { return mBackingStore; } + bool setKeyboardGrabEnabled(bool) Q_DECL_OVERRIDE { return false; } + void propagateSizeHints() Q_DECL_OVERRIDE { } + public slots: void requestResize(); From c9dbc3d97dd6e36c1b71a1516bde57927b9c30a0 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Sat, 6 Sep 2014 00:26:20 +0300 Subject: [PATCH 28/32] Fix QWaylandScreen geometry and physical size The wl_output.geometry event carries the physical size of the output, not the logical one. This happened to work only because the geometry event was sent before the mode event, which carries the logical size. Moreover, use the done event to send only one geometry change event instead of one per advertized mode. Change-Id: I5b09d56654aac149d90692bb5a3e050cc0d60cb6 Reviewed-by: Laszlo Agocs --- .../platforms/wayland/qwaylandscreen.cpp | 28 +++++++++++-------- .../platforms/wayland/qwaylandscreen_p.h | 3 ++ 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 2cc719776ea..6213da87f4e 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -95,6 +95,11 @@ QImage::Format QWaylandScreen::format() const return mFormat; } +QSizeF QWaylandScreen::physicalSize() const +{ + return mPhysicalSize; +} + QDpi QWaylandScreen::logicalDpi() const { static int force_dpi = !qgetenv("QT_WAYLAND_FORCE_DPI").isEmpty() ? qgetenv("QT_WAYLAND_FORCE_DPI").toInt() : -1; @@ -153,16 +158,11 @@ void QWaylandScreen::output_mode(uint32_t flags, int width, int height, int refr QSize size(width, height); - if (size != mGeometry.size()) { + if (size != mGeometry.size()) mGeometry.setSize(size); - QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry); - QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry); - } - if (refresh != mRefreshRate) { + if (refresh != mRefreshRate) mRefreshRate = refresh; - QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate()); - } } void QWaylandScreen::output_geometry(int32_t x, int32_t y, @@ -202,14 +202,18 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y, if (!model.isEmpty()) mOutputName = model; - QRect geom(x, y, width, height); + mPhysicalSize = QSize(width, height); + mGeometry.moveTopLeft(QPoint(x, y)); +} - if (mGeometry == geom) - return; - - mGeometry = geom; +void QWaylandScreen::output_done() +{ + // the done event is sent after all the geometry and the mode events are sent, + // and the last mode event to be sent is the active one, so we can trust the + // values of mGeometry and mRefreshRate here QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry); QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry); + QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate()); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandscreen_p.h b/src/plugins/platforms/wayland/qwaylandscreen_p.h index 90b8fc903ee..866ac26ea2c 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen_p.h +++ b/src/plugins/platforms/wayland/qwaylandscreen_p.h @@ -65,6 +65,8 @@ public: int depth() const; QImage::Format format() const; + QSizeF physicalSize() const Q_DECL_OVERRIDE; + QDpi logicalDpi() const Q_DECL_OVERRIDE; void setOrientationUpdateMask(Qt::ScreenOrientations mask); @@ -93,6 +95,7 @@ private: const QString &make, const QString &model, int32_t transform) Q_DECL_OVERRIDE; + void output_done() Q_DECL_OVERRIDE; int m_outputId; QWaylandDisplay *mWaylandDisplay; From 3d6c98cc58b2db499388351b003d508626ae6e92 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Mon, 15 Sep 2014 10:36:14 +0300 Subject: [PATCH 29/32] The QWindowSystemInterface API changed, make it build again Change-Id: Ic00a820ebac7727a8d71d62ce191fe29de52aac0 Reviewed-by: Robin Burchell --- src/plugins/platforms/wayland/qwaylandscreen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 6213da87f4e..9c34baeed50 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -211,8 +211,7 @@ void QWaylandScreen::output_done() // the done event is sent after all the geometry and the mode events are sent, // and the last mode event to be sent is the active one, so we can trust the // values of mGeometry and mRefreshRate here - QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry); - QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), mGeometry); + QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry, mGeometry); QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate()); } From b9f7e26a49885fc8d9907273978ce6792e12abfd Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 12 Sep 2014 22:19:45 +0300 Subject: [PATCH 30/32] Don't give bogus values for a screen physical size If we don't have a valid physical size for a screen, i.e. (0x0), return the default value from the base class. Change-Id: Ia7b6f90ee73e07014ab752ceb165426812c49415 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylandscreen.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 9c34baeed50..943e29a05c1 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -97,7 +97,10 @@ QImage::Format QWaylandScreen::format() const QSizeF QWaylandScreen::physicalSize() const { - return mPhysicalSize; + if (mPhysicalSize.isNull()) + return QPlatformScreen::physicalSize(); + else + return mPhysicalSize; } QDpi QWaylandScreen::logicalDpi() const From 1aeeab6e336e07118c87c497130aba9a0bb47d8c Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Fri, 12 Sep 2014 13:44:42 +0300 Subject: [PATCH 31/32] Fix retrieving the selection/dnd data Installing a roudtrip on the custom event queue in the wl_data_offer.offer handler is broken because that triggers a wl_data_device.selection event, which emits the QClipboard changed signal, so code listening to it may end up trying to retrieve the clipboard data before the roundtrip ends. Additionally, we're calling wl_data_offer.receive for each mime type, even if then we never read from the fd, making the source client do work for no reason. Instead, call wl_data_offer.receive retrieveData_sys, that is when actually retreiving the data. We don't need to install a roundtrip after that, just flushing out the requests is enough, because we wait up to one second for the source client to write into the fd. Change-Id: I180779e375ebd5a22af7084458505a41107fab19 Reviewed-by: Robin Burchell --- .../platforms/wayland/qwaylanddataoffer.cpp | 34 +++++++++---------- .../platforms/wayland/qwaylanddataoffer_p.h | 2 +- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylanddataoffer.cpp b/src/plugins/platforms/wayland/qwaylanddataoffer.cpp index d1c85c7a40e..4ad73dc7e77 100644 --- a/src/plugins/platforms/wayland/qwaylanddataoffer.cpp +++ b/src/plugins/platforms/wayland/qwaylanddataoffer.cpp @@ -94,30 +94,18 @@ QWaylandMimeData::~QWaylandMimeData() void QWaylandMimeData::appendFormat(const QString &mimeType) { - if (m_types.contains(mimeType)) - close(m_types.take(mimeType)); // Unconsumed data + m_types << mimeType; m_data.remove(mimeType); // Clear previous contents - - int pipefd[2]; - if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) { - qWarning("QWaylandMimeData: pipe2() failed"); - return; - } - - m_dataOffer->receive(mimeType, pipefd[1]); - m_display->forceRoundTrip(); - close(pipefd[1]); - m_types.insert(mimeType, pipefd[0]); } bool QWaylandMimeData::hasFormat_sys(const QString &mimeType) const { - return m_types.contains(mimeType) || m_data.contains(mimeType); + return m_types.contains(mimeType); } QStringList QWaylandMimeData::formats_sys() const { - return m_types.keys() << m_data.keys(); + return m_types; } QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::Type type) const @@ -130,14 +118,24 @@ QVariant QWaylandMimeData::retrieveData_sys(const QString &mimeType, QVariant::T if (!m_types.contains(mimeType)) return QVariant(); + int pipefd[2]; + if (::pipe2(pipefd, O_CLOEXEC|O_NONBLOCK) == -1) { + qWarning("QWaylandMimeData: pipe2() failed"); + return QVariant(); + } + + m_dataOffer->receive(mimeType, pipefd[1]); + m_display->flushRequests(); + + close(pipefd[1]); + QByteArray content; - int fd = m_types.take(mimeType); - if (readData(fd, content) != 0) { + if (readData(pipefd[0], content) != 0) { qWarning("QWaylandDataOffer: error reading data for mimeType %s", qPrintable(mimeType)); content = QByteArray(); } - close(fd); + close(pipefd[0]); m_data.insert(mimeType, content); return content; } diff --git a/src/plugins/platforms/wayland/qwaylanddataoffer_p.h b/src/plugins/platforms/wayland/qwaylanddataoffer_p.h index a21e18bdc8d..12fc0a22f60 100644 --- a/src/plugins/platforms/wayland/qwaylanddataoffer_p.h +++ b/src/plugins/platforms/wayland/qwaylanddataoffer_p.h @@ -87,7 +87,7 @@ private: mutable QWaylandDataOffer *m_dataOffer; QWaylandDisplay *m_display; - mutable QHash m_types; + mutable QStringList m_types; mutable QHash m_data; }; From a3fa898878a8324f88d73204b682ea72ea759cc5 Mon Sep 17 00:00:00 2001 From: Giulio Camuffo Date: Wed, 17 Sep 2014 14:27:15 +0300 Subject: [PATCH 32/32] Ignore negative screen physical size Weston can send in some cases a negative physical size in the wl_output.geometry event. While it is not clear whether that is legal go the extra mile and catch it. Change-Id: Ie2fbab84e653ad77732a72b6ca61509eb7849895 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/wayland/qwaylandscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 943e29a05c1..88667ae0d4f 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -97,7 +97,7 @@ QImage::Format QWaylandScreen::format() const QSizeF QWaylandScreen::physicalSize() const { - if (mPhysicalSize.isNull()) + if (mPhysicalSize.isEmpty()) return QPlatformScreen::physicalSize(); else return mPhysicalSize;