diff options
86 files changed, 1358 insertions, 672 deletions
diff --git a/.qmake.conf b/.qmake.conf index 0338efe07..dc68d3884 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.10.1 +MODULE_VERSION = 5.11.0 diff --git a/examples/wayland/minimal-cpp/minimal-cpp.pro b/examples/wayland/minimal-cpp/minimal-cpp.pro index 46e422f69..7076825c2 100644 --- a/examples/wayland/minimal-cpp/minimal-cpp.pro +++ b/examples/wayland/minimal-cpp/minimal-cpp.pro @@ -1,4 +1,4 @@ -QT += gui gui-private core-private waylandcompositor waylandcompositor-private +QT += gui waylandcompositor LIBS += -L ../../lib diff --git a/examples/wayland/minimal-qml/main.qml b/examples/wayland/minimal-qml/main.qml index 44920ae73..0f0ca61bc 100644 --- a/examples/wayland/minimal-qml/main.qml +++ b/examples/wayland/minimal-qml/main.qml @@ -50,7 +50,7 @@ import QtQuick 2.6 import QtQuick.Window 2.2 -import QtWayland.Compositor 1.0 +import QtWayland.Compositor 1.1 WaylandCompositor { // The output defines the screen. @@ -60,32 +60,31 @@ WaylandCompositor { width: 1024 height: 768 visible: true - Rectangle { - id: surfaceArea - color: "#1337af" - anchors.fill: parent + Repeater { + model: shellSurfaces + // ShellSurfaceItem handles displaying a shell surface. + // It has implementations for things like interactive + // resize/move, and forwarding of mouse and keyboard + // events to the client process. + ShellSurfaceItem { + shellSurface: modelData + onSurfaceDestroyed: shellSurfaces.remove(index) + } } } } - // The chrome defines the window look and behavior. - // Here we use the built-in ShellSurfaceItem. - Component { - id: chromeComponent - ShellSurfaceItem { - onSurfaceDestroyed: destroy() - } - } // Extensions are additions to the core Wayland // protocol. We choose to support two different // shells (window management protocols). When the - // client creates a new window, we instantiate a - // chromeComponent on the output. + // client creates a new shell surface (i.e. a window) + // we append it to our list of shellSurfaces. WlShell { onWlShellSurfaceCreated: - chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); + shellSurfaces.append({shellSurface: shellSurface}); } - XdgShellV5 { - onXdgSurfaceCreated: - chromeComponent.createObject(surfaceArea, { "shellSurface": xdgSurface } ); + XdgShellV6 { + onToplevelCreated: + shellSurfaces.append({shellSurface: xdgSurface}); } + ListModel { id: shellSurfaces } } diff --git a/examples/wayland/overview-compositor/.gitignore b/examples/wayland/overview-compositor/.gitignore new file mode 100644 index 000000000..e4b9e3403 --- /dev/null +++ b/examples/wayland/overview-compositor/.gitignore @@ -0,0 +1 @@ +overview-compositor diff --git a/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc b/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc new file mode 100644 index 000000000..c34eeb2a7 --- /dev/null +++ b/examples/wayland/overview-compositor/doc/src/overview-compositor.qdoc @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + * \title Qt Wayland Compositor Examples - Overview Compositor + * \example overview-compositor + * \brief Overview Compositor shows how to switch between clients in a grid + * \ingroup qtwaylandcompositor-examples + */ diff --git a/examples/wayland/overview-compositor/main.cpp b/examples/wayland/overview-compositor/main.cpp new file mode 100644 index 000000000..435b4e3f1 --- /dev/null +++ b/examples/wayland/overview-compositor/main.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/overview-compositor/main.qml b/examples/wayland/overview-compositor/main.qml new file mode 100644 index 000000000..6e5cec985 --- /dev/null +++ b/examples/wayland/overview-compositor/main.qml @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.7 +import QtWayland.Compositor 1.0 +import QtQuick.Window 2.0 +import QtQuick.Controls 2.0 + +WaylandCompositor { + WaylandOutput { + sizeFollowsWindow: true + window: Window { + id: win + visible: true + width: 1280 + height: 720 + Grid { + id: grid + anchors.fill: parent + columns: Math.ceil(Math.sqrt(shellSurfaces.count)) + property bool overview: true + property int selected: 0 + property int selectedColumn: selected % columns + property int selectedRow: selected / columns + + transform: [ + Scale { + xScale: grid.overview ? (1.0/grid.columns) : 1 + yScale: grid.overview ? (1.0/grid.columns) : 1 + Behavior on xScale { PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 } } + Behavior on yScale { PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 } } + }, + Translate { + x: grid.overview ? 0 : win.width * -grid.selectedColumn + y: grid.overview ? 0 : win.height * -grid.selectedRow + Behavior on x { PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 } } + Behavior on y { PropertyAnimation { easing.type: Easing.InOutQuad; duration: 200 } } + } + ] + + Repeater { + model: shellSurfaces + Item { + width: win.width + height: win.height + WaylandQuickItem { + anchors.fill: parent + sizeFollowsSurface: false + surface: modelData.surface + onSurfaceDestroyed: shellSurfaces.remove(index) + } + MouseArea { + enabled: grid.overview + anchors.fill: parent + onClicked: { + grid.selected = index; + grid.overview = false; + } + } + } + } + } + + Button { + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + text: "Toggle overview"; + onClicked: grid.overview = !grid.overview + } + + Shortcut { sequence: "space"; onActivated: grid.overview = !grid.overview } + Shortcut { sequence: "right"; onActivated: grid.selected = Math.min(grid.selected+1, shellSurfaces.count-1) } + Shortcut { sequence: "left"; onActivated: grid.selected = Math.max(grid.selected-1, 0) } + Shortcut { sequence: "up"; onActivated: grid.selected = Math.max(grid.selected-grid.columns, 0) } + Shortcut { sequence: "down"; onActivated: grid.selected = Math.min(grid.selected+grid.columns, shellSurfaces.count-1) } + } + } + + ListModel { id: shellSurfaces } + + WlShell { + onWlShellSurfaceCreated: { + shellSurfaces.append({shellSurface: shellSurface}); + shellSurface.sendConfigure(Qt.size(win.width, win.height), WlShellSurface.NoneEdge); + } + } +} diff --git a/examples/wayland/overview-compositor/overview-compositor.pro b/examples/wayland/overview-compositor/overview-compositor.pro new file mode 100644 index 000000000..213d8d01f --- /dev/null +++ b/examples/wayland/overview-compositor/overview-compositor.pro @@ -0,0 +1,14 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + main.qml + +RESOURCES += overview-compositor.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/overview-compositor +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS overview-compositor.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/overview-compositor +INSTALLS += target sources diff --git a/examples/wayland/overview-compositor/overview-compositor.qrc b/examples/wayland/overview-compositor/overview-compositor.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/examples/wayland/overview-compositor/overview-compositor.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp index 2c43e6953..64f468262 100644 --- a/examples/wayland/qwindow-compositor/compositor.cpp +++ b/examples/wayland/qwindow-compositor/compositor.cpp @@ -275,7 +275,7 @@ View * Compositor::findView(const QWaylandSurface *s) const if (view->surface() == s) return view; } - return Q_NULLPTR; + return nullptr; } void Compositor::onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface) diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.pro b/examples/wayland/qwindow-compositor/qwindow-compositor.pro index 8cc7279d1..b9261e772 100644 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.pro +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.pro @@ -1,4 +1,4 @@ -QT += gui gui-private core-private waylandcompositor waylandcompositor-private +QT += gui waylandcompositor LIBS += -L ../../lib diff --git a/src/client/global/qwaylandclientextension.h b/src/client/global/qwaylandclientextension.h index 37debc513..98272e571 100644 --- a/src/client/global/qwaylandclientextension.h +++ b/src/client/global/qwaylandclientextension.h @@ -95,7 +95,7 @@ public: return T::interface(); } - void bind(struct ::wl_registry *registry, int id, int ver) + void bind(struct ::wl_registry *registry, int id, int ver) override { T* instance = static_cast<T *>(this); // Make sure lowest version is used of the supplied version from the diff --git a/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h b/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h index f1f0cf932..7776c6158 100644 --- a/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h +++ b/src/client/hardwareintegration/qwaylandclientbufferintegration_p.h @@ -86,8 +86,8 @@ public: EglConfig, EglContext }; - virtual void *nativeResource(NativeResource /*resource*/) { return Q_NULLPTR; } - virtual void *nativeResourceForContext(NativeResource /*resource*/, QPlatformOpenGLContext */*context*/) { return Q_NULLPTR; } + virtual void *nativeResource(NativeResource /*resource*/) { return nullptr; } + virtual void *nativeResourceForContext(NativeResource /*resource*/, QPlatformOpenGLContext */*context*/) { return nullptr; } }; } diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp index 94eca3262..8f573064e 100644 --- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp +++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegrationfactory.cpp @@ -90,7 +90,7 @@ QWaylandInputDeviceIntegration *QWaylandInputDeviceIntegrationFactory::create(co if (QWaylandInputDeviceIntegration *ret = qLoadPlugin<QWaylandInputDeviceIntegration, QWaylandInputDeviceIntegrationPlugin>(loader(), name, args)) return ret; #endif - return Q_NULLPTR; + return nullptr; } } diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 7caa247e5..bd820e28e 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -92,7 +92,7 @@ struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) waylandCursor = requestCursor((WaylandCursor)newShape); } else if (newShape == Qt::BitmapCursor) { // cannot create a wl_cursor_image for a CursorShape - return Q_NULLPTR; + return nullptr; } else { //TODO: Custom cursor logic (for resize arrows) } @@ -119,7 +119,7 @@ QSharedPointer<QWaylandBuffer> QWaylandCursor::cursorBitmapImage(const QCursor * const QImage &img = cursor->pixmap().toImage(); QSharedPointer<QWaylandShmBuffer> buffer(new QWaylandShmBuffer(mDisplay, img.size(), img.format())); - memcpy(buffer->image()->bits(), img.bits(), img.byteCount()); + memcpy(buffer->image()->bits(), img.bits(), img.sizeInBytes()); return buffer; } diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index 33068c5e9..66f36f75b 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -97,7 +97,7 @@ void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source) { if (source) connect(source, &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::selectionSourceCancelled); - set_selection(source ? source->object() : Q_NULLPTR, m_inputDevice->serial()); + set_selection(source ? source->object() : nullptr, m_inputDevice->serial()); m_selectionSource.reset(source); } @@ -160,7 +160,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface, m_dragWindow = QWaylandWindow::fromWlSurface(surface)->window(); m_dragPoint = calculateDragPosition(x, y, m_dragWindow); - QMimeData *dragData = Q_NULLPTR; + QMimeData *dragData = nullptr; Qt::DropActions supportedActions; m_dragOffer.reset(static_cast<QWaylandDataOffer *>(wl_data_offer_get_user_data(id))); diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 86cfe1a0d..02b1fd9a9 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -97,7 +97,7 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion) { struct ::wl_region *region = mCompositor.create_region(); - Q_FOREACH (const QRect &rect, qregion.rects()) + for (const QRect &rect : qregion) wl_region_add(region, rect.x(), rect.y(), rect.width(), rect.height()); return region; @@ -136,8 +136,8 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) , mLastInputSerial(0) , mLastInputDevice(0) , mLastInputWindow(0) - , mLastKeyboardFocus(Q_NULLPTR) - , mSyncCallback(Q_NULLPTR) + , mLastKeyboardFocus(nullptr) + , mSyncCallback(nullptr) { qRegisterMetaType<uint32_t>("uint32_t"); @@ -157,6 +157,9 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) QWaylandDisplay::~QWaylandDisplay(void) { + if (mSyncCallback) + wl_callback_destroy(mSyncCallback); + qDeleteAll(mInputDevices); mInputDevices.clear(); @@ -343,6 +346,15 @@ sync_callback(void *data, struct wl_callback *callback, uint32_t serial) bool *done = static_cast<bool *>(data); *done = true; + + // If the wl_callback done event is received after the condition check in the while loop in + // forceRoundTrip(), but before the call to processEvents, the call to processEvents may block + // forever if no more events are posted (eventhough the callback is handled in response to the + // aboutToBlock signal). Hence, we wake up the event dispatcher so forceRoundTrip may return. + // (QTBUG-64696) + if (auto *dispatcher = QThread::currentThread()->eventDispatcher()) + dispatcher->wakeUp(); + wl_callback_destroy(callback); } @@ -446,7 +458,7 @@ void QWaylandDisplay::handleWaylandSync() // This callback is used to set the window activation because we may get an activate/deactivate // pair, and the latter one would be lost in the QWindowSystemInterface queue, if we issue the // handleWindowActivated() calls immediately. - QWindow *activeWindow = mActiveWindows.empty() ? Q_NULLPTR : mActiveWindows.last()->window(); + QWindow *activeWindow = mActiveWindows.empty() ? nullptr : mActiveWindows.last()->window(); if (activeWindow != QGuiApplication::focusWindow()) QWindowSystemInterface::handleWindowActivated(activeWindow); } @@ -456,7 +468,7 @@ const wl_callback_listener QWaylandDisplay::syncCallbackListener = { Q_UNUSED(time); wl_callback_destroy(callback); QWaylandDisplay *display = static_cast<QWaylandDisplay *>(data); - display->mSyncCallback = Q_NULLPTR; + display->mSyncCallback = nullptr; display->handleWaylandSync(); } }; diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 4def0de8f..b34504a1f 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -70,19 +70,16 @@ #include <QtGui/QGuiApplication> +#if QT_CONFIG(xkbcommon_evdev) +#include <xkbcommon/xkbcommon-compose.h> +#endif + QT_BEGIN_NAMESPACE namespace QtWaylandClient { QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p) : mParent(p) - , mFocus(0) -#if QT_CONFIG(xkbcommon_evdev) - , mXkbContext(0) - , mXkbMap(0) - , mXkbState(0) -#endif - , mNativeModifiers(0) { connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey())); } @@ -113,6 +110,7 @@ bool QWaylandInputDevice::Keyboard::createDefaultKeyMap() qWarning() << "xkb_map_new_from_names failed, no key input"; return false; } + createComposeState(); return true; } @@ -125,15 +123,45 @@ void QWaylandInputDevice::Keyboard::releaseKeyMap() if (mXkbContext) xkb_context_unref(mXkbContext); } + +void QWaylandInputDevice::Keyboard::createComposeState() +{ + static const char *locale = nullptr; + if (!locale) { + locale = getenv("LC_ALL"); + if (!locale) + locale = getenv("LC_CTYPE"); + if (!locale) + locale = getenv("LANG"); + if (!locale) + locale = "C"; + } + + mXkbComposeTable = xkb_compose_table_new_from_locale(mXkbContext, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); + if (mXkbComposeTable) + mXkbComposeState = xkb_compose_state_new(mXkbComposeTable, XKB_COMPOSE_STATE_NO_FLAGS); +} + +void QWaylandInputDevice::Keyboard::releaseComposeState() +{ + if (mXkbComposeState) + xkb_compose_state_unref(mXkbComposeState); + if (mXkbComposeTable) + xkb_compose_table_unref(mXkbComposeTable); + mXkbComposeState = nullptr; + mXkbComposeTable = nullptr; +} + #endif QWaylandInputDevice::Keyboard::~Keyboard() { #if QT_CONFIG(xkbcommon_evdev) + releaseComposeState(); releaseKeyMap(); #endif if (mFocus) - QWindowSystemInterface::handleWindowActivated(0); + QWindowSystemInterface::handleWindowActivated(nullptr); if (mParent->mVersion >= 3) wl_keyboard_release(object()); else @@ -147,16 +175,6 @@ void QWaylandInputDevice::Keyboard::stopRepeat() QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *p) : mParent(p) - , mFocus(0) - , mEnterSerial(0) -#if QT_CONFIG(cursor) - , mCursorSerial(0) -#endif - , mButtons(0) -#if QT_CONFIG(cursor) - , mCursorBuffer(nullptr) - , mCursorShape(Qt::BitmapCursor) -#endif { } @@ -170,7 +188,6 @@ QWaylandInputDevice::Pointer::~Pointer() QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p) : mParent(p) - , mFocus(0) { } @@ -188,17 +205,6 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, , mQDisplay(display) , mDisplay(display->wl_display()) , mVersion(qMin(version, 4)) - , mCaps(0) -#if QT_CONFIG(wayland_datadevice) - , mDataDevice(0) -#endif - , mKeyboard(0) - , mPointer(0) - , mTouch(0) - , mTextInput(0) - , mTime(0) - , mSerial(0) - , mTouchDevice(0) { #if QT_CONFIG(wayland_datadevice) if (mQDisplay->dndSelectionHandler()) { @@ -227,7 +233,7 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps) mKeyboard->init(get_keyboard()); } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && mKeyboard) { delete mKeyboard; - mKeyboard = 0; + mKeyboard = nullptr; } if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) { @@ -236,7 +242,7 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps) pointerSurface = mQDisplay->createSurface(this); } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) { delete mPointer; - mPointer = 0; + mPointer = nullptr; } if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) { @@ -251,7 +257,7 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps) } } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && mTouch) { delete mTouch; - mTouch = 0; + mTouch = nullptr; } } @@ -272,14 +278,8 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window) { - if (mPointer && window == mPointer->mFocus) - mPointer->mFocus = 0; - if (mKeyboard && window == mKeyboard->mFocus) { - mKeyboard->mFocus = 0; + if (mKeyboard && window == mKeyboard->mFocus) mKeyboard->stopRepeat(); - } - if (mTouch && window == mTouch->mFocus) - mTouch->mFocus = 0; } void QWaylandInputDevice::handleEndDrag() @@ -321,17 +321,17 @@ void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button) QWaylandWindow *QWaylandInputDevice::pointerFocus() const { - return mPointer ? mPointer->mFocus : 0; + return mPointer ? mPointer->mFocus : nullptr; } QWaylandWindow *QWaylandInputDevice::keyboardFocus() const { - return mKeyboard ? mKeyboard->mFocus : 0; + return mKeyboard ? mKeyboard->mFocus : nullptr; } QWaylandWindow *QWaylandInputDevice::touchFocus() const { - return mTouch ? mTouch->mFocus : 0; + return mTouch ? mTouch->mFocus : nullptr; } Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const @@ -411,7 +411,7 @@ void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, const QPoint &hotS /* Hide cursor */ if (!buffer) { - mPointer->set_cursor(mPointer->mEnterSerial, NULL, 0, 0); + mPointer->set_cursor(mPointer->mEnterSerial, nullptr, 0, 0); return; } @@ -434,7 +434,7 @@ class EnterEvent : public QWaylandPointerEvent { public: EnterEvent(const QPointF &l, const QPointF &g) - : QWaylandPointerEvent(QWaylandPointerEvent::Enter, 0, l, g, 0, Qt::NoModifier) + : QWaylandPointerEvent(QWaylandPointerEvent::Enter, 0, l, g, nullptr, Qt::NoModifier) {} }; @@ -474,7 +474,7 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); window->handleMouseLeave(mParent); } - mFocus = 0; + mFocus = nullptr; mButtons = Qt::NoButton; mParent->mTime = time; @@ -493,7 +493,7 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf { QWaylandWindow *window = mFocus; - if (window == NULL) { + if (!window) { // We destroyed the pointer focus surface, but the server // didn't get the message yet. return; @@ -595,7 +595,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in QPoint pixelDelta; QPoint angleDelta; - if (window == NULL) { + if (!window) { // We destroyed the pointer focus surface, but the server // didn't get the message yet. return; @@ -624,7 +624,7 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, return; } - char *map_str = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); if (map_str == MAP_FAILED) { close(fd); return; @@ -632,14 +632,17 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, // Release the old keymap resources in the case they were already created in // the key event or when the compositor issues a new map + releaseComposeState(); releaseKeyMap(); - mXkbContext = xkb_context_new(xkb_context_flags(0)); - mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, (xkb_keymap_compile_flags)0); + mXkbContext = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(map_str, size); close(fd); mXkbState = xkb_state_new(mXkbMap); + createComposeState(); + #else Q_UNUSED(format); Q_UNUSED(fd); @@ -672,7 +675,7 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf window->unfocus(); } - mFocus = NULL; + mFocus = nullptr; mParent->mQDisplay->handleKeyboardFocusChanged(mParent); @@ -703,7 +706,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, { QWaylandWindow *window = mFocus; uint32_t code = key + 8; - bool isDown = state != 0; + bool isDown = state != WL_KEYBOARD_KEY_STATE_RELEASED; QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease; QString text; int qtkey = key + 8; // qt-compositor substracts 8 for some reason @@ -723,12 +726,37 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, return; } - const xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code); + QString composedText; + xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState, code); + if (mXkbComposeState) { + if (isDown) + xkb_compose_state_feed(mXkbComposeState, sym); + xkb_compose_status status = xkb_compose_state_get_status(mXkbComposeState); + + switch (status) { + case XKB_COMPOSE_COMPOSED: { + int size = xkb_compose_state_get_utf8(mXkbComposeState, nullptr, 0); + QVarLengthArray<char, 32> buffer(size + 1); + xkb_compose_state_get_utf8(mXkbComposeState, buffer.data(), buffer.size()); + composedText = QString::fromUtf8(buffer.constData()); + sym = xkb_compose_state_get_one_sym(mXkbComposeState); + xkb_compose_state_reset(mXkbComposeState); + } break; + case XKB_COMPOSE_COMPOSING: + case XKB_COMPOSE_CANCELLED: + return; + case XKB_COMPOSE_NOTHING: + break; + } + } Qt::KeyboardModifiers modifiers = mParent->modifiers(); std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers); + if (!composedText.isNull()) + text = composedText; + sendKey(window->window(), time, type, qtkey, modifiers, code, sym, mNativeModifiers, text); #else // Generic fallback for single hard keys: Assume 'key' is a Qt key code. @@ -817,7 +845,7 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_ { Q_UNUSED(serial); Q_UNUSED(time); - mFocus = 0; + mFocus = nullptr; mParent->handleTouchPoint(id, 0, 0, Qt::TouchPointReleased); // As of Weston 1.5.90 there is no touch_frame after the last touch_up @@ -843,7 +871,7 @@ void QWaylandInputDevice::Touch::touch_cancel() if (touchExt) touchExt->touchCanceled(); - QWindowSystemInterface::handleTouchCancelEvent(0, mParent->mTouchDevice); + QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice); } void QWaylandInputDevice::handleTouchPoint(int id, double x, double y, Qt::TouchPointState state) @@ -928,7 +956,7 @@ void QWaylandInputDevice::Touch::touch_frame() return; } - QWindow *window = mFocus ? mFocus->window() : 0; + QWindow *window = mFocus ? mFocus->window() : nullptr; if (mFocus) { const QWindowSystemInterface::TouchPoint &tp = mTouchPoints.last(); diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index 9e3d1d1f4..8a02769e3 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -71,11 +71,17 @@ #endif #include <QtCore/QDebug> +#include <QPointer> #if QT_CONFIG(cursor) struct wl_cursor_image; #endif +#if QT_CONFIG(xkbcommon_evdev) +struct xkb_compose_state; +struct xkb_compose_table; +#endif + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -141,27 +147,27 @@ private: struct wl_display *mDisplay; int mVersion; - uint32_t mCaps; + uint32_t mCaps = 0; struct wl_surface *pointerSurface; #if QT_CONFIG(wayland_datadevice) - QWaylandDataDevice *mDataDevice; + QWaylandDataDevice *mDataDevice = nullptr; #endif - Keyboard *mKeyboard; - Pointer *mPointer; - Touch *mTouch; + Keyboard *mKeyboard = nullptr; + Pointer *mPointer = nullptr; + Touch *mTouch = nullptr; - QWaylandTextInput *mTextInput; + QWaylandTextInput *mTextInput = nullptr; - uint32_t mTime; - uint32_t mSerial; + uint32_t mTime = 0; + uint32_t mSerial = 0; void seat_capabilities(uint32_t caps) override; void handleTouchPoint(int id, double x, double y, Qt::TouchPointState state); - QTouchDevice *mTouchDevice; + QTouchDevice *mTouchDevice = nullptr; QSharedPointer<QWaylandBuffer> mPixmapCursor; @@ -202,13 +208,15 @@ public: uint32_t group) override; QWaylandInputDevice *mParent; - QWaylandWindow *mFocus; + QPointer<QWaylandWindow> mFocus; #if QT_CONFIG(xkbcommon_evdev) - xkb_context *mXkbContext; - xkb_keymap *mXkbMap; - xkb_state *mXkbState; + xkb_context *mXkbContext = nullptr; + xkb_keymap *mXkbMap = nullptr; + xkb_state *mXkbState = nullptr; + xkb_compose_table *mXkbComposeTable = nullptr; + xkb_compose_state *mXkbComposeState = nullptr; #endif - uint32_t mNativeModifiers; + uint32_t mNativeModifiers = 0; int mRepeatKey; uint32_t mRepeatCode; @@ -228,6 +236,8 @@ private: #if QT_CONFIG(xkbcommon_evdev) bool createDefaultKeyMap(); void releaseKeyMap(); + void createComposeState(); + void releaseComposeState(); #endif }; @@ -253,17 +263,17 @@ public: void releaseButtons(); QWaylandInputDevice *mParent; - QWaylandWindow *mFocus; - uint32_t mEnterSerial; + QPointer<QWaylandWindow> mFocus; + uint32_t mEnterSerial = 0; #if QT_CONFIG(cursor) - uint32_t mCursorSerial; + uint32_t mCursorSerial = 0; #endif QPointF mSurfacePos; QPointF mGlobalPos; - Qt::MouseButtons mButtons; + Qt::MouseButtons mButtons = Qt::NoButton; #if QT_CONFIG(cursor) - wl_buffer *mCursorBuffer; - Qt::CursorShape mCursorShape; + wl_buffer *mCursorBuffer = nullptr; + Qt::CursorShape mCursorShape = Qt::BitmapCursor; #endif }; @@ -293,7 +303,7 @@ public: void releasePoints(); QWaylandInputDevice *mParent; - QWaylandWindow *mFocus; + QPointer<QWaylandWindow> mFocus; QList<QWindowSystemInterface::TouchPoint> mTouchPoints; QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints; }; diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index bffadf29a..f0182218f 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -122,7 +122,7 @@ public: QWaylandIntegration::QWaylandIntegration() : mClientBufferIntegration(0) - , mInputDeviceIntegration(Q_NULLPTR) + , mInputDeviceIntegration(nullptr) , mFontDb(new QGenericUnixFontDatabase()) , mNativeInterface(new QWaylandNativeInterface(this)) #if QT_CONFIG(accessibility) @@ -397,7 +397,7 @@ void QWaylandIntegration::initializeShellIntegration() "please specify the shell using QT_WAYLAND_SHELL_INTEGRATION instead"; preferredShells << QLatin1String("xdg-shell-v5"); } - preferredShells << QLatin1String("wl-shell"); + preferredShells << QLatin1String("wl-shell") << QLatin1String("ivi-shell"); } Q_FOREACH (QString preferredShell, preferredShells) { diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp index 5b43428d9..b6336f2e6 100644 --- a/src/client/qwaylandscreen.cpp +++ b/src/client/qwaylandscreen.cpp @@ -147,7 +147,7 @@ void QWaylandScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask) { foreach (QWindow *window, QGuiApplication::allWindows()) { QWaylandWindow *w = static_cast<QWaylandWindow *>(window->handle()); - if (w && w->screen() == this) + if (w && w->waylandScreen() == this) w->setOrientationMask(mask); } } diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp index 2085bc597..a13a5f764 100644 --- a/src/client/qwaylandshmbackingstore.cpp +++ b/src/client/qwaylandshmbackingstore.cpp @@ -125,7 +125,7 @@ QWaylandShmBuffer::~QWaylandShmBuffer(void) { delete mMarginsImage; if (mImage.constBits()) - munmap((void *) mImage.constBits(), mImage.byteCount()); + munmap((void *) mImage.constBits(), mImage.sizeInBytes()); if (mShmPool) wl_shm_pool_destroy(mShmPool); } @@ -171,7 +171,7 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window) QWaylandShmBackingStore::~QWaylandShmBackingStore() { if (QWaylandWindow *w = waylandWindow()) - w->setBackingStore(Q_NULLPTR); + w->setBackingStore(nullptr); // if (mFrontBuffer == waylandWindow()->attached()) // waylandWindow()->attach(0); @@ -287,10 +287,10 @@ void QWaylandShmBackingStore::resize(const QSize &size) buffer = getBuffer(sizeWithMargins); } - int oldSize = mBackBuffer ? mBackBuffer->image()->byteCount() : 0; + qsizetype oldSize = mBackBuffer ? mBackBuffer->image()->sizeInBytes() : 0; // mBackBuffer may have been deleted here but if so it means its size was different so we wouldn't copy it anyway - if (mBackBuffer != buffer && oldSize == buffer->image()->byteCount()) { - memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), buffer->image()->byteCount()); + if (mBackBuffer != buffer && oldSize == buffer->image()->sizeInBytes()) { + memcpy(buffer->image()->bits(), mBackBuffer->image()->constBits(), buffer->image()->sizeInBytes()); } mBackBuffer = buffer; // ensure the new buffer is at the beginning of the list so next time getBuffer() will pick diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 6661d8e7e..2e709440f 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -80,7 +80,7 @@ QWaylandWindow *QWaylandWindow::mMouseGrab = 0; QWaylandWindow::QWaylandWindow(QWindow *window) : QObject() , QPlatformWindow(window) - , mDisplay(screen()->display()) + , mDisplay(waylandScreen()->display()) , mShellSurface(0) , mSubSurfaceWindow(0) , mWindowDecoration(0) @@ -95,7 +95,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mScale(1) , mState(Qt::WindowNoState) , mMask() - , mBackingStore(Q_NULLPTR) + , mBackingStore(nullptr) , mUpdateRequested(false) { static WId id = 1; @@ -128,6 +128,12 @@ QWaylandWindow::~QWaylandWindow() } } +void QWaylandWindow::ensureSize() +{ + if (mBackingStore) + mBackingStore->ensureSize(); +} + void QWaylandWindow::initWindow() { if (window()->type() == Qt::Desktop) @@ -194,12 +200,11 @@ void QWaylandWindow::initWindow() } } - mScale = screen()->scale(); + mScale = waylandScreen()->scale(); // Enable high-dpi rendering. Scale() returns the screen scale factor and will // typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale() // to inform the compositor that high-resolution buffers will be provided. - //FIXME this needs to be changed when the screen changes along with a resized backing store if (mDisplay->compositorVersion() >= 3) set_buffer_scale(scale()); @@ -241,7 +246,7 @@ bool QWaylandWindow::shouldCreateShellSurface() const bool QWaylandWindow::shouldCreateSubSurface() const { - return QPlatformWindow::parent() != Q_NULLPTR; + return QPlatformWindow::parent() != nullptr; } void QWaylandWindow::reset(bool sendDestroyEvent) @@ -369,7 +374,7 @@ void QWaylandWindow::closePopups(QWaylandWindow *parent) QWaylandScreen *QWaylandWindow::calculateScreenFromSurfaceEvents() const { - return mScreens.isEmpty() ? screen() : mScreens.first(); + return mScreens.isEmpty() ? waylandScreen() : mScreens.first(); } void QWaylandWindow::setVisible(bool visible) @@ -523,7 +528,7 @@ void QWaylandWindow::surface_enter(wl_output *output) QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents(); if (oldScreen != newScreen) //currently this will only happen if the first wl_surface.enter is for a non-primary screen - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); + handleScreenChanged(); } void QWaylandWindow::surface_leave(wl_output *output) @@ -540,7 +545,7 @@ void QWaylandWindow::surface_leave(wl_output *output) QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents(); if (oldScreen != newScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); + handleScreenChanged(); } void QWaylandWindow::handleScreenRemoved(QScreen *qScreen) @@ -550,7 +555,7 @@ void QWaylandWindow::handleScreenRemoved(QScreen *qScreen) if (wasRemoved) { QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents(); if (oldScreen != newScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); + handleScreenChanged(); } } @@ -590,8 +595,7 @@ void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) return; attachOffset(buffer); - const QVector<QRect> rects = damage.rects(); - for (const QRect &rect: rects) + for (const QRect &rect: damage) wl_surface::damage(rect.x(), rect.y(), rect.width(), rect.height()); wl_surface::commit(); } @@ -603,6 +607,7 @@ const wl_callback_listener QWaylandWindow::callbackListener = { void QWaylandWindow::frameCallback(void *data, struct wl_callback *callback, uint32_t time) { Q_UNUSED(time); + Q_UNUSED(callback); QWaylandWindow *self = static_cast<QWaylandWindow*>(data); self->mWaitingForFrameSync = false; @@ -642,7 +647,7 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const return mSubSurfaceWindow; } -QWaylandScreen *QWaylandWindow::screen() const +QWaylandScreen *QWaylandWindow::waylandScreen() const { return static_cast<QWaylandScreen *>(QPlatformWindow::screen()); } @@ -913,10 +918,24 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe } } +void QWaylandWindow::handleScreenChanged() +{ + QWaylandScreen *newScreen = calculateScreenFromSurfaceEvents(); + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen()); + + int scale = newScreen->scale(); + if (scale != mScale) { + mScale = scale; + if (isInitialized() && mDisplay->compositorVersion() >= 3) + set_buffer_scale(mScale); + ensureSize(); + } +} + #if QT_CONFIG(cursor) void QWaylandWindow::setMouseCursor(QWaylandInputDevice *device, const QCursor &cursor) { - device->setCursor(cursor, screen()); + device->setCursor(cursor, waylandScreen()); } void QWaylandWindow::restoreMouseCursor(QWaylandInputDevice *device) diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 961b7881d..fca96f30d 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -110,6 +110,7 @@ public: ~QWaylandWindow(); virtual WindowType windowType() const = 0; + virtual void ensureSize(); WId winId() const override; void setVisible(bool visible) override; void setParent(const QPlatformWindow *parent) override; @@ -142,7 +143,7 @@ public: QWaylandDisplay *display() const { return mDisplay; } QWaylandShellSurface *shellSurface() const; QWaylandSubSurface *subSurfaceWindow() const; - QWaylandScreen *screen() const; + QWaylandScreen *waylandScreen() const; void handleContentOrientationChange(Qt::ScreenOrientation orientation) override; void setOrientationMask(Qt::ScreenOrientations mask); @@ -263,6 +264,7 @@ private: QWaylandScreen *calculateScreenFromSurfaceEvents() const; void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e); + void handleScreenChanged(); bool mUpdateRequested; @@ -285,8 +287,8 @@ inline QPoint QWaylandWindow::attachOffset() const return mOffset; } -QT_END_NAMESPACE - } +QT_END_NAMESPACE + #endif // QWAYLANDWINDOW_H diff --git a/src/client/qwaylandwlshellintegration.cpp b/src/client/qwaylandwlshellintegration.cpp index e945745e2..e51637108 100644 --- a/src/client/qwaylandwlshellintegration.cpp +++ b/src/client/qwaylandwlshellintegration.cpp @@ -55,7 +55,7 @@ QWaylandWlShellIntegration *QWaylandWlShellIntegration::create(QWaylandDisplay * } QWaylandWlShellIntegration::QWaylandWlShellIntegration(QWaylandDisplay *display) - : m_wlShell(Q_NULLPTR) + : m_wlShell(nullptr) { Q_FOREACH (QWaylandDisplay::RegistryGlobal global, display->globals()) { if (global.interface == QLatin1String("wl_shell")) { diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp index 92223f45e..185cfc4a9 100644 --- a/src/client/qwaylandwlshellsurface.cpp +++ b/src/client/qwaylandwlshellsurface.cpp @@ -58,7 +58,7 @@ QWaylandWlShellSurface::QWaylandWlShellSurface(struct ::wl_shell_surface *shell_ , m_window(window) , m_maximized(false) , m_fullscreen(false) - , m_extendedWindow(Q_NULLPTR) + , m_extendedWindow(nullptr) { if (window->display()->windowExtension()) m_extendedWindow = new QWaylandExtendedSurface(window); @@ -192,7 +192,7 @@ void QWaylandWlShellSurface::updateTransientParent(QWindow *parent) flags); } -void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial) +void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, uint serial) { QWaylandWindow *parent_wayland_window = parent; if (!parent_wayland_window) { diff --git a/src/client/qwaylandwlshellsurface_p.h b/src/client/qwaylandwlshellsurface_p.h index 94e3417a4..62583949b 100644 --- a/src/client/qwaylandwlshellsurface_p.h +++ b/src/client/qwaylandwlshellsurface_p.h @@ -102,7 +102,7 @@ private: void setTopLevel(); void updateTransientParent(QWindow *parent); - void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial); + void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, uint serial); QWaylandWindow *m_window; bool m_maximized; diff --git a/src/client/qwaylandxdgshellintegration.cpp b/src/client/qwaylandxdgshellintegration.cpp index 04b8e8048..7c40d2dd7 100644 --- a/src/client/qwaylandxdgshellintegration.cpp +++ b/src/client/qwaylandxdgshellintegration.cpp @@ -57,7 +57,7 @@ QWaylandXdgShellIntegration *QWaylandXdgShellIntegration::create(QWaylandDisplay } QWaylandXdgShellIntegration::QWaylandXdgShellIntegration(QWaylandDisplay *display) - : m_xdgShell(Q_NULLPTR) + : m_xdgShell(nullptr) { Q_FOREACH (QWaylandDisplay::RegistryGlobal global, display->globals()) { if (global.interface == QLatin1String("xdg_shell")) { diff --git a/src/client/qwaylandxdgsurface.cpp b/src/client/qwaylandxdgsurface.cpp index fe8761e5b..60266af68 100644 --- a/src/client/qwaylandxdgsurface.cpp +++ b/src/client/qwaylandxdgsurface.cpp @@ -61,7 +61,7 @@ QWaylandXdgSurface::QWaylandXdgSurface(QWaylandXdgShell *shell, QWaylandWindow * , m_minimized(false) , m_fullscreen(false) , m_active(false) - , m_extendedWindow(Q_NULLPTR) + , m_extendedWindow(nullptr) { if (window->display()->windowExtension()) m_extendedWindow = new QWaylandExtendedSurface(window); @@ -105,7 +105,7 @@ void QWaylandXdgSurface::setMaximized() void QWaylandXdgSurface::setFullscreen() { if (!m_fullscreen) - set_fullscreen(Q_NULLPTR); + set_fullscreen(nullptr); } void QWaylandXdgSurface::setNormal() diff --git a/src/client/shellintegration/qwaylandshellintegrationfactory.cpp b/src/client/shellintegration/qwaylandshellintegrationfactory.cpp index 09c62339b..c5a505bbe 100644 --- a/src/client/shellintegration/qwaylandshellintegrationfactory.cpp +++ b/src/client/shellintegration/qwaylandshellintegrationfactory.cpp @@ -90,7 +90,7 @@ QWaylandShellIntegration *QWaylandShellIntegrationFactory::create(const QString if (QWaylandShellIntegration *ret = qLoadPlugin<QWaylandShellIntegration, QWaylandShellIntegrationPlugin>(loader(), name, args)) return ret; #endif - return Q_NULLPTR; + return nullptr; } } diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp index 57a120e48..8ceeeea56 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.cpp +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -185,7 +185,7 @@ bool QWaylandBufferRef::isDestroyed() const */ struct ::wl_resource *QWaylandBufferRef::wl_buffer() const { - return d->buffer ? d->buffer->waylandBufferHandle() : Q_NULLPTR; + return d->buffer ? d->buffer->waylandBufferHandle() : nullptr; } /*! diff --git a/src/compositor/compositor_api/qwaylandclient.cpp b/src/compositor/compositor_api/qwaylandclient.cpp index 2b73c06ca..122fd41c3 100644 --- a/src/compositor/compositor_api/qwaylandclient.cpp +++ b/src/compositor/compositor_api/qwaylandclient.cpp @@ -146,7 +146,7 @@ QWaylandClient *QWaylandClient::fromWlClient(QWaylandCompositor *compositor, wl_ if (!wlClient) return 0; - QWaylandClient *client = Q_NULLPTR; + QWaylandClient *client = nullptr; wl_listener *l = wl_client_get_destroy_listener(wlClient, QWaylandClientPrivate::client_destroy_callback); diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp index 4e7040889..4c662a34a 100644 --- a/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -656,7 +656,7 @@ QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const return output; } - return Q_NULLPTR; + return nullptr; } /*! @@ -822,7 +822,7 @@ QWaylandSeat *QWaylandCompositor::defaultSeat() const Q_D(const QWaylandCompositor); if (d->seats.size()) return d->seats.first(); - return Q_NULLPTR; + return nullptr; } /*! diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h index 3970ff152..18595a806 100644 --- a/src/compositor/compositor_api/qwaylandcompositor_p.h +++ b/src/compositor/compositor_api/qwaylandcompositor_p.h @@ -87,7 +87,7 @@ public: void destroySurface(QWaylandSurface *surface); void unregisterSurface(QWaylandSurface *surface); - QWaylandOutput *defaultOutput() const { return outputs.size() ? outputs.first() : Q_NULLPTR; } + QWaylandOutput *defaultOutput() const { return outputs.size() ? outputs.first() : nullptr; } inline QtWayland::ClientBufferIntegration *clientBufferIntegration() const; inline QtWayland::ServerBufferIntegration *serverBufferIntegration() const; diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp index c30f7b18d..930eae1ae 100644 --- a/src/compositor/compositor_api/qwaylandkeyboard.cpp +++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp @@ -122,7 +122,7 @@ void QWaylandKeyboardPrivate::sendEnter(QWaylandSurface *surface, Resource *keyb void QWaylandKeyboardPrivate::focused(QWaylandSurface *surface) { if (surface && surface->isCursorSurface()) - surface = Q_NULLPTR; + surface = nullptr; if (focus != surface) { if (focusResource) { uint32_t serial = compositor()->nextSerial(); @@ -466,7 +466,7 @@ QWaylandClient *QWaylandKeyboard::focusClient() const { Q_D(const QWaylandKeyboard); if (!d->focusResource) - return Q_NULLPTR; + return nullptr; return QWaylandClient::fromWlClient(compositor(), d->focusResource->client()); } diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp index c369bb26c..9cbf80fd3 100644 --- a/src/compositor/compositor_api/qwaylandoutput.cpp +++ b/src/compositor/compositor_api/qwaylandoutput.cpp @@ -104,8 +104,8 @@ static QtWaylandServer::wl_output::transform toWlTransform(const QWaylandOutput: QWaylandOutputPrivate::QWaylandOutputPrivate() : QtWaylandServer::wl_output() - , compositor(Q_NULLPTR) - , window(Q_NULLPTR) + , compositor(nullptr) + , window(nullptr) , currentMode(-1) , preferredMode(-1) , subpixel(QWaylandOutput::SubpixelUnknown) @@ -319,7 +319,7 @@ struct ::wl_resource *QWaylandOutput::resourceForClient(QWaylandClient *client) if (r) return r->handle; - return Q_NULLPTR; + return nullptr; } /*! @@ -997,7 +997,7 @@ void QWaylandOutput::handleSetHeight(int newHeight) void QWaylandOutput::handleWindowDestroyed() { Q_D(QWaylandOutput); - d->window = Q_NULLPTR; + d->window = nullptr; emit windowChanged(); emit windowDestroyed(); } diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h index 594fe1291..dab6daf73 100644 --- a/src/compositor/compositor_api/qwaylandoutput_p.h +++ b/src/compositor/compositor_api/qwaylandoutput_p.h @@ -87,7 +87,7 @@ struct QWaylandSurfaceViewMapper if (surface && surface->primaryView() == views.at(i)) return views.at(i); } - return Q_NULLPTR; + return nullptr; } QWaylandSurface *surface; diff --git a/src/compositor/compositor_api/qwaylandpointer.cpp b/src/compositor/compositor_api/qwaylandpointer.cpp index bf4bf547d..4bdee9be2 100644 --- a/src/compositor/compositor_api/qwaylandpointer.cpp +++ b/src/compositor/compositor_api/qwaylandpointer.cpp @@ -133,7 +133,7 @@ void QWaylandPointerPrivate::pointer_set_cursor(wl_pointer::Resource *resource, Q_UNUSED(serial); if (!surface) { - seat->cursorSurfaceRequest(Q_NULLPTR, 0, 0); + seat->cursorSurfaceRequest(nullptr, 0, 0); return; } @@ -250,7 +250,7 @@ void QWaylandPointer::sendMouseMoveEvent(QWaylandView *view, const QPointF &loca { Q_D(QWaylandPointer); if (view && (!view->surface() || view->surface()->isCursorSurface())) - view = Q_NULLPTR; + view = nullptr; d->seat->setMouseFocus(view); d->localPosition = localPos; d->spacePosition = outputSpacePos; diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index 5414d06ae..de5a36cdb 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -384,7 +384,7 @@ QWaylandQuickItem::~QWaylandQuickItem() QWaylandCompositor *QWaylandQuickItem::compositor() const { Q_D(const QWaylandQuickItem); - return d->view->surface() ? d->view->surface()->compositor() : Q_NULLPTR; + return d->view->surface() ? d->view->surface()->compositor() : nullptr; } /*! @@ -587,7 +587,7 @@ void QWaylandQuickItem::hoverLeaveEvent(QHoverEvent *event) Q_D(QWaylandQuickItem); if (d->shouldSendInputEvents()) { QWaylandSeat *seat = compositor()->seatFor(event); - seat->setMouseFocus(Q_NULLPTR); + seat->setMouseFocus(nullptr); } else { event->ignore(); } @@ -949,9 +949,14 @@ void QWaylandQuickItem::parentChanged(QWaylandSurface *newParent, QWaylandSurfac void QWaylandQuickItem::updateSize() { Q_D(QWaylandQuickItem); - if (d->sizeFollowsSurface && surface()) { - setSize(surface()->size() * (d->scaleFactor() / surface()->bufferScale())); - } + + QSize size(0, 0); + if (surface()) + size = surface()->size() * (d->scaleFactor() / surface()->bufferScale()); + + setImplicitSize(size.width(), size.height()); + if (d->sizeFollowsSurface) + setSize(size); } /*! @@ -1006,7 +1011,13 @@ bool QWaylandQuickItem::inputRegionContains(const QPointF &localPosition) QPointF QWaylandQuickItem::mapToSurface(const QPointF &point) const { Q_D(const QWaylandQuickItem); - return point / d->scaleFactor(); + if (!surface() || surface()->size().isEmpty()) + return point / d->scaleFactor(); + + qreal xScale = width() / surface()->size().width(); + qreal yScale = height() / surface()->size().height(); + + return QPointF(point.x() / xScale, point.y() / yScale); } /*! @@ -1032,6 +1043,9 @@ bool QWaylandQuickItem::sizeFollowsSurface() const return d->sizeFollowsSurface; } +//TODO: sizeFollowsSurface became obsolete when we added an implementation for +//implicit size. The property is here for compatibility reasons only and should +//be removed or at least default to false in Qt 6. void QWaylandQuickItem::setSizeFollowsSurface(bool sizeFollowsSurface) { Q_D(QWaylandQuickItem); diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index 30b96c4f6..98af6ba7c 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -109,9 +109,9 @@ class QWaylandQuickItemPrivate : public QQuickItemPrivate public: QWaylandQuickItemPrivate() : QQuickItemPrivate() - , view(Q_NULLPTR) - , oldSurface(Q_NULLPTR) - , provider(Q_NULLPTR) + , view(nullptr) + , oldSurface(nullptr) + , provider(nullptr) , paintEnabled(true) , touchEventsEnabled(true) , inputEventsEnabled(true) @@ -119,7 +119,7 @@ public: , newTexture(false) , focusOnClick(true) , sizeFollowsSurface(true) - , connectedWindow(Q_NULLPTR) + , connectedWindow(nullptr) , origin(QWaylandSurface::OriginTopLeft) { } diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index ec68ee6a1..1197e9e43 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -49,9 +49,6 @@ #include <QtWaylandCompositor/QWaylandView> #include <QtWaylandCompositor/private/qwaylandsurface_p.h> -#include <QtWaylandCompositor/private/qwayland-server-surface-extension.h> -#include <QtWaylandCompositor/private/qwlextendedsurface_p.h> - QT_BEGIN_NAMESPACE class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate @@ -112,8 +109,11 @@ void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha) /*! * \qmlproperty bool QtWaylandCompositor::WaylandSurface::clientRenderingEnabled + * \deprecated * - * This property specifies whether client rendering is enabled for the surface. + * This property used to specify whether client rendering was enabled for the surface. + * It depended on a Wayland extension that was part of the private API. The surface extension + * is not used anymore, so this property does nothing. */ bool QWaylandQuickSurface::clientRenderingEnabled() const { @@ -124,12 +124,9 @@ bool QWaylandQuickSurface::clientRenderingEnabled() const void QWaylandQuickSurface::setClientRenderingEnabled(bool enabled) { Q_D(QWaylandQuickSurface); + qWarning() << Q_FUNC_INFO << "doesn't do anything"; if (d->clientRenderingEnabled != enabled) { d->clientRenderingEnabled = enabled; - - if (QtWayland::ExtendedSurface *extSurface = QtWayland::ExtendedSurface::findIn(this)) - extSurface->setVisibility(enabled ? QWindow::AutomaticVisibility : QWindow::Hidden); - emit clientRenderingEnabledChanged(); } } diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h index 7ec08e123..273fb25f4 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.h +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -63,12 +63,12 @@ public: bool useTextureAlpha() const; void setUseTextureAlpha(bool useTextureAlpha); - bool clientRenderingEnabled() const; - void setClientRenderingEnabled(bool enabled); + Q_DECL_DEPRECATED bool clientRenderingEnabled() const; + Q_DECL_DEPRECATED void setClientRenderingEnabled(bool enabled); Q_SIGNALS: void useTextureAlphaChanged(); - void clientRenderingEnabledChanged(); + void clientRenderingEnabledChanged(); //deprecated }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp index b4b45392c..4b506bcda 100644 --- a/src/compositor/compositor_api/qwaylandseat.cpp +++ b/src/compositor/compositor_api/qwaylandseat.cpp @@ -65,7 +65,7 @@ QWaylandSeatPrivate::QWaylandSeatPrivate(QWaylandSeat *seat) , QtWaylandServer::wl_seat() , isInitialized(false) , compositor(nullptr) - , mouseFocus(Q_NULLPTR) + , mouseFocus(nullptr) , keyboardFocus(nullptr) , capabilities() #if QT_CONFIG(wayland_datadevice) @@ -298,7 +298,93 @@ uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const Q } /*! - * Sends a frame event to the touch device of a \a client. + * \qmlmethod uint QtWaylandCompositor::WaylandSeat::sendTouchPointPressed(WaylandSurface surface, int id, point position) + * + * Sends a touch pressed event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch down event. + */ + +/*! + * Sends a touch pressed event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch down event. + */ +uint QWaylandSeat::sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position) +{ + return sendTouchPointEvent(surface, id, position, Qt::TouchPointPressed); +} + +/*! + * \qmlmethod void QtWaylandCompositor::WaylandSeat::sendTouchPointReleased(WaylandSurface surface, int id, point position) + * + * Sends a touch released event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch up event. + */ + +/*! + * Sends a touch released event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch up event. + */ +uint QWaylandSeat::sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position) +{ + return sendTouchPointEvent(surface, id, position, Qt::TouchPointReleased); +} + +/*! + * \qmlmethod void QtWaylandCompositor::WaylandSeat::sendTouchPointMoved(WaylandSurface surface, int id, point position) + * + * Sends a touch moved event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch motion event. + */ + +/*! + * Sends a touch moved event for the touch point \a id on \a surface with + * position \a position. + * + * \note You need to send a touch frame event when you are done sending touch + * events. + * + * Returns the serial for the touch motion event. + */ +uint QWaylandSeat::sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position) +{ + return sendTouchPointEvent(surface, id, position, Qt::TouchPointMoved); +} + +/*! + * \qmlmethod void QtWaylandCompositor::WaylandSeat::sendTouchFrameEvent(WaylandClient client) + * + * Sends a frame event to the touch device of a \a client to indicate the end + * of a series of touch up, down, and motion events. + */ + +/*! + * Sends a frame event to the touch device of a \a client to indicate the end + * of a series of touch up, down, and motion events. */ void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client) { @@ -308,6 +394,12 @@ void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client) } /*! + * \qmlmethod void QtWaylandCompositor::WaylandSeat::sendTouchCancelEvent(WaylandClient client) + * + * Sends a cancel event to the touch device of a \a client. + */ + +/*! * Sends a cancel event to the touch device of a \a client. */ void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client) @@ -381,7 +473,7 @@ QWaylandSurface *QWaylandSeat::keyboardFocus() const { Q_D(const QWaylandSeat); if (d->keyboard.isNull() || !d->keyboard->focus()) - return Q_NULLPTR; + return nullptr; return d->keyboard->focus(); } diff --git a/src/compositor/compositor_api/qwaylandseat.h b/src/compositor/compositor_api/qwaylandseat.h index e5ef46dc6..d22e05a5b 100644 --- a/src/compositor/compositor_api/qwaylandseat.h +++ b/src/compositor/compositor_api/qwaylandseat.h @@ -99,8 +99,11 @@ public: void sendFullKeyEvent(QKeyEvent *event); uint sendTouchPointEvent(QWaylandSurface *surface, int id, const QPointF &point, Qt::TouchPointState state); - void sendTouchFrameEvent(QWaylandClient *client); - void sendTouchCancelEvent(QWaylandClient *client); + Q_INVOKABLE uint sendTouchPointPressed(QWaylandSurface *surface, int id, const QPointF &position); + Q_INVOKABLE uint sendTouchPointReleased(QWaylandSurface *surface, int id, const QPointF &position); + Q_INVOKABLE uint sendTouchPointMoved(QWaylandSurface *surface, int id, const QPointF &position); + Q_INVOKABLE void sendTouchFrameEvent(QWaylandClient *client); + Q_INVOKABLE void sendTouchCancelEvent(QWaylandClient *client); void sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event); diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 05113c41c..37b6876ac 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -49,7 +49,6 @@ #include "wayland_wrapper/qwldatadevicemanager_p.h" #endif -#include "extensions/qwlextendedsurface_p.h" #include "qwaylandinputmethodcontrol_p.h" #include <QtWaylandCompositor/QWaylandCompositor> @@ -127,9 +126,9 @@ QList<QWaylandSurfacePrivate *> QWaylandSurfacePrivate::uninitializedSurfaces; QWaylandSurfacePrivate::QWaylandSurfacePrivate() : QtWaylandServer::wl_surface() - , compositor(Q_NULLPTR) + , compositor(nullptr) , refCount(1) - , client(Q_NULLPTR) + , client(nullptr) , role(0) , inputRegion(infiniteRegion()) , bufferScale(1) @@ -139,7 +138,7 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate() , isInitialized(false) , contentOrientation(Qt::PrimaryOrientation) #if QT_CONFIG(im) - , inputMethodControl(Q_NULLPTR) + , inputMethodControl(nullptr) #endif , subsurface(0) { @@ -459,7 +458,7 @@ QWaylandClient *QWaylandSurface::client() const { Q_D(const QWaylandSurface); if (isDestroyed() || !compositor() || !compositor()->clients().contains(d->client)) - return Q_NULLPTR; + return nullptr; return d->client; } @@ -603,7 +602,7 @@ void QWaylandSurface::sendFrameCallbacks() int i = 0; while (i < d->frameCallbacks.size()) { if (d->frameCallbacks.at(i)->canSend) { - d->frameCallbacks.at(i)->surface = Q_NULLPTR; + d->frameCallbacks.at(i)->surface = nullptr; d->frameCallbacks.at(i)->send(time); d->frameCallbacks.removeAt(i); } else { @@ -716,7 +715,7 @@ QWaylandView *QWaylandSurface::primaryView() const { Q_D(const QWaylandSurface); if (d->views.isEmpty()) - return Q_NULLPTR; + return nullptr; return d->views.first(); } @@ -808,7 +807,7 @@ QWaylandSurfaceRole *QWaylandSurface::role() const QWaylandSurfacePrivate *QWaylandSurfacePrivate::get(QWaylandSurface *surface) { - return surface ? surface->d_func() : Q_NULLPTR; + return surface ? surface->d_func() : nullptr; } void QWaylandSurfacePrivate::ref() diff --git a/src/compositor/compositor_api/qwaylandsurfacegrabber.h b/src/compositor/compositor_api/qwaylandsurfacegrabber.h index ce1e397e5..c28614f37 100644 --- a/src/compositor/compositor_api/qwaylandsurfacegrabber.h +++ b/src/compositor/compositor_api/qwaylandsurfacegrabber.h @@ -60,7 +60,7 @@ public: RendererNotReady, }; Q_ENUM(Error) - explicit QWaylandSurfaceGrabber(QWaylandSurface *surface, QObject *parent = Q_NULLPTR); + explicit QWaylandSurfaceGrabber(QWaylandSurface *surface, QObject *parent = nullptr); QWaylandSurface *surface() const; void grab(); diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp index 9e8297574..4d6f392e1 100644 --- a/src/compositor/compositor_api/qwaylandview.cpp +++ b/src/compositor/compositor_api/qwaylandview.cpp @@ -55,7 +55,7 @@ void QWaylandViewPrivate::markSurfaceAsDestroyed(QWaylandSurface *surface) Q_Q(QWaylandView); Q_ASSERT(surface == this->surface); - q->setSurface(Q_NULLPTR); + q->setSurface(nullptr); emit q->surfaceDestroyed(); } @@ -376,7 +376,7 @@ struct wl_resource *QWaylandView::surfaceResource() const { Q_D(const QWaylandView); if (!d->surface) - return Q_NULLPTR; + return nullptr; return d->surface->resource(); } diff --git a/src/compositor/compositor_api/qwaylandview_p.h b/src/compositor/compositor_api/qwaylandview_p.h index 326e0b297..a2bf219d7 100644 --- a/src/compositor/compositor_api/qwaylandview_p.h +++ b/src/compositor/compositor_api/qwaylandview_p.h @@ -69,9 +69,9 @@ public: static QWaylandViewPrivate *get(QWaylandView *view) { return view->d_func(); } QWaylandViewPrivate() - : renderObject(Q_NULLPTR) - , surface(Q_NULLPTR) - , output(Q_NULLPTR) + : renderObject(nullptr) + , surface(nullptr) + , output(nullptr) , nextBufferCommitted(false) , bufferLocked(false) , broadcastRequestedPositionChanged(false) diff --git a/src/compositor/doc/qtwaylandcompositor.qdocconf b/src/compositor/doc/qtwaylandcompositor.qdocconf index 73331aa09..f520c98ba 100644 --- a/src/compositor/doc/qtwaylandcompositor.qdocconf +++ b/src/compositor/doc/qtwaylandcompositor.qdocconf @@ -29,7 +29,7 @@ qhp.QtWaylandCompositor.subprojects.examples.indexTitle = Qt Wayland Composi qhp.QtWaylandCompositor.subprojects.examples.selectors = fake:example qhp.QtWaylandCompositor.subprojects.examples.sortPages = true -depends += qtqml qtquick qtdoc qtquickcontrols qmake qtgui +depends += qtcore qtqml qtquick qtdoc qtquickcontrols qmake qtgui exampledirs += ../../../examples/wayland headerdirs += .. diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri index 9cb0bcfa1..7c53e5d43 100644 --- a/src/compositor/extensions/extensions.pri +++ b/src/compositor/extensions/extensions.pri @@ -2,7 +2,6 @@ CONFIG += wayland-scanner CONFIG += generated_privates WAYLANDSERVERSOURCES += \ - ../extensions/surface-extension.xml \ ../extensions/touch-extension.xml \ ../extensions/qtkey-extension.xml \ ../extensions/qt-windowmanager.xml \ @@ -12,7 +11,6 @@ WAYLANDSERVERSOURCES += \ ../3rdparty/protocol/ivi-application.xml \ HEADERS += \ - extensions/qwlextendedsurface_p.h \ extensions/qwlqttouch_p.h \ extensions/qwlqtkey_p.h \ extensions/qwaylandshell.h \ @@ -36,7 +34,6 @@ HEADERS += \ extensions/qwaylandivisurface_p.h \ SOURCES += \ - extensions/qwlextendedsurface.cpp \ extensions/qwlqttouch.cpp \ extensions/qwlqtkey.cpp \ extensions/qwaylandshell.cpp \ diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp index 4cdbb0a3a..c588c1063 100644 --- a/src/compositor/extensions/qwaylandwlshell.cpp +++ b/src/compositor/extensions/qwaylandwlshell.cpp @@ -104,8 +104,8 @@ void QWaylandWlShellPrivate::unregisterShellSurface(QWaylandWlShellSurface *shel QWaylandWlShellSurfacePrivate::QWaylandWlShellSurfacePrivate() : QWaylandCompositorExtensionPrivate() , wl_shell_surface() - , m_shell(Q_NULLPTR) - , m_surface(Q_NULLPTR) + , m_shell(nullptr) + , m_surface(nullptr) , m_windowType(Qt::WindowType::Window) { } @@ -195,7 +195,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_fullscreen(Resource *resou Q_Q(QWaylandWlShellSurface); QWaylandOutput *output = output_resource ? QWaylandOutput::fromResource(output_resource) - : Q_NULLPTR; + : nullptr; setWindowType(Qt::WindowType::Window); emit q->setFullScreen(QWaylandWlShellSurface::FullScreenMethod(method), framerate, output); } @@ -220,7 +220,7 @@ void QWaylandWlShellSurfacePrivate::shell_surface_set_maximized(Resource *resour Q_Q(QWaylandWlShellSurface); QWaylandOutput *output = output_resource ? QWaylandOutput::fromResource(output_resource) - : Q_NULLPTR; + : nullptr; setWindowType(Qt::WindowType::Window); emit q->setMaximized(output); } diff --git a/src/compositor/extensions/qwlextendedsurface.cpp b/src/compositor/extensions/qwlextendedsurface.cpp deleted file mode 100644 index b0850f0e2..000000000 --- a/src/compositor/extensions/qwlextendedsurface.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWaylandCompositor module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwlextendedsurface_p.h" - -#include <QtWaylandCompositor/QWaylandCompositor> - -QT_BEGIN_NAMESPACE - -namespace QtWayland { - -SurfaceExtensionGlobal::SurfaceExtensionGlobal(QWaylandCompositor *compositor) - : QWaylandCompositorExtensionTemplate(compositor) - , QtWaylandServer::qt_surface_extension(compositor->display(), 1) -{ -} - -void SurfaceExtensionGlobal::surface_extension_get_extended_surface(Resource *resource, - uint32_t id, - struct wl_resource *surface_resource) -{ - QWaylandSurface *surface = QWaylandSurface::fromResource(surface_resource); - ExtendedSurface *extSurface = new ExtendedSurface(resource->client(),id, wl_resource_get_version(resource->handle), surface); - emit extendedSurfaceReady(extSurface, surface); -} - -ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, int version, QWaylandSurface *surface) - : QWaylandCompositorExtensionTemplate(surface) - , QtWaylandServer::qt_extended_surface(client, id, version) - , m_surface(surface) - , m_windowFlags(0) -{ -} - -ExtendedSurface::~ExtendedSurface() -{ -} - -void ExtendedSurface::sendGenericProperty(const QString &name, const QVariant &variant) -{ - QByteArray byteValue; - QDataStream ds(&byteValue, QIODevice::WriteOnly); - ds << variant; - send_set_generic_property(name, byteValue); - -} - -void ExtendedSurface::sendOnScreenVisibilityChange(bool onScreen) -{ - setVisibility(onScreen ? QWindow::AutomaticVisibility : QWindow::Hidden); -} - -void ExtendedSurface::setVisibility(QWindow::Visibility visibility) -{ - send_onscreen_visibility(visibility); -} - -void ExtendedSurface::setParentSurface(QWaylandSurface *surface) -{ - m_surface = surface; -} - -void ExtendedSurface::extended_surface_update_generic_property(Resource *resource, - const QString &name, - struct wl_array *value) -{ - Q_UNUSED(resource); - QVariant variantValue; - QByteArray byteValue((const char*)value->data, value->size); - QDataStream ds(&byteValue, QIODevice::ReadOnly); - ds >> variantValue; - setWindowPropertyImpl(name,variantValue); -} - -Qt::ScreenOrientations ExtendedSurface::contentOrientationMask() const -{ - return m_contentOrientationMask; -} - -void ExtendedSurface::extended_surface_set_content_orientation_mask(Resource *resource, int32_t orientation) -{ - Q_UNUSED(resource); - Qt::ScreenOrientations mask = 0; - if (orientation & QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION) - mask |= Qt::PortraitOrientation; - if (orientation & QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION) - mask |= Qt::LandscapeOrientation; - if (orientation & QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION) - mask |= Qt::InvertedPortraitOrientation; - if (orientation & QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION) - mask |= Qt::InvertedLandscapeOrientation; - if (orientation & QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION) - mask |= Qt::PrimaryOrientation; - - Qt::ScreenOrientations oldMask = m_contentOrientationMask; - m_contentOrientationMask = mask; - - if (mask != oldMask) - emit contentOrientationMaskChanged(); -} - -QVariantMap ExtendedSurface::windowProperties() const -{ - return m_windowProperties; -} - -QVariant ExtendedSurface::windowProperty(const QString &propertyName) const -{ - QVariantMap props = m_windowProperties; - return props.value(propertyName); -} - -void ExtendedSurface::setWindowProperty(const QString &name, const QVariant &value) -{ - setWindowPropertyImpl(name,value); - sendGenericProperty(name, value); -} - -void ExtendedSurface::setWindowPropertyImpl(const QString &name, const QVariant &value) -{ - m_windowProperties.insert(name, value); - emit windowPropertyChanged(name,value); -} - -void ExtendedSurface::extended_surface_set_window_flags(Resource *resource, int32_t flags) -{ - Q_UNUSED(resource); - WindowFlags windowFlags(flags); - if (windowFlags == m_windowFlags) - return; - m_windowFlags = windowFlags; - emit windowFlagsChanged(); -} - -void ExtendedSurface::extended_surface_destroy_resource(Resource *) -{ - delete this; -} - -void ExtendedSurface::extended_surface_raise(Resource *) -{ - emit raiseRequested(); -} - -void ExtendedSurface::extended_surface_lower(Resource *) -{ - emit lowerRequested(); -} - -} - -QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwlextendedsurface_p.h b/src/compositor/extensions/qwlextendedsurface_p.h deleted file mode 100644 index 8ad89619a..000000000 --- a/src/compositor/extensions/qwlextendedsurface_p.h +++ /dev/null @@ -1,159 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWaylandCompositor module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** 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-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef WLEXTENDEDSURFACE_H -#define WLEXTENDEDSURFACE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <wayland-server.h> - -#include <QtWaylandCompositor/private/qwayland-server-surface-extension.h> -#include <QtWaylandCompositor/qwaylandsurface.h> -#include <QtWaylandCompositor/qwaylandcompositorextension.h> - -#include <QtCore/QVariant> -#include <QtCore/QLinkedList> -#include <QtGui/QWindow> - -QT_BEGIN_NAMESPACE - -class QWaylandCompositor; -class QWaylandSurface; - -namespace QtWayland { - -class ExtendedSurface; - -class Q_WAYLAND_COMPOSITOR_EXPORT SurfaceExtensionGlobal : public QWaylandCompositorExtensionTemplate<SurfaceExtensionGlobal>, public QtWaylandServer::qt_surface_extension -{ - Q_OBJECT -public: - SurfaceExtensionGlobal(QWaylandCompositor *compositor); - -Q_SIGNALS: - void extendedSurfaceReady(ExtendedSurface *extSurface, QWaylandSurface *surface); - -private: - void surface_extension_get_extended_surface(Resource *resource, - uint32_t id, - struct wl_resource *surface); - -}; - -class Q_WAYLAND_COMPOSITOR_EXPORT ExtendedSurface : public QWaylandCompositorExtensionTemplate<ExtendedSurface>, public QtWaylandServer::qt_extended_surface -{ - Q_OBJECT - Q_PROPERTY(Qt::ScreenOrientations contentOrientationMask READ contentOrientationMask NOTIFY contentOrientationMaskChanged) - Q_PROPERTY(WindowFlags windowFlags READ windowFlags NOTIFY windowFlagsChanged) - Q_FLAGS(WindowFlag WindowFlags) -public: - enum WindowFlag { - OverridesSystemGestures = 0x0001, - StaysOnTop = 0x0002, - BypassWindowManager = 0x0004 - }; - Q_DECLARE_FLAGS(WindowFlags, WindowFlag) - - ExtendedSurface(struct wl_client *client, uint32_t id, int version, QWaylandSurface *surface); - ~ExtendedSurface(); - - void sendGenericProperty(const QString &name, const QVariant &variant); - - void sendOnScreenVisibilityChange(bool onScreen); - void setVisibility(QWindow::Visibility visibility); - - void setParentSurface(QWaylandSurface *s); - - Qt::ScreenOrientations contentOrientationMask() const; - - WindowFlags windowFlags() const { return m_windowFlags; } - - QVariantMap windowProperties() const; - QVariant windowProperty(const QString &propertyName) const; - void setWindowProperty(const QString &name, const QVariant &value); - -Q_SIGNALS: - void contentOrientationMaskChanged(); - void windowFlagsChanged(); - void windowPropertyChanged(const QString &name, const QVariant &value); - void raiseRequested(); - void lowerRequested(); - -private: - void setWindowPropertyImpl(const QString &name, const QVariant &value); - - QWaylandSurface *m_surface; - - Qt::ScreenOrientations m_contentOrientationMask; - - WindowFlags m_windowFlags; - - QByteArray m_authenticationToken; - QVariantMap m_windowProperties; - - void extended_surface_update_generic_property(Resource *resource, - const QString &name, - struct wl_array *value) override; - - void extended_surface_set_content_orientation_mask(Resource *resource, - int32_t orientation) override; - - void extended_surface_set_window_flags(Resource *resource, - int32_t flags) override; - - void extended_surface_destroy_resource(Resource *) override; - void extended_surface_raise(Resource *) override; - void extended_surface_lower(Resource *) override; -}; - -} - -QT_END_NAMESPACE - -#endif // WLEXTENDEDSURFACE_H diff --git a/src/compositor/global/qwaylandcompositorextension.cpp b/src/compositor/global/qwaylandcompositorextension.cpp index 7b44dbde6..ee117bbae 100644 --- a/src/compositor/global/qwaylandcompositorextension.cpp +++ b/src/compositor/global/qwaylandcompositorextension.cpp @@ -146,7 +146,7 @@ QWaylandObject::QWaylandObject(QObjectPrivate &d, QObject *parent) QWaylandObject::~QWaylandObject() { foreach (QWaylandCompositorExtension *extension, extension_vector) - QWaylandCompositorExtensionPrivate::get(extension)->extension_container = Q_NULLPTR; + QWaylandCompositorExtensionPrivate::get(extension)->extension_container = nullptr; } QWaylandCompositorExtension *QWaylandObject::extension(const QByteArray &name) @@ -155,7 +155,7 @@ QWaylandCompositorExtension *QWaylandObject::extension(const QByteArray &name) if (extension_vector.at(i)->extensionInterface()->name == name) return extension_vector.at(i); } - return Q_NULLPTR; + return nullptr; } QWaylandCompositorExtension *QWaylandObject::extension(const wl_interface *interface) @@ -164,7 +164,7 @@ QWaylandCompositorExtension *QWaylandObject::extension(const wl_interface *inter if (extension_vector.at(i)->extensionInterface() == interface) return extension_vector.at(i); } - return Q_NULLPTR; + return nullptr; } QList<QWaylandCompositorExtension *> QWaylandObject::extensions() const diff --git a/src/compositor/global/qwaylandcompositorextension.h b/src/compositor/global/qwaylandcompositorextension.h index 73f8aab36..48fce0c96 100644 --- a/src/compositor/global/qwaylandcompositorextension.h +++ b/src/compositor/global/qwaylandcompositorextension.h @@ -114,7 +114,7 @@ public: static T *findIn(QWaylandObject *container) { - if (!container) return Q_NULLPTR; + if (!container) return nullptr; return qobject_cast<T *>(container->extension(T::interfaceName())); } diff --git a/src/compositor/global/qwaylandcompositorextension_p.h b/src/compositor/global/qwaylandcompositorextension_p.h index 56889cfab..68f817aa6 100644 --- a/src/compositor/global/qwaylandcompositorextension_p.h +++ b/src/compositor/global/qwaylandcompositorextension_p.h @@ -64,7 +64,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandCompositorExtensionPrivate : public QO public: QWaylandCompositorExtensionPrivate() : QObjectPrivate() - , extension_container(Q_NULLPTR) + , extension_container(nullptr) , initialized(false) { } diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp index 771b4b2e4..8a1009fa8 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp @@ -162,7 +162,7 @@ void *QWaylandEglClientBufferIntegration::nativeResource(NativeResource resource default: break; } - return Q_NULLPTR; + return nullptr; } void *QWaylandEglClientBufferIntegration::nativeResourceForContext(NativeResource resource, QPlatformOpenGLContext *context) @@ -178,7 +178,7 @@ void *QWaylandEglClientBufferIntegration::nativeResourceForContext(NativeResourc default: break; } - return Q_NULLPTR; + return nullptr; } EGLDisplay QWaylandEglClientBufferIntegration::eglDisplay() const diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 6b5c53263..87f3e2d4e 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -92,6 +92,11 @@ QWaylandWindow::WindowType QWaylandEglWindow::windowType() const return QWaylandWindow::Egl; } +void QWaylandEglWindow::ensureSize() +{ + updateSurface(false); +} + void QWaylandEglWindow::setGeometry(const QRect &rect) { QWaylandWindow::setGeometry(rect); diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h index e471a8f7c..77aee56dc 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h @@ -59,6 +59,7 @@ public: QWaylandEglWindow(QWindow *window); ~QWaylandEglWindow(); WindowType windowType() const override; + void ensureSize() override; void updateSurface(bool create); virtual void setGeometry(const QRect &rect) override; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index f4dd6f492..967028861 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -327,7 +327,7 @@ void QWaylandGLContext::updateGLFormat() EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); - wl_surface *wlSurface = m_display->createSurface(Q_NULLPTR); + wl_surface *wlSurface = m_display->createSurface(nullptr); wl_egl_window *eglWindow = wl_egl_window_create(wlSurface, 1, 1); EGLSurface eglSurface = eglCreateWindowSurface(m_eglDisplay, m_config, eglWindow, 0); diff --git a/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp index 7a86785b0..1dd037adc 100644 --- a/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp +++ b/src/hardwareintegration/compositor/shm-emulation-server/shmserverbufferintegration.cpp @@ -70,7 +70,7 @@ ShmServerBuffer::ShmServerBuffer(ShmServerBufferIntegration *integration, const QString key = "qt_shm_emulation_" + QString::number(qimage.cacheKey()); m_shm = new QSharedMemory(key); - int shm_size = qimage.byteCount(); + qsizetype shm_size = qimage.sizeInBytes(); bool ok = m_shm->create(shm_size) && m_shm->lock(); if (ok) { memcpy(m_shm->data(), qimage.constBits(), shm_size); diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index f5e63aec5..fdaddb6ab 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -223,7 +223,7 @@ WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPriva , egl_create_image(0) , egl_destroy_image(0) , gl_egl_image_target_texture_2d(0) - , funcs(Q_NULLPTR) + , funcs(nullptr) { } diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp index 502b17c0d..fee812501 100644 --- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp +++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp @@ -55,8 +55,8 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { QWaylandIviShellIntegration::QWaylandIviShellIntegration() - : m_iviApplication(Q_NULLPTR) - , m_iviController(Q_NULLPTR) + : m_iviApplication(nullptr) + , m_iviController(nullptr) , m_lastSurfaceId(0) , m_surfaceNumber(0) , m_useEnvSurfaceId(false) @@ -129,11 +129,11 @@ uint32_t QWaylandIviShellIntegration::getNextUniqueSurfaceId() QWaylandShellSurface *QWaylandIviShellIntegration::createShellSurface(QWaylandWindow *window) { if (!m_iviApplication) - return Q_NULLPTR; + return nullptr; uint32_t surfaceId = getNextUniqueSurfaceId(); if (surfaceId == 0) - return Q_NULLPTR; + return nullptr; struct ivi_surface *surface = m_iviApplication->surface_create(surfaceId, window->object()); if (!m_iviController) diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp index a16518cc3..335aa852c 100644 --- a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp +++ b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp @@ -52,7 +52,7 @@ QWaylandIviSurface::QWaylandIviSurface(struct ::ivi_surface *ivi_surface, QWayla : QtWayland::ivi_surface(ivi_surface) , QWaylandShellSurface(window) , m_window(window) - , m_extendedWindow(Q_NULLPTR) + , m_extendedWindow(nullptr) { createExtendedSurface(window); } @@ -63,7 +63,7 @@ QWaylandIviSurface::QWaylandIviSurface(struct ::ivi_surface *ivi_surface, QWayla , QWaylandShellSurface(window) , QtWayland::ivi_controller_surface(iviControllerSurface) , m_window(window) - , m_extendedWindow(Q_NULLPTR) + , m_extendedWindow(nullptr) { createExtendedSurface(window); } diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp index ed36a1386..d6a83dbbc 100644 --- a/src/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/qtwaylandscanner/qtwaylandscanner.cpp @@ -504,6 +504,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" private:\n"); printf(" static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n"); printf(" static void destroy_func(struct ::wl_resource *client_resource);\n"); + printf(" static void display_destroy_func(struct ::wl_listener *listener, void *data);\n"); printf("\n"); printf(" Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n"); printf(" Resource *bind(struct ::wl_resource *handle);\n"); @@ -527,6 +528,10 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" Resource *m_resource;\n"); printf(" struct ::wl_global *m_global;\n"); printf(" uint32_t m_globalVersion;\n"); + printf(" struct DisplayDestroyedListener : ::wl_listener {\n"); + printf(" %s *parent;\n", interfaceName); + printf(" };\n"); + printf(" DisplayDestroyedListener m_displayDestroyedListener;\n"); printf(" };\n"); if (j < interfaces.size() - 1) @@ -607,6 +612,13 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" %s::~%s()\n", interfaceName, interfaceName); printf(" {\n"); + printf(" for (auto resource : qAsConst(m_resource_map))\n"); + printf(" wl_resource_set_implementation(resource->handle, nullptr, nullptr, nullptr);\n"); + printf("\n"); + printf(" if (m_global) {\n"); + printf(" wl_global_destroy(m_global);\n"); + printf(" wl_list_remove(&m_displayDestroyedListener.link);\n"); + printf(" }\n"); printf(" }\n"); printf("\n"); @@ -642,6 +654,9 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" {\n"); printf(" m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName); printf(" m_globalVersion = version;\n"); + printf(" m_displayDestroyedListener.notify = %s::display_destroy_func;\n", interfaceName); + printf(" m_displayDestroyedListener.parent = this;\n"); + printf(" wl_display_add_destroy_listener(display, &m_displayDestroyedListener);\n"); printf(" }\n"); printf("\n"); @@ -674,6 +689,14 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" }\n"); printf("\n"); + printf(" void %s::display_destroy_func(struct ::wl_listener *listener, void *data)\n", interfaceName); + printf(" {\n"); + printf(" Q_UNUSED(data);\n"); + printf(" %s *that = static_cast<%s::DisplayDestroyedListener *>(listener)->parent;\n", interfaceName, interfaceName); + printf(" that->m_global = nullptr;\n"); + printf(" }\n"); + printf("\n"); + printf(" void %s::destroy_func(struct ::wl_resource *client_resource)\n", interfaceName); printf(" {\n"); printf(" Resource *resource = Resource::fromResource(client_resource);\n"); diff --git a/tests/auto/client/client.pro b/tests/auto/client/client.pro index 916b3abe4..d19326797 100644 --- a/tests/auto/client/client.pro +++ b/tests/auto/client/client.pro @@ -1,3 +1,5 @@ TEMPLATE=subdirs -SUBDIRS += client +SUBDIRS += \ + client \ + xdgshellv6 diff --git a/tests/auto/client/client/client.pro b/tests/auto/client/client/client.pro index e6e607c3f..edf80bb9b 100644 --- a/tests/auto/client/client/client.pro +++ b/tests/auto/client/client/client.pro @@ -1,24 +1,4 @@ -CONFIG += testcase link_pkgconfig -TARGET = tst_client - -QT += testlib -QT += core-private gui-private waylandclient-private - -QMAKE_USE += wayland-client wayland-server +include (../shared/shared.pri) -CONFIG += wayland-scanner -WAYLANDSERVERSOURCES += \ - ../../../../src/3rdparty/protocol/wayland.xml - -SOURCES += \ - tst_client.cpp \ - mockcompositor.cpp \ - mockinput.cpp \ - mockshell.cpp \ - mocksurface.cpp \ - mockoutput.cpp - -HEADERS += \ - mockcompositor.h \ - mockinput.h \ - mocksurface.h +TARGET = tst_client +SOURCES += tst_client.cpp diff --git a/tests/auto/client/client/tst_client.cpp b/tests/auto/client/client/tst_client.cpp index aed601d8a..94198b457 100644 --- a/tests/auto/client/client/tst_client.cpp +++ b/tests/auto/client/client/tst_client.cpp @@ -97,6 +97,7 @@ public: void touchEvent(QTouchEvent *event) override { + Q_UNUSED(event); ++touchEventCount; } @@ -161,7 +162,10 @@ public slots: } private slots: - void screen(); + void primaryScreen(); + void screens(); + void windowScreens(); + void removePrimaryScreen(); void createDestroyWindow(); void events(); void backingStore(); @@ -176,11 +180,96 @@ private: MockCompositor *compositor; }; -void tst_WaylandClient::screen() +void tst_WaylandClient::primaryScreen() { + compositor->setOutputMode(screenSize); QTRY_COMPARE(QGuiApplication::primaryScreen()->size(), screenSize); } +void tst_WaylandClient::screens() +{ + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + compositor->sendAddOutput(); + QTRY_COMPARE(QGuiApplication::screens().size(), 2); + QSharedPointer<MockOutput> secondOutput; + QTRY_VERIFY(secondOutput = compositor->output(1)); + compositor->sendRemoveOutput(secondOutput); + QTRY_COMPARE(QGuiApplication::screens().size(), 1); +} + +void tst_WaylandClient::windowScreens() +{ + QSharedPointer<MockOutput> firstOutput; + QTRY_VERIFY(firstOutput = compositor->output()); + + TestWindow window; + window.show(); + + QSharedPointer<MockSurface> surface; + QTRY_VERIFY(surface = compositor->surface()); + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + QScreen *primaryScreen = QGuiApplication::screens().first(); + QCOMPARE(window.screen(), primaryScreen); + + compositor->sendAddOutput(); + + QTRY_COMPARE(QGuiApplication::screens().size(), 2); + QScreen *secondaryScreen = QGuiApplication::screens().at(1); + QVERIFY(secondaryScreen); + + window.setScreen(secondaryScreen); + QCOMPARE(window.screen(), secondaryScreen); + + QSharedPointer<MockOutput> secondOutput; + QTRY_VERIFY(secondOutput = compositor->output(1)); + compositor->sendSurfaceEnter(surface, firstOutput); + + compositor->sendSurfaceEnter(surface, secondOutput); + QTRY_COMPARE(window.screen(), primaryScreen); + + compositor->sendSurfaceLeave(surface, firstOutput); + QTRY_COMPARE(window.screen(), secondaryScreen); + + compositor->sendRemoveOutput(secondOutput); + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + QCOMPARE(window.screen(), primaryScreen); + + window.destroy(); + QTRY_VERIFY(!compositor->surface()); +} + +void tst_WaylandClient::removePrimaryScreen() +{ + QSharedPointer<MockOutput> firstOutput; + QTRY_VERIFY(firstOutput = compositor->output()); + + TestWindow window; + window.show(); + + QSharedPointer<MockSurface> surface; + QTRY_VERIFY(surface = compositor->surface()); + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + QScreen *primaryScreen = QGuiApplication::screens().first(); + QCOMPARE(window.screen(), primaryScreen); + + compositor->sendAddOutput(); + + QTRY_COMPARE(QGuiApplication::screens().size(), 2); + QScreen *secondaryScreen = QGuiApplication::screens().at(1); + QVERIFY(secondaryScreen); + + compositor->sendRemoveOutput(firstOutput); + QTRY_COMPARE(QGuiApplication::screens().size(), 1); + + compositor->sendMousePress(surface, window.frameOffset() + QPoint(10, 10)); + QTRY_COMPARE(window.mousePressEventCount, 1); + compositor->sendMouseRelease(surface); + QTRY_COMPARE(window.mouseReleaseEventCount, 1); + + window.destroy(); + QTRY_VERIFY(!compositor->surface()); +} + void tst_WaylandClient::createDestroyWindow() { TestWindow window; @@ -301,6 +390,7 @@ public: protected: void mousePressEvent(QMouseEvent *event) override { + Q_UNUSED(event); if (dragStarted) return; dragStarted = true; @@ -452,7 +542,7 @@ int main(int argc, char **argv) setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin MockCompositor compositor; - compositor.setOutputGeometry(QRect(QPoint(), screenSize)); + compositor.setOutputMode(screenSize); QGuiApplication app(argc, argv); diff --git a/tests/auto/client/client/mockcompositor.cpp b/tests/auto/client/shared/mockcompositor.cpp index 2c5f2541f..e7c6e90d2 100644 --- a/tests/auto/client/client/mockcompositor.cpp +++ b/tests/auto/client/shared/mockcompositor.cpp @@ -28,8 +28,11 @@ #include "mockcompositor.h" #include "mockinput.h" +#include "mockoutput.h" #include "mocksurface.h" +#include <wayland-xdg-shell-unstable-v6-server-protocol.h> + #include <stdio.h> MockCompositor::MockCompositor() : m_alive(true) @@ -75,10 +78,10 @@ void MockCompositor::processWaylandEvents() m_waitCondition.wakeOne(); } -void MockCompositor::setOutputGeometry(const QRect &rect) +void MockCompositor::setOutputMode(const QSize &size) { - Command command = makeCommand(Impl::Compositor::setOutputGeometry, m_compositor); - command.parameters << rect; + Command command = makeCommand(Impl::Compositor::setOutputMode, m_compositor); + command.parameters << size; processCommand(command); } @@ -180,6 +183,35 @@ void MockCompositor::sendDataDeviceLeave(const QSharedPointer<MockSurface> &surf processCommand(command); } +void MockCompositor::sendAddOutput() +{ + Command command = makeCommand(Impl::Compositor::sendAddOutput, m_compositor); + processCommand(command); +} + +void MockCompositor::sendRemoveOutput(const QSharedPointer<MockOutput> &output) +{ + Command command = makeCommand(Impl::Compositor::sendRemoveOutput, m_compositor); + command.parameters << QVariant::fromValue(output); + processCommand(command); +} + +void MockCompositor::sendSurfaceEnter(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output) +{ + Command command = makeCommand(Impl::Compositor::sendSurfaceEnter, m_compositor); + command.parameters << QVariant::fromValue(surface); + command.parameters << QVariant::fromValue(output); + processCommand(command); +} + +void MockCompositor::sendSurfaceLeave(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output) +{ + Command command = makeCommand(Impl::Compositor::sendSurfaceLeave, m_compositor); + command.parameters << QVariant::fromValue(surface); + command.parameters << QVariant::fromValue(output); + processCommand(command); +} + void MockCompositor::waitForStartDrag() { Command command = makeCommand(Impl::Compositor::waitForStartDrag, m_compositor); @@ -202,6 +234,15 @@ QSharedPointer<MockSurface> MockCompositor::surface() return result; } +QSharedPointer<MockOutput> MockCompositor::output(int index) +{ + QSharedPointer<MockOutput> result; + lock(); + result = m_compositor->outputs().at(index)->mockOutput(); + unlock(); + return result; +} + MockCompositor::Command MockCompositor::makeCommand(Command::Callback callback, void *target) { Command command; @@ -264,11 +305,7 @@ namespace Impl { Compositor::Compositor() : m_display(wl_display_create()) - , m_startDragSeen(false) - , m_time(0) { - wl_list_init(&m_outputResources); - if (wl_display_add_socket(m_display, 0)) { fprintf(stderr, "Fatal: Failed to open server socket\n"); exit(EXIT_FAILURE); @@ -285,8 +322,9 @@ Compositor::Compositor() m_keyboard = m_seat->keyboard(); m_touch = m_seat->touch(); - wl_global_create(m_display, &wl_output_interface, 1, this, bindOutput); + m_outputs.append(new Output(m_display, QSize(1920, 1080), QPoint(0, 0))); wl_global_create(m_display, &wl_shell_interface, 1, this, bindShell); + wl_global_create(m_display, &zxdg_shell_v6_interface, 1, this, bindXdgShellV6); m_loop = wl_display_get_event_loop(m_display); m_fd = wl_event_loop_get_fd(m_loop); @@ -349,6 +387,11 @@ QVector<Surface *> Compositor::surfaces() const return m_surfaces; } +QVector<Output *> Compositor::outputs() const +{ + return m_outputs; +} + uint32_t Compositor::nextSerial() { return wl_display_next_serial(m_display); @@ -366,5 +409,17 @@ void Compositor::removeSurface(Surface *surface) m_pointer->handleSurfaceDestroyed(surface); } +Surface *Compositor::resolveSurface(const QVariant &v) +{ + QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >(); + return mockSurface ? mockSurface->handle() : nullptr; +} + +Output *Compositor::resolveOutput(const QVariant &v) +{ + QSharedPointer<MockOutput> mockOutput = v.value<QSharedPointer<MockOutput> >(); + return mockOutput ? mockOutput->handle() : nullptr; +} + } diff --git a/tests/auto/client/client/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h index dd6450fc9..9258b1926 100644 --- a/tests/auto/client/client/mockcompositor.h +++ b/tests/auto/client/shared/mockcompositor.h @@ -51,6 +51,7 @@ class Touch; class Seat; class DataDeviceManager; class Surface; +class Output; class Compositor { @@ -64,9 +65,8 @@ public: uint32_t nextSerial(); uint32_t time() { return ++m_time; } - static void setOutputGeometry(void *compositor, const QList<QVariant> ¶meters); - QVector<Surface *> surfaces() const; + QVector<Output *> outputs() const; void addSurface(Surface *surface); void removeSurface(Surface *surface); @@ -86,36 +86,40 @@ public: static void sendDataDeviceDrop(void *data, const QList<QVariant> ¶meters); static void sendDataDeviceLeave(void *data, const QList<QVariant> ¶meters); static void waitForStartDrag(void *data, const QList<QVariant> ¶meters); + static void setOutputMode(void *compositor, const QList<QVariant> ¶meters); + static void sendAddOutput(void *data, const QList<QVariant> ¶meters); + static void sendRemoveOutput(void *data, const QList<QVariant> ¶meters); + static void sendSurfaceEnter(void *data, const QList<QVariant> ¶meters); + static void sendSurfaceLeave(void *data, const QList<QVariant> ¶meters); public: - bool m_startDragSeen; + bool m_startDragSeen = false; private: static void bindCompositor(wl_client *client, void *data, uint32_t version, uint32_t id); - static void bindOutput(wl_client *client, void *data, uint32_t version, uint32_t id); static void bindShell(wl_client *client, void *data, uint32_t version, uint32_t id); + static void bindXdgShellV6(wl_client *client, void *compositorData, uint32_t version, uint32_t id); + static Surface *resolveSurface(const QVariant &v); + static Output *resolveOutput(const QVariant &v); void initShm(); - void sendOutputGeometry(wl_resource *resource); - void sendOutputMode(wl_resource *resource); - QRect m_outputGeometry; - wl_display *m_display; - wl_event_loop *m_loop; - wl_shm *m_shm; - int m_fd; + wl_display *m_display = nullptr; + wl_event_loop *m_loop = nullptr; + wl_shm *m_shm = nullptr; + int m_fd = -1; - wl_list m_outputResources; - uint32_t m_time; + uint32_t m_time = 0; QScopedPointer<Seat> m_seat; - Pointer *m_pointer; - Keyboard *m_keyboard; - Touch *m_touch; + Pointer *m_pointer = nullptr; + Keyboard *m_keyboard = nullptr; + Touch *m_touch = nullptr; QScopedPointer<DataDeviceManager> m_data_device_manager; QVector<Surface *> m_surfaces; + QVector<Output *> m_outputs; }; void registerResource(wl_list *list, wl_resource *resource); @@ -139,6 +143,16 @@ private: Q_DECLARE_METATYPE(QSharedPointer<MockSurface>) +class MockOutput { +public: + Impl::Output *handle() const { return m_output; } + MockOutput(Impl::Output *output); +private: + Impl::Output *m_output; +}; + +Q_DECLARE_METATYPE(QSharedPointer<MockOutput>) + class MockCompositor { public: @@ -150,7 +164,7 @@ public: int waylandFileDescriptor() const; void processWaylandEvents(); - void setOutputGeometry(const QRect &rect); + void setOutputMode(const QSize &size); void setKeyboardFocus(const QSharedPointer<MockSurface> &surface); void sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos); void sendMouseRelease(const QSharedPointer<MockSurface> &surface); @@ -165,9 +179,14 @@ public: void sendDataDeviceMotion(const QPoint &position); void sendDataDeviceDrop(const QSharedPointer<MockSurface> &surface); void sendDataDeviceLeave(const QSharedPointer<MockSurface> &surface); + void sendAddOutput(); + void sendRemoveOutput(const QSharedPointer<MockOutput> &output); + void sendSurfaceEnter(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output); + void sendSurfaceLeave(const QSharedPointer<MockSurface> &surface, QSharedPointer<MockOutput> &output); void waitForStartDrag(); QSharedPointer<MockSurface> surface(); + QSharedPointer<MockOutput> output(int index = 0); void lock(); void unlock(); diff --git a/tests/auto/client/client/mockinput.cpp b/tests/auto/client/shared/mockinput.cpp index b2bcdf2e6..9cea85b6d 100644 --- a/tests/auto/client/client/mockinput.cpp +++ b/tests/auto/client/shared/mockinput.cpp @@ -32,12 +32,6 @@ namespace Impl { -static Surface *resolveSurface(const QVariant &v) -{ - QSharedPointer<MockSurface> mockSurface = v.value<QSharedPointer<MockSurface> >(); - return mockSurface ? mockSurface->handle() : 0; -} - void Compositor::setKeyboardFocus(void *data, const QList<QVariant> ¶meters) { Compositor *compositor = static_cast<Compositor *>(data); @@ -194,6 +188,7 @@ void Compositor::sendDataDeviceLeave(void *data, const QList<QVariant> ¶mete void Compositor::waitForStartDrag(void *data, const QList<QVariant> ¶meters) { + Q_UNUSED(parameters); Compositor *compositor = static_cast<Compositor *>(data); Q_ASSERT(compositor); while (!compositor->m_startDragSeen) { @@ -239,8 +234,8 @@ void Seat::seat_get_touch(Resource *resource, uint32_t id) Keyboard::Keyboard(Compositor *compositor) : wl_keyboard() , m_compositor(compositor) - , m_focusResource(Q_NULLPTR) - , m_focus(Q_NULLPTR) + , m_focusResource(nullptr) + , m_focus(nullptr) { } @@ -293,8 +288,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) + , m_focusResource(nullptr) + , m_focus(nullptr) { } @@ -447,6 +442,11 @@ DataDevice::~DataDevice() void DataDevice::data_device_start_drag(QtWaylandServer::wl_data_device::Resource *resource, wl_resource *source, wl_resource *origin, wl_resource *icon, uint32_t serial) { + Q_UNUSED(resource); + Q_UNUSED(source); + Q_UNUSED(origin); + Q_UNUSED(icon); + Q_UNUSED(serial); m_compositor->m_startDragSeen = true; } @@ -469,6 +469,7 @@ DataDevice *DataDeviceManager::dataDevice() const void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, uint32_t id, struct ::wl_resource *seat) { + Q_UNUSED(seat); if (!m_data_device) m_data_device.reset(new DataDevice(m_compositor)); m_data_device->add(resource->client(), id, 1); diff --git a/tests/auto/client/client/mockinput.h b/tests/auto/client/shared/mockinput.h index 9c217b6ac..9c217b6ac 100644 --- a/tests/auto/client/client/mockinput.h +++ b/tests/auto/client/shared/mockinput.h diff --git a/tests/auto/client/shared/mockoutput.cpp b/tests/auto/client/shared/mockoutput.cpp new file mode 100644 index 000000000..7d7b7413a --- /dev/null +++ b/tests/auto/client/shared/mockoutput.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2016 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 "mockcompositor.h" +#include "mockoutput.h" + +#include <QDebug> + +namespace Impl { + +void Compositor::sendAddOutput(void *data, const QList<QVariant> ¶meters) { + Q_UNUSED(parameters); + Compositor *compositor = static_cast<Compositor *>(data); + auto output = new Output(compositor->m_display, QSize(1920, 1200), QPoint(0, 0)); + compositor->m_outputs.append(output); + + // Wait for the client to bind to the output + while (output->resourceMap().isEmpty()) + compositor->dispatchEvents(); +} + +void Compositor::sendRemoveOutput(void *data, const QList<QVariant> ¶meters) { + Compositor *compositor = static_cast<Compositor *>(data); + Q_ASSERT(compositor); + Output *output = resolveOutput(parameters.first()); + Q_ASSERT(output); + bool wasRemoved = compositor->m_outputs.removeOne(output); + Q_ASSERT(wasRemoved); + delete output; +} + +void Compositor::setOutputMode(void *data, const QList<QVariant> ¶meters) +{ + Compositor *compositor = static_cast<Compositor *>(data); + QSize size = parameters.first().toSize(); + Output *output = compositor->m_outputs.first(); + Q_ASSERT(output); + output->setCurrentMode(size); +} + +Output::Output(wl_display *display, const QSize &resolution, const QPoint &position) + : wl_output(display, 2) + , m_size(resolution) + , m_position(position) + , m_physicalSize(520, 320) + , m_mockOutput(new MockOutput(this)) +{ +} + +void Output::setCurrentMode(const QSize &size) +{ + qDebug() << Q_FUNC_INFO << size; + m_size = size; + for (Resource *resource : resourceMap()) + sendCurrentMode(resource); +} + +void Output::output_bind_resource(QtWaylandServer::wl_output::Resource *resource) +{ + sendGeometry(resource); + sendCurrentMode(resource); +} + +void Output::sendGeometry(Resource *resource) +{ + const int subPixel = 0; + const int transform = 0; + + send_geometry(resource->handle, + m_position.x(), m_position.y(), + m_physicalSize.width(), m_physicalSize.height(), + subPixel, "", "", transform ); +} + +void Output::sendCurrentMode(Resource *resource) +{ + send_mode(resource->handle, + WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, + m_size.width(), m_size.height(), 60000); +} + +} // Impl + +MockOutput::MockOutput(Impl::Output *output) + : m_output(output) +{ +} diff --git a/tests/auto/client/client/mockoutput.cpp b/tests/auto/client/shared/mockoutput.h index 86561976f..d5a2bb56b 100644 --- a/tests/auto/client/client/mockoutput.cpp +++ b/tests/auto/client/shared/mockoutput.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** 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. @@ -26,42 +26,37 @@ ** ****************************************************************************/ -#include "mockcompositor.h" +#ifndef MOCKOUTPUT_H +#define MOCKOUTPUT_H -namespace Impl { +#include <qglobal.h> -void Compositor::bindOutput(wl_client *client, void *compositorData, uint32_t version, uint32_t id) -{ - wl_resource *resource = wl_resource_create(client, &wl_output_interface, static_cast<int>(version), id); +#include "qwayland-server-wayland.h" - Compositor *compositor = static_cast<Compositor *>(compositorData); - registerResource(&compositor->m_outputResources, resource); +#include "mockcompositor.h" - compositor->sendOutputGeometry(resource); - compositor->sendOutputMode(resource); -} +namespace Impl { -void Compositor::sendOutputGeometry(wl_resource *resource) +class Output : public QtWaylandServer::wl_output { - const QRect &r = m_outputGeometry; - wl_output_send_geometry(resource, r.x(), r.y(), r.width(), r.height(), 0, "", "",0); -} +public: + Output(::wl_display *display, const QSize &resolution, const QPoint &position); -void Compositor::sendOutputMode(wl_resource *resource) -{ - const QRect &r = m_outputGeometry; - wl_output_send_mode(resource, WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED, r.width(), r.height(), 60); -} + QSharedPointer<MockOutput> mockOutput() const { return m_mockOutput; } + void setCurrentMode(const QSize &size); -void Compositor::setOutputGeometry(void *c, const QList<QVariant> ¶meters) -{ - Compositor *compositor = static_cast<Compositor *>(c); - compositor->m_outputGeometry = parameters.first().toRect(); +protected: + void output_bind_resource(Resource *resource) override; - wl_resource *resource; - wl_list_for_each(resource, &compositor->m_outputResources, link) - compositor->sendOutputGeometry(resource); -} +private: + void sendGeometry(Resource *resource); + void sendCurrentMode(Resource *resource); + QSize m_size; + QPoint m_position; + const QSize m_physicalSize; + QSharedPointer<MockOutput> m_mockOutput; +}; } +#endif // MOCKOUTPUT_H diff --git a/tests/auto/client/client/mockshell.cpp b/tests/auto/client/shared/mockshell.cpp index d5eede22e..d5eede22e 100644 --- a/tests/auto/client/client/mockshell.cpp +++ b/tests/auto/client/shared/mockshell.cpp diff --git a/tests/auto/client/client/mocksurface.cpp b/tests/auto/client/shared/mocksurface.cpp index 55712af11..7aa2a00b2 100644 --- a/tests/auto/client/client/mocksurface.cpp +++ b/tests/auto/client/shared/mocksurface.cpp @@ -27,13 +27,42 @@ ****************************************************************************/ #include "mocksurface.h" +#include "mockoutput.h" #include "mockcompositor.h" namespace Impl { +void Compositor::sendSurfaceEnter(void *data, const QList<QVariant> ¶meters) +{ + Q_UNUSED(data); + Surface *surface = resolveSurface(parameters.at(0)); + Output *output = resolveOutput(parameters.at(1)); + Q_ASSERT(surface && surface->resource()); + Q_ASSERT(output); + auto outputResources = output->resourceMap().values(surface->resource()->client()); + Q_ASSERT(!outputResources.isEmpty()); + + for (auto outputResource : outputResources) + surface->send_enter(outputResource->handle); +} + +void Compositor::sendSurfaceLeave(void *data, const QList<QVariant> ¶meters) +{ + Q_UNUSED(data); + Surface *surface = resolveSurface(parameters.at(0)); + Output *output = resolveOutput(parameters.at(1)); + Q_ASSERT(surface && surface->resource()); + Q_ASSERT(output); + auto outputResources = output->resourceMap().values(surface->resource()->client()); + Q_ASSERT(!outputResources.isEmpty()); + + for (auto outputResource : outputResources) + surface->send_leave(outputResource->handle); +} + Surface::Surface(wl_client *client, uint32_t id, int v, Compositor *compositor) : QtWaylandServer::wl_surface(client, id, v) - , m_buffer(Q_NULLPTR) + , m_buffer(nullptr) , m_compositor(compositor) , m_mockSurface(new MockSurface(this)) , m_mapped(false) diff --git a/tests/auto/client/client/mocksurface.h b/tests/auto/client/shared/mocksurface.h index 5155599bb..5155599bb 100644 --- a/tests/auto/client/client/mocksurface.h +++ b/tests/auto/client/shared/mocksurface.h diff --git a/tests/auto/client/shared/mockxdgshellv6.cpp b/tests/auto/client/shared/mockxdgshellv6.cpp new file mode 100644 index 000000000..fe9d11857 --- /dev/null +++ b/tests/auto/client/shared/mockxdgshellv6.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 "mockcompositor.h" +#include "mocksurface.h" + +#include <qwayland-server-xdg-shell-unstable-v6.h> + +namespace Impl { + +class XdgToplevelV6 : public QtWaylandServer::zxdg_toplevel_v6 +{ +public: + XdgToplevelV6(wl_client *client, uint32_t id, int version) + : QtWaylandServer::zxdg_toplevel_v6(client, id, version) + {} + void zxdg_toplevel_v6_destroy_resource(Resource *resource) override { delete this; } +}; + +class XdgSurfaceV6 : public QtWaylandServer::zxdg_surface_v6 +{ +public: + XdgSurfaceV6(wl_client *client, uint32_t id, int version, Surface *surface); + void zxdg_surface_v6_destroy_resource(Resource *resource) override { delete this; } + void zxdg_surface_v6_get_toplevel(Resource *resource, uint32_t id) override; + Surface *m_surface = nullptr; +}; + +XdgSurfaceV6::XdgSurfaceV6(wl_client *client, uint32_t id, int version, Surface *surface) + : QtWaylandServer::zxdg_surface_v6(client, id, version) + , m_surface(surface) +{ +} + +void XdgSurfaceV6::zxdg_surface_v6_get_toplevel(QtWaylandServer::zxdg_surface_v6::Resource *resource, uint32_t id) +{ + int version = wl_resource_get_version(resource->handle); + new XdgToplevelV6(resource->client(), id, version); + m_surface->map(); +} + + +void shell_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + Q_UNUSED(client); + Q_UNUSED(resource); +} + +void create_positioner(struct wl_client *client, + struct wl_resource *resource, + uint32_t id) +{ + Q_UNUSED(client); + Q_UNUSED(resource); + Q_UNUSED(id); +} + +void get_xdg_surface(struct wl_client *client, + struct wl_resource *compositorResource, + uint32_t id, + struct wl_resource *surfaceResource) +{ + int version = wl_resource_get_version(compositorResource); + new XdgSurfaceV6(client, id, version, Surface::fromResource(surfaceResource)); +} + +void pong(struct wl_client *client, + struct wl_resource *resource, + uint32_t serial) +{ + Q_UNUSED(client); + Q_UNUSED(resource); + Q_UNUSED(serial); +} + +void Compositor::bindXdgShellV6(wl_client *client, void *compositorData, uint32_t version, uint32_t id) +{ + static const struct zxdg_shell_v6_interface shellInterface = { + shell_destroy, + create_positioner, + get_xdg_surface, + pong + }; + + wl_resource *resource = wl_resource_create(client, &zxdg_shell_v6_interface, static_cast<int>(version), id); + wl_resource_set_implementation(resource, &shellInterface, compositorData, nullptr); +} + +} diff --git a/tests/auto/client/shared/shared.pri b/tests/auto/client/shared/shared.pri new file mode 100644 index 000000000..608664bb7 --- /dev/null +++ b/tests/auto/client/shared/shared.pri @@ -0,0 +1,26 @@ +CONFIG += testcase link_pkgconfig +QT += testlib +QT += core-private gui-private waylandclient-private + +QMAKE_USE += wayland-client wayland-server + +CONFIG += wayland-scanner +WAYLANDSERVERSOURCES += \ + ../../../../src/3rdparty/protocol/wayland.xml \ + ../../../../src/3rdparty/protocol/xdg-shell-unstable-v6.xml + +INCLUDEPATH += ../shared + +SOURCES += \ + ../shared/mockcompositor.cpp \ + ../shared/mockinput.cpp \ + ../shared/mockshell.cpp \ + ../shared/mockxdgshellv6.cpp \ + ../shared/mocksurface.cpp \ + ../shared/mockoutput.cpp + +HEADERS += \ + ../shared/mockcompositor.h \ + ../shared/mockinput.h \ + ../shared/mocksurface.h \ + ../shared/mockoutput.h diff --git a/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp b/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp new file mode 100644 index 000000000..5aac336f2 --- /dev/null +++ b/tests/auto/client/xdgshellv6/tst_xdgshellv6.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** 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 "mockcompositor.h" + +#include <QBackingStore> +#include <QPainter> +#include <QScreen> +#include <QWindow> +#include <QMimeData> +#include <QPixmap> +#include <QDrag> + +#include <QtTest/QtTest> + +static const QSize screenSize(1600, 1200); + +class TestWindow : public QWindow +{ +public: + TestWindow() + { + setSurfaceType(QSurface::RasterSurface); + setGeometry(0, 0, 32, 32); + create(); + } +}; + +class tst_WaylandClientXdgShellV6 : public QObject +{ + Q_OBJECT +public: + tst_WaylandClientXdgShellV6(MockCompositor *c) + : m_compositor(c) + { + QSocketNotifier *notifier = new QSocketNotifier(m_compositor->waylandFileDescriptor(), QSocketNotifier::Read, this); + connect(notifier, &QSocketNotifier::activated, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); + // connect to the event dispatcher to make sure to flush out the outgoing message queue + connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::awake, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); + connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, this, &tst_WaylandClientXdgShellV6::processWaylandEvents); + } + +public slots: + void processWaylandEvents() + { + m_compositor->processWaylandEvents(); + } + + void cleanup() + { + // make sure the surfaces from the last test are properly cleaned up + // and don't show up as false positives in the next test + QTRY_VERIFY(!m_compositor->surface()); + } + +private slots: + void createDestroyWindow(); + +private: + MockCompositor *m_compositor; +}; + +void tst_WaylandClientXdgShellV6::createDestroyWindow() +{ + TestWindow window; + window.show(); + + QTRY_VERIFY(m_compositor->surface()); + + window.destroy(); + QTRY_VERIFY(!m_compositor->surface()); +} + +int main(int argc, char **argv) +{ + setenv("XDG_RUNTIME_DIR", ".", 1); + setenv("QT_QPA_PLATFORM", "wayland", 1); // force QGuiApplication to use wayland plugin + setenv("QT_WAYLAND_SHELL_INTEGRATION", "xdg-shell-v6", 1); + + // 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.setOutputMode(screenSize); + + QGuiApplication app(argc, argv); + compositor.applicationInitialized(); + + tst_WaylandClientXdgShellV6 tc(&compositor); + return QTest::qExec(&tc, argc, argv); +} + +#include <tst_xdgshellv6.moc> diff --git a/tests/auto/client/xdgshellv6/xdgshellv6.pro b/tests/auto/client/xdgshellv6/xdgshellv6.pro new file mode 100644 index 000000000..4fec593df --- /dev/null +++ b/tests/auto/client/xdgshellv6/xdgshellv6.pro @@ -0,0 +1,5 @@ +include (../shared/shared.pri) + +TARGET = tst_client_xdgshellv6 +SOURCES += tst_xdgshellv6.cpp + diff --git a/tests/auto/cmake/test_waylandclient/main.cpp b/tests/auto/cmake/test_waylandclient/main.cpp index f0ccdef4b..33f4470bb 100644 --- a/tests/auto/cmake/test_waylandclient/main.cpp +++ b/tests/auto/cmake/test_waylandclient/main.cpp @@ -3,5 +3,5 @@ int main() { // use symbol - QtWaylandClient::QWaylandCursor cursor(Q_NULLPTR); + QtWaylandClient::QWaylandCursor cursor(nullptr); } diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp index da1096fb9..bdc2b3b93 100644 --- a/tests/auto/compositor/compositor/mockclient.cpp +++ b/tests/auto/compositor/compositor/mockclient.cpp @@ -41,13 +41,13 @@ #include <sys/mman.h> const struct wl_registry_listener MockClient::registryListener = { - MockClient::handleGlobal + MockClient::handleGlobal, + MockClient::handleGlobalRemove }; MockClient::MockClient() : display(wl_display_connect("wayland-qt-test-0")) , compositor(0) - , output(0) , registry(0) , wlshell(0) , xdgShell(nullptr) @@ -74,9 +74,9 @@ MockClient::MockClient() timeout.start(); do { QCoreApplication::processEvents(); - } while (!(compositor && output) && timeout.elapsed() < 1000); + } while (!(compositor && !m_outputs.isEmpty()) && timeout.elapsed() < 1000); - if (!compositor || !output) + if (!compositor || m_outputs.empty()) qFatal("MockClient(): failed to receive globals from display"); } @@ -165,12 +165,19 @@ void MockClient::handleGlobal(void *data, wl_registry *registry, uint32_t id, co resolve(data)->handleGlobal(id, QByteArray(interface)); } +void MockClient::handleGlobalRemove(void *data, wl_registry *wl_registry, uint32_t id) +{ + Q_UNUSED(wl_registry); + resolve(data)->handleGlobalRemove(id); +} + void MockClient::handleGlobal(uint32_t id, const QByteArray &interface) { if (interface == "wl_compositor") { compositor = static_cast<wl_compositor *>(wl_registry_bind(registry, id, &wl_compositor_interface, 1)); } else if (interface == "wl_output") { - output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2)); + auto output = static_cast<wl_output *>(wl_registry_bind(registry, id, &wl_output_interface, 2)); + m_outputs.insert(id, output); wl_output_add_listener(output, &outputListener, this); } else if (interface == "wl_shm") { shm = static_cast<wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface, 1)); @@ -186,6 +193,11 @@ void MockClient::handleGlobal(uint32_t id, const QByteArray &interface) } } +void MockClient::handleGlobalRemove(uint32_t id) +{ + m_outputs.remove(id); +} + wl_surface *MockClient::createSurface() { flushDisplay(); @@ -248,7 +260,7 @@ ShmBuffer::ShmBuffer(const QSize &size, wl_shm *shm) ShmBuffer::~ShmBuffer() { - munmap(image.bits(), image.byteCount()); + munmap(image.bits(), image.sizeInBytes()); wl_buffer_destroy(handle); wl_shm_pool_destroy(shm_pool); } diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h index 1881393a6..dd50f9a28 100644 --- a/tests/auto/compositor/compositor/mockclient.h +++ b/tests/auto/compositor/compositor/mockclient.h @@ -64,7 +64,7 @@ public: wl_display *display; wl_compositor *compositor; - wl_output *output; + QMap<uint, wl_output *> m_outputs; wl_shm *shm; wl_registry *registry; wl_shell *wlshell; @@ -96,6 +96,7 @@ private: static MockClient *resolve(void *data) { return static_cast<MockClient *>(data); } static const struct wl_registry_listener registryListener; static void handleGlobal(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version); + static void handleGlobalRemove(void *data, struct wl_registry *wl_registry, uint32_t id); static int sourceUpdate(uint32_t mask, void *data); static void outputGeometryEvent(void *data, @@ -117,6 +118,7 @@ private: static void outputScale(void *data, wl_output *output, int factor); void handleGlobal(uint32_t id, const QByteArray &interface); + void handleGlobalRemove(uint32_t id); static const wl_output_listener outputListener; }; diff --git a/tests/auto/compositor/compositor/testcompositor.cpp b/tests/auto/compositor/compositor/testcompositor.cpp index 733bea5b3..f91d0d3f1 100644 --- a/tests/auto/compositor/compositor/testcompositor.cpp +++ b/tests/auto/compositor/compositor/testcompositor.cpp @@ -42,7 +42,7 @@ TestCompositor::TestCompositor(bool createInputDev) void TestCompositor::create() { - new QWaylandOutput(this, Q_NULLPTR); + new QWaylandOutput(this, nullptr); QWaylandCompositor::create(); connect(this, &QWaylandCompositor::surfaceCreated, this, &TestCompositor::onSurfaceCreated); diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp index c51c13bd6..96095a0d4 100644 --- a/tests/auto/compositor/compositor/tst_compositor.cpp +++ b/tests/auto/compositor/compositor/tst_compositor.cpp @@ -67,6 +67,7 @@ private slots: void sizeFollowsWindow(); void mapSurface(); void frameCallback(); + void removeOutput(); void advertisesXdgShellSupport(); void createsXdgSurfaces(); @@ -201,7 +202,7 @@ void tst_WaylandCompositor::keyboardGrab() QTRY_COMPARE(grabKeyReleaseSpy.count(), 2); // Stop grabbing - seat->setKeyboardFocus(Q_NULLPTR); + seat->setKeyboardFocus(nullptr); seat->sendFullKeyEvent(&ke); seat->sendFullKeyEvent(&ke1); QTRY_COMPARE(grabKeyPressSpy.count(), 2); @@ -378,6 +379,22 @@ void tst_WaylandCompositor::frameCallback() wl_surface_destroy(surface); } +void tst_WaylandCompositor::removeOutput() +{ + TestCompositor compositor; + QWindow window; + window.resize(800, 600); + auto output = new QWaylandOutput(&compositor, &window); + + compositor.create(); + MockClient client; + QTRY_COMPARE(client.m_outputs.size(), 2); + + delete output; + compositor.flushClients(); + QTRY_COMPARE(client.m_outputs.size(), 1); +} + void tst_WaylandCompositor::seatCapabilities() { TestCompositor compositor; |