From fa7a1f77226795ece274b3505655e522881a0e24 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Thu, 28 Sep 2017 16:21:21 +0200 Subject: Fix crash after destroying view with mouse focus Don't emit QWaylandSeat::mouseFocusChanged with a destroyed QWaylandView. QWaylandPointer has been refactored to make it easier to follow enter and leave logic. A missing emit for buttonPressedChanged has been fixed as well. This also adds a test for pointer events to verify that setting mouse focus works and that the crash has been fixed. Task-number: QTBUG-63208 Change-Id: Id0c174a7b609dfd0152f3ae446dd51fd8befd554 Reviewed-by: Allan Sandfeld Jensen Reviewed-by: Paul Olav Tvete --- tests/auto/compositor/compositor/compositor.pro | 6 +- tests/auto/compositor/compositor/mockpointer.cpp | 97 ++++++++++++++++++++++ tests/auto/compositor/compositor/mockpointer.h | 47 +++++++++++ tests/auto/compositor/compositor/mockseat.cpp | 1 + tests/auto/compositor/compositor/mockseat.h | 7 ++ .../auto/compositor/compositor/tst_compositor.cpp | 56 +++++++++++++ 6 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 tests/auto/compositor/compositor/mockpointer.cpp create mode 100644 tests/auto/compositor/compositor/mockpointer.h (limited to 'tests') diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro index f0cdaf32c..112e2e74f 100644 --- a/tests/auto/compositor/compositor/compositor.pro +++ b/tests/auto/compositor/compositor/compositor.pro @@ -20,11 +20,13 @@ SOURCES += \ testkeyboardgrabber.cpp \ mockclient.cpp \ mockseat.cpp \ - testseat.cpp + testseat.cpp \ + mockpointer.cpp HEADERS += \ testcompositor.h \ testkeyboardgrabber.h \ mockclient.h \ mockseat.h \ - testseat.h + testseat.h \ + mockpointer.h diff --git a/tests/auto/compositor/compositor/mockpointer.cpp b/tests/auto/compositor/compositor/mockpointer.cpp new file mode 100644 index 000000000..6c51d8bd1 --- /dev/null +++ b/tests/auto/compositor/compositor/mockpointer.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mockpointer.h" + +static void pointerEnter(void *pointer, struct wl_pointer *wlPointer, uint serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y) +{ + Q_UNUSED(wlPointer); + Q_UNUSED(serial); + Q_UNUSED(x); + Q_UNUSED(y); + + static_cast(pointer)->m_enteredSurface = surface; +} + +static void pointerLeave(void *pointer, struct wl_pointer *wlPointer, uint32_t serial, struct wl_surface *surface) +{ + Q_UNUSED(pointer); + Q_UNUSED(wlPointer); + Q_UNUSED(serial); + + Q_ASSERT(surface); + + static_cast(pointer)->m_enteredSurface = nullptr; +} + +static void pointerMotion(void *pointer, struct wl_pointer *wlPointer, uint32_t time, wl_fixed_t x, wl_fixed_t y) +{ + Q_UNUSED(pointer); + Q_UNUSED(wlPointer); + Q_UNUSED(time); + Q_UNUSED(x); + Q_UNUSED(y); +} + +static void pointerButton(void *pointer, struct wl_pointer *wlPointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) +{ + Q_UNUSED(pointer); + Q_UNUSED(wlPointer); + Q_UNUSED(serial); + Q_UNUSED(time); + Q_UNUSED(button); + Q_UNUSED(state); +} + +static void pointerAxis(void *pointer, struct wl_pointer *wlPointer, uint32_t time, uint32_t axis, wl_fixed_t value) +{ + Q_UNUSED(pointer); + Q_UNUSED(wlPointer); + Q_UNUSED(time); + Q_UNUSED(axis); + Q_UNUSED(value); +} + +static const struct wl_pointer_listener pointerListener = { + pointerEnter, + pointerLeave, + pointerMotion, + pointerButton, + pointerAxis, +}; + +MockPointer::MockPointer(wl_seat *seat) + : m_pointer(wl_seat_get_pointer(seat)) +{ + wl_pointer_add_listener(m_pointer, &pointerListener, this); +} + +MockPointer::~MockPointer() +{ + wl_pointer_destroy(m_pointer); +} diff --git a/tests/auto/compositor/compositor/mockpointer.h b/tests/auto/compositor/compositor/mockpointer.h new file mode 100644 index 000000000..353861415 --- /dev/null +++ b/tests/auto/compositor/compositor/mockpointer.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOCKPOINTER_H +#define MOCKPOINTER_H + +#include +#include + +class MockPointer : public QObject +{ + Q_OBJECT + +public: + MockPointer(wl_seat *seat); + ~MockPointer(); + + wl_pointer *m_pointer = nullptr; + wl_surface *m_enteredSurface = nullptr; +}; + +#endif // MOCKPOINTER_H diff --git a/tests/auto/compositor/compositor/mockseat.cpp b/tests/auto/compositor/compositor/mockseat.cpp index 29c4a4e13..052c2f90b 100644 --- a/tests/auto/compositor/compositor/mockseat.cpp +++ b/tests/auto/compositor/compositor/mockseat.cpp @@ -30,6 +30,7 @@ MockSeat::MockSeat(wl_seat *seat) : m_seat(seat) + , m_pointer(new MockPointer(seat)) { // Bind to the keyboard interface so that the compositor has // the right resource associations diff --git a/tests/auto/compositor/compositor/mockseat.h b/tests/auto/compositor/compositor/mockseat.h index 1c6d324c2..e6d5e0b1c 100644 --- a/tests/auto/compositor/compositor/mockseat.h +++ b/tests/auto/compositor/compositor/mockseat.h @@ -28,6 +28,8 @@ #ifndef MOCKSEAT #define MOCKSEAT +#include "mockpointer.h" + #include #include @@ -38,8 +40,13 @@ class MockSeat : public QObject public: MockSeat(wl_seat *seat); ~MockSeat(); + MockPointer *pointer() const { return m_pointer.data(); } wl_seat *m_seat; wl_keyboard *m_keyboard; + +private: + QScopedPointer m_pointer; }; + #endif diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index 3d7d2dab9..6f00b6e61 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -27,6 +27,8 @@ ****************************************************************************/ #include "mockclient.h" +#include "mockseat.h" +#include "mockpointer.h" #include "testcompositor.h" #include "testkeyboardgrabber.h" #include "testseat.h" @@ -56,6 +58,7 @@ private slots: void keyboardGrab(); void seatCreation(); void seatKeyboardFocus(); + void seatMouseFocus(); void singleClient(); void multipleClients(); void geometry(); @@ -438,6 +441,59 @@ void tst_WaylandCompositor::seatKeyboardFocus() QTRY_VERIFY(!compositor.defaultSeat()->keyboardFocus()); } +void tst_WaylandCompositor::seatMouseFocus() +{ + TestCompositor compositor(true); + compositor.create(); + + // Create client after all the seats have been set up as the mock client + // does not dynamically listen to new seats + MockClient client; + wl_surface *surface = client.createSurface(); + QTRY_COMPARE(compositor.surfaces.size(), 1); + + QWaylandSurface *waylandSurface = compositor.surfaces.at(0); + auto view = new QWaylandView; + view->setSurface(waylandSurface); + + QWaylandSeat* seat = compositor.defaultSeat(); + seat->setMouseFocus(view); + seat->sendMouseMoveEvent(view, QPointF(10, 10), QPointF(100, 100)); + + compositor.flushClients(); + + QTRY_VERIFY(seat->mouseFocus()); + QTRY_VERIFY(seat->pointer()); + QTRY_COMPARE(seat->mouseFocus()->surface(), waylandSurface); + + QTRY_COMPARE(client.m_seats.size(), 1); + MockPointer *mockPointer = client.m_seats.first()->pointer(); + QVERIFY(mockPointer); + QTRY_COMPARE(mockPointer->m_enteredSurface, surface); + + delete view; + + compositor.flushClients(); + + QTRY_COMPARE(mockPointer->m_enteredSurface, nullptr); + QTRY_VERIFY(!compositor.defaultSeat()->mouseFocus()); + + view = new QWaylandView; + view->setSurface(waylandSurface); + seat->sendMouseMoveEvent(view, QPointF(10, 10), QPointF(100, 100)); + QTRY_COMPARE(compositor.defaultSeat()->mouseFocus(), view); + + compositor.flushClients(); + + QTRY_COMPARE(mockPointer->m_enteredSurface, surface); + + wl_surface_destroy(surface); + QTRY_VERIFY(compositor.surfaces.size() == 0); + QTRY_VERIFY(!compositor.defaultSeat()->mouseFocus()); + + delete view; +} + class XdgTestCompositor: public TestCompositor { Q_OBJECT public: -- cgit v1.2.3