summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2019-09-16 23:10:27 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2019-09-16 23:11:30 +0200
commitb95e6e5babc5e70b25076aed8080ee37773000cb (patch)
tree21170a1e7062e61507104f9ed0f3be2ca9b6257b
parent3e9fe00c4e4ae4c096a960b4a3b432fca546007a (diff)
parentfb1f6733b6d98d84f8abd89623c3878ed4a62573 (diff)
downloadqtwayland-b95e6e5babc5e70b25076aed8080ee37773000cb.tar.gz
Merge remote-tracking branch 'origin/dev' into wip/qt6
Conflicts: .qmake.conf Change-Id: Ifb5723b11bf5fe5bb3583018f496beba17c6bf40
-rw-r--r--.qmake.conf1
-rw-r--r--dist/changes-5.12.440
-rw-r--r--examples/wayland/minimal-cpp/compositor.cpp8
-rw-r--r--examples/wayland/minimal-cpp/compositor.h2
-rw-r--r--examples/wayland/minimal-cpp/window.cpp2
-rw-r--r--examples/wayland/multi-output/qml/GridScreen.qml10
-rw-r--r--examples/wayland/multi-output/qml/ShellScreen.qml10
-rw-r--r--examples/wayland/multi-output/qml/main.qml4
-rw-r--r--examples/wayland/wayland.pro4
-rw-r--r--src/3rdparty/protocol/idle-inhibit-unstable-v1.xml83
-rw-r--r--src/3rdparty/protocol/qt_attribution.json3
-rw-r--r--src/client/client.pro2
-rw-r--r--src/client/qwaylandcursor.cpp18
-rw-r--r--src/client/qwaylandinputdevice.cpp23
-rw-r--r--src/client/qwaylandinputdevice_p.h10
-rw-r--r--src/client/qwaylandintegration.cpp2
-rw-r--r--src/client/qwaylandnativeinterface.cpp22
-rw-r--r--src/client/qwaylandshmbackingstore.cpp14
-rw-r--r--src/client/qwaylandshmbackingstore_p.h5
-rw-r--r--src/client/qwaylandwindow.cpp74
-rw-r--r--src/client/qwaylandwindow_p.h3
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp2
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor_p.h4
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp7
-rw-r--r--src/compositor/compositor_api/qwaylandoutput.cpp10
-rw-r--r--src/compositor/compositor_api/qwaylandoutput_p.h5
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp10
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp23
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h4
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h3
-rw-r--r--src/compositor/doc/qtwaylandcompositor.qdocconf1
-rw-r--r--src/compositor/extensions/extensions.pri10
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1.cpp190
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1.h62
-rw-r--r--src/compositor/extensions/qwaylandidleinhibitv1_p.h88
-rw-r--r--src/compositor/extensions/qwaylandquickxdgoutputv1.cpp73
-rw-r--r--src/compositor/extensions/qwaylandquickxdgoutputv1.h62
-rw-r--r--src/compositor/extensions/qwaylandwlscaler_p.h2
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1.cpp595
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1.h111
-rw-r--r--src/compositor/extensions/qwaylandxdgoutputv1_p.h112
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer.cpp2
-rw-r--r--src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp35
-rw-r--r--src/imports/compositor/qwaylandquickcompositorplugin.cpp13
-rw-r--r--src/imports/imports.pro4
-rw-r--r--src/plugins/hardwareintegration/hardwareintegration.pro2
-rw-r--r--src/plugins/plugins.pro13
-rw-r--r--src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp4
-rw-r--r--src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h2
-rw-r--r--src/qtwaylandscanner/qtwaylandscanner.cpp215
-rw-r--r--src/src.pro30
-rw-r--r--sync.profile4
-rw-r--r--tests/auto/auto.pro4
-rw-r--r--tests/auto/client/datadevicev1/tst_datadevicev1.cpp8
-rw-r--r--tests/auto/client/inputcontext/inputcontext.pro2
-rw-r--r--tests/auto/client/output/tst_output.cpp3
-rw-r--r--tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp11
-rw-r--r--tests/auto/client/seatv4/tst_seatv4.cpp26
-rw-r--r--tests/auto/client/seatv5/tst_seatv5.cpp116
-rw-r--r--tests/auto/client/shared/coreprotocol.cpp68
-rw-r--r--tests/auto/client/shared/coreprotocol.h20
-rw-r--r--tests/auto/client/shared/mockcompositor.cpp2
-rw-r--r--tests/auto/client/shared/mockcompositor.h1
-rw-r--r--tests/auto/client/xdgshell/tst_xdgshell.cpp47
-rw-r--r--tests/auto/compositor/compositor/compositor.pro10
-rw-r--r--tests/auto/compositor/compositor/mockclient.cpp25
-rw-r--r--tests/auto/compositor/compositor/mockclient.h8
-rw-r--r--tests/auto/compositor/compositor/mockxdgoutputv1.cpp68
-rw-r--r--tests/auto/compositor/compositor/mockxdgoutputv1.h64
-rw-r--r--tests/auto/compositor/compositor/tst_compositor.cpp194
70 files changed, 2398 insertions, 317 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 1c947565..3f7f9129 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -2,5 +2,6 @@ load(qt_build_config)
DEFINES += QT_NO_FOREACH
DEFINES += QT_NO_JAVA_STYLE_ITERATORS
+DEFINES += QT_NO_LINKED_LIST
MODULE_VERSION = 6.0.0
diff --git a/dist/changes-5.12.4 b/dist/changes-5.12.4
new file mode 100644
index 00000000..672b9a7c
--- /dev/null
+++ b/dist/changes-5.12.4
@@ -0,0 +1,40 @@
+Qt 5.12.4 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.3.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Compositor *
+****************************************************************************
+
+ - Fixed a crash that could happen when accessing the d_func of
+ QWaylandShell.
+
+****************************************************************************
+* QPA plugin *
+****************************************************************************
+
+ - The non-blocking version of eglSwapBuffers is now used, if supported.
+ This fixed a bug where minimized windows would block the event loop.
+ - Windows that don't get frame callbacks from the compositor within 100 ms
+ are now set as not exposed. This should stop most clients from rendering
+ unnecessary frames to minimized or hidden windows.
+ - Fixed a crash on xdg-shell v5 when creating a popup without a valid
+ parent.
+ - Fixed a protocol error when an application tried to render to a window
+ before a shell or sub-surface was created.
+ - Fixed a crash when closing multiple popups at once.
diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp
index fa9ae2da..a4b98997 100644
--- a/examples/wayland/minimal-cpp/compositor.cpp
+++ b/examples/wayland/minimal-cpp/compositor.cpp
@@ -163,9 +163,13 @@ void Compositor::handleMouseMove(const QPoint &position)
defaultSeat()->sendMouseMoveEvent(view, mapToView(view, position));
}
-void Compositor::handleMouseWheel(Qt::Orientation orientation, int delta)
+void Compositor::handleMouseWheel(const QPoint &angleDelta)
{
- defaultSeat()->sendMouseWheelEvent(orientation, delta);
+ // TODO: fix this to send a single event, when diagonal scrolling is supported
+ if (angleDelta.x() != 0)
+ defaultSeat()->sendMouseWheelEvent(Qt::Horizontal, angleDelta.x());
+ if (angleDelta.y() != 0)
+ defaultSeat()->sendMouseWheelEvent(Qt::Vertical, angleDelta.y());
}
void Compositor::handleKeyPress(quint32 nativeScanCode)
diff --git a/examples/wayland/minimal-cpp/compositor.h b/examples/wayland/minimal-cpp/compositor.h
index 3c0c80e0..e32442dd 100644
--- a/examples/wayland/minimal-cpp/compositor.h
+++ b/examples/wayland/minimal-cpp/compositor.h
@@ -102,7 +102,7 @@ public:
void handleMousePress(const QPoint &position, Qt::MouseButton button);
void handleMouseRelease(const QPoint &position, Qt::MouseButton button, Qt::MouseButtons buttons);
void handleMouseMove(const QPoint &position);
- void handleMouseWheel(Qt::Orientation orientation, int delta);
+ void handleMouseWheel(const QPoint &angleDelta);
void handleKeyPress(quint32 nativeScanCode);
void handleKeyRelease(quint32 nativeScanCode);
diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp
index f32fb515..9f22cc68 100644
--- a/examples/wayland/minimal-cpp/window.cpp
+++ b/examples/wayland/minimal-cpp/window.cpp
@@ -129,7 +129,7 @@ void Window::mouseMoveEvent(QMouseEvent *event)
void Window::wheelEvent(QWheelEvent *event)
{
- m_compositor->handleMouseWheel(event->orientation(), event->delta());
+ m_compositor->handleMouseWheel(event->angleDelta());
}
void Window::keyPressEvent(QKeyEvent *e)
diff --git a/examples/wayland/multi-output/qml/GridScreen.qml b/examples/wayland/multi-output/qml/GridScreen.qml
index 340291af..a59cb8fb 100644
--- a/examples/wayland/multi-output/qml/GridScreen.qml
+++ b/examples/wayland/multi-output/qml/GridScreen.qml
@@ -50,7 +50,7 @@
import QtQuick 2.0
import QtQuick.Window 2.2
-import QtWayland.Compositor 1.0
+import QtWayland.Compositor 1.14
WaylandOutput {
id: output
@@ -93,4 +93,12 @@ WaylandOutput {
}
}
}
+
+ XdgOutputV1 {
+ name: "WL-2"
+ description: "Overview screen"
+ logicalPosition: output.position
+ logicalSize: Qt.size(output.geometry.width / output.scaleFactor,
+ output.geometry.height / output.scaleFactor)
+ }
}
diff --git a/examples/wayland/multi-output/qml/ShellScreen.qml b/examples/wayland/multi-output/qml/ShellScreen.qml
index 4482e6e8..aa9b4b29 100644
--- a/examples/wayland/multi-output/qml/ShellScreen.qml
+++ b/examples/wayland/multi-output/qml/ShellScreen.qml
@@ -50,7 +50,7 @@
import QtQuick 2.0
import QtQuick.Window 2.2
-import QtWayland.Compositor 1.0
+import QtWayland.Compositor 1.14
WaylandOutput {
id: output
@@ -84,4 +84,12 @@ WaylandOutput {
}
}
}
+
+ XdgOutputV1 {
+ name: "WL-1"
+ description: "Screen with window management"
+ logicalPosition: output.position
+ logicalSize: Qt.size(output.geometry.width / output.scaleFactor,
+ output.geometry.height / output.scaleFactor)
+ }
}
diff --git a/examples/wayland/multi-output/qml/main.qml b/examples/wayland/multi-output/qml/main.qml
index d01def55..45f91fd6 100644
--- a/examples/wayland/multi-output/qml/main.qml
+++ b/examples/wayland/multi-output/qml/main.qml
@@ -49,7 +49,7 @@
****************************************************************************/
import QtQuick 2.0
-import QtWayland.Compositor 1.0
+import QtWayland.Compositor 1.14
WaylandCompositor {
id: comp
@@ -91,6 +91,8 @@ WaylandCompositor {
}
}
+ XdgOutputManagerV1 {}
+
WlShell {
id: defaultShell
diff --git a/examples/wayland/wayland.pro b/examples/wayland/wayland.pro
index 2b7f992e..f9287481 100644
--- a/examples/wayland/wayland.pro
+++ b/examples/wayland/wayland.pro
@@ -1,6 +1,8 @@
-requires(qtHaveModule(waylandcompositor))
TEMPLATE=subdirs
+!qtHaveModule(waylandcompositor): \
+ return()
+
qtConfig(opengl) {
SUBDIRS += \
qwindow-compositor \
diff --git a/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml b/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml
new file mode 100644
index 00000000..9c06cdcb
--- /dev/null
+++ b/src/3rdparty/protocol/idle-inhibit-unstable-v1.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="idle_inhibit_unstable_v1">
+
+ <copyright>
+ Copyright © 2015 Samsung Electronics Co., Ltd
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="zwp_idle_inhibit_manager_v1" version="1">
+ <description summary="control behavior when display idles">
+ This interface permits inhibiting the idle behavior such as screen
+ blanking, locking, and screensaving. The client binds the idle manager
+ globally, then creates idle-inhibitor objects for each surface.
+
+ Warning! The protocol described in this file is experimental and
+ backward incompatible changes may be made. Backward compatible changes
+ may be added together with the corresponding interface version bump.
+ Backward incompatible changes are done by bumping the version number in
+ the protocol and interface names and resetting the interface version.
+ Once the protocol is to be declared stable, the 'z' prefix and the
+ version number in the protocol and interface names are removed and the
+ interface version number is reset.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the idle inhibitor object">
+ Destroy the inhibit manager.
+ </description>
+ </request>
+
+ <request name="create_inhibitor">
+ <description summary="create a new inhibitor object">
+ Create a new inhibitor object associated with the given surface.
+ </description>
+ <arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
+ <arg name="surface" type="object" interface="wl_surface"
+ summary="the surface that inhibits the idle behavior"/>
+ </request>
+
+ </interface>
+
+ <interface name="zwp_idle_inhibitor_v1" version="1">
+ <description summary="context object for inhibiting idle behavior">
+ An idle inhibitor prevents the output that the associated surface is
+ visible on from being set to a state where it is not visually usable due
+ to lack of user interaction (e.g. blanked, dimmed, locked, set to power
+ save, etc.) Any screensaver processes are also blocked from displaying.
+
+ If the surface is destroyed, unmapped, becomes occluded, loses
+ visibility, or otherwise becomes not visually relevant for the user, the
+ idle inhibitor will not be honored by the compositor; if the surface
+ subsequently regains visibility the inhibitor takes effect once again.
+ Likewise, the inhibitor isn't honored if the system was already idled at
+ the time the inhibitor was established, although if the system later
+ de-idles and re-idles the inhibitor will take effect.
+ </description>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy the idle inhibitor object">
+ Remove the inhibitor effect from the associated wl_surface.
+ </description>
+ </request>
+
+ </interface>
+</protocol>
diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json
index e6f90698..c49ead4f 100644
--- a/src/3rdparty/protocol/qt_attribution.json
+++ b/src/3rdparty/protocol/qt_attribution.json
@@ -127,8 +127,9 @@ Copyright (c) 2013 BMW Car IT GmbH"
"Id": "wayland-xdg-output-protocol",
"Name": "Wayland XDG Output Protocol",
"QDocModule": "qtwaylandcompositor",
- "QtUsage": "Used in the Qt Wayland platform plugin.",
+ "QtUsage": "Used in the Qt Wayland Compositor API, and the Qt Wayland platform plugin.",
"Files": "xdg-output-unstable-v1.xml",
+
"Description": "The XDG Output protocol is an extended way to describe output regions under Wayland",
"Homepage": "https://wayland.freedesktop.org",
"Version": "unstable v1, version 2",
diff --git a/src/client/client.pro b/src/client/client.pro
index 4f4c5832..d0ae9009 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -20,7 +20,7 @@ qtConfig(xkbcommon) {
}
qtHaveModule(linuxaccessibility_support_private): \
- QT += linuxaccessibility_support_private
+ QT_PRIVATE += linuxaccessibility_support_private
QMAKE_USE += wayland-client
diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp
index 165df776..4356b23a 100644
--- a/src/client/qwaylandcursor.cpp
+++ b/src/client/qwaylandcursor.cpp
@@ -48,6 +48,8 @@
#include <wayland-cursor.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
@@ -75,7 +77,10 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
if (struct wl_cursor *cursor = m_cursors.value(shape, nullptr))
return cursor;
- static const QMultiMap<WaylandCursor, QByteArray>cursorNamesMap {
+ static Q_CONSTEXPR struct ShapeAndName {
+ WaylandCursor shape;
+ const char name[33];
+ } cursorNamesMap[] = {
{ArrowCursor, "left_ptr"},
{ArrowCursor, "default"},
{ArrowCursor, "top_left_arrow"},
@@ -193,9 +198,14 @@ wl_cursor *QWaylandCursorTheme::requestCursor(WaylandCursor shape)
{ResizeSouthWestCursor, "bottom_left_corner"},
};
- QList<QByteArray> cursorNames = cursorNamesMap.values(shape);
- for (auto &name : qAsConst(cursorNames)) {
- if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, name.constData())) {
+ const auto byShape = [](ShapeAndName lhs, ShapeAndName rhs) {
+ return lhs.shape < rhs.shape;
+ };
+ Q_ASSERT(std::is_sorted(std::begin(cursorNamesMap), std::end(cursorNamesMap), byShape));
+ const auto p = std::equal_range(std::begin(cursorNamesMap), std::end(cursorNamesMap),
+ ShapeAndName{shape, ""}, byShape);
+ for (auto it = p.first; it != p.second; ++it) {
+ if (wl_cursor *cursor = wl_cursor_theme_get_cursor(m_theme, it->name)) {
m_cursors.insert(shape, cursor);
return cursor;
}
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 19e36ccb..8aa0239d 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -442,6 +442,21 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice
return new Touch(device);
}
+QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const
+{
+ return mKeyboard;
+}
+
+QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
+{
+ return mPointer;
+}
+
+QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
+{
+ return mTouch;
+}
+
void QWaylandInputDevice::handleEndDrag()
{
if (mTouch)
@@ -602,7 +617,7 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
invalidateFocus();
}
mFocus = window->waylandSurface();
- connect(mFocus, &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
+ connect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());
@@ -774,8 +789,10 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
void QWaylandInputDevice::Pointer::invalidateFocus()
{
- disconnect(mFocus, &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
- mFocus = nullptr;
+ if (mFocus) {
+ disconnect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
+ mFocus = nullptr;
+ }
mEnterSerial = 0;
}
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 06ba5d56..4ac1dca3 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -148,6 +148,10 @@ public:
virtual Pointer *createPointer(QWaylandInputDevice *device);
virtual Touch *createTouch(QWaylandInputDevice *device);
+ Keyboard *keyboard() const;
+ Pointer *pointer() const;
+ Touch *touch() const;
+
private:
QWaylandDisplay *mQDisplay = nullptr;
struct wl_display *mDisplay = nullptr;
@@ -248,6 +252,8 @@ public:
Qt::KeyboardModifiers modifiers() const;
+ struct ::wl_keyboard *wl_keyboard() { return QtWayland::wl_keyboard::object(); }
+
private slots:
void handleFocusDestroyed();
void handleFocusLost();
@@ -284,6 +290,8 @@ public:
#endif
QWaylandInputDevice *seat() const { return mParent; }
+ struct ::wl_pointer *wl_pointer() { return QtWayland::wl_pointer::object(); }
+
protected:
void pointer_enter(uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx, wl_fixed_t sy) override;
@@ -377,6 +385,8 @@ public:
bool allTouchPointsReleased();
void releasePoints();
+ struct ::wl_touch *wl_touch() { return QtWayland::wl_touch::object(); }
+
QWaylandInputDevice *mParent = nullptr;
QPointer<QWaylandWindow> mFocus;
QList<QWindowSystemInterface::TouchPoint> mTouchPoints;
diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp
index 078e5be1..7f79d6b9 100644
--- a/src/client/qwaylandintegration.cpp
+++ b/src/client/qwaylandintegration.cpp
@@ -272,7 +272,7 @@ QPlatformAccessibility *QWaylandIntegration::accessibility() const
{
if (!mAccessibility) {
#ifndef QT_NO_ACCESSIBILITY_ATSPI_BRIDGE
- Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QXcbIntegration",
+ Q_ASSERT_X(QCoreApplication::eventDispatcher(), "QWaylandIntegration",
"Initializing accessibility without event-dispatcher!");
mAccessibility.reset(new QSpiAccessibleBridge());
#else
diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp
index cf227d48..b4ecc009 100644
--- a/src/client/qwaylandnativeinterface.cpp
+++ b/src/client/qwaylandnativeinterface.cpp
@@ -47,6 +47,7 @@
#include "qwaylanddisplay_p.h"
#include "qwaylandwindowmanagerintegration_p.h"
#include "qwaylandscreen_p.h"
+#include "qwaylandinputdevice_p.h"
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QScreen>
#include <QtWaylandClient/private/qwaylandclientbufferintegration_p.h>
@@ -76,6 +77,27 @@ void *QWaylandNativeInterface::nativeResourceForIntegration(const QByteArray &re
if (lowerCaseResource == "egldisplay" && m_integration->clientBufferIntegration())
return m_integration->clientBufferIntegration()->nativeResource(QWaylandClientBufferIntegration::EglDisplay);
+ if (lowerCaseResource == "wl_seat")
+ return m_integration->display()->defaultInputDevice()->wl_seat();
+ if (lowerCaseResource == "wl_keyboard") {
+ auto *keyboard = m_integration->display()->defaultInputDevice()->keyboard();
+ if (keyboard)
+ return keyboard->wl_keyboard();
+ return nullptr;
+ }
+ if (lowerCaseResource == "wl_pointer") {
+ auto *pointer = m_integration->display()->defaultInputDevice()->pointer();
+ if (pointer)
+ return pointer->wl_pointer();
+ return nullptr;
+ }
+ if (lowerCaseResource == "wl_touch") {
+ auto *touch = m_integration->display()->defaultInputDevice()->touch();
+ if (touch)
+ return touch->wl_touch();
+ return nullptr;
+ }
+
return nullptr;
}
diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp
index d768e7fc..9b5971a2 100644
--- a/src/client/qwaylandshmbackingstore.cpp
+++ b/src/client/qwaylandshmbackingstore.cpp
@@ -249,7 +249,7 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
if (b->size() == size) {
return b;
} else {
- mBuffers.removeOne(b);
+ mBuffers.remove(b);
if (mBackBuffer == b)
mBackBuffer = nullptr;
delete b;
@@ -257,11 +257,11 @@ QWaylandShmBuffer *QWaylandShmBackingStore::getBuffer(const QSize &size)
}
}
- static const int MAX_BUFFERS = 5;
- if (mBuffers.count() < MAX_BUFFERS) {
+ static const size_t MAX_BUFFERS = 5;
+ if (mBuffers.size() < MAX_BUFFERS) {
QImage::Format format = QPlatformScreen::platformScreenForWindow(window())->format();
QWaylandShmBuffer *b = new QWaylandShmBuffer(mDisplay, size, format, waylandWindow()->scale());
- mBuffers.prepend(b);
+ mBuffers.push_front(b);
return b;
}
return nullptr;
@@ -300,9 +300,9 @@ void QWaylandShmBackingStore::resize(const QSize &size)
// ensure the new buffer is at the beginning of the list so next time getBuffer() will pick
// it if possible
- if (mBuffers.first() != buffer) {
- mBuffers.removeOne(buffer);
- mBuffers.prepend(buffer);
+ if (mBuffers.front() != buffer) {
+ mBuffers.remove(buffer);
+ mBuffers.push_front(buffer);
}
if (windowDecoration() && window()->isVisible() && oldSizeInBytes != newSizeInBytes)
diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h
index 88ecfc5e..8a85cd7f 100644
--- a/src/client/qwaylandshmbackingstore_p.h
+++ b/src/client/qwaylandshmbackingstore_p.h
@@ -57,7 +57,8 @@
#include <QtGui/QImage>
#include <qpa/qplatformwindow.h>
#include <QMutex>
-#include <QLinkedList>
+
+#include <list>
QT_BEGIN_NAMESPACE
@@ -116,7 +117,7 @@ private:
QWaylandShmBuffer *getBuffer(const QSize &size);
QWaylandDisplay *mDisplay = nullptr;
- QLinkedList<QWaylandShmBuffer *> mBuffers;
+ std::list<QWaylandShmBuffer *> mBuffers;
QWaylandShmBuffer *mFrontBuffer = nullptr;
QWaylandShmBuffer *mBackBuffer = nullptr;
bool mPainting = false;
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 9a58ec39..ce58003c 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -249,6 +249,13 @@ void QWaylandWindow::reset(bool sendDestroyEvent)
mFrameCallback = nullptr;
}
+ int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
+ if (timerId != -1) {
+ killTimer(timerId);
+ }
+ mWaitingForFrameCallback = false;
+ mFrameCallbackTimedOut = false;
+
mMask = QRegion();
mQueuedBuffer = nullptr;
}
@@ -343,7 +350,7 @@ void QWaylandWindow::setGeometry(const QRect &rect)
mSentInitialResize = true;
}
QRect exposeGeometry(QPoint(), geometry().size());
- if (exposeGeometry != mLastExposeGeometry)
+ if (isExposed() && !mInResizeFromApplyConfigure && exposeGeometry != mLastExposeGeometry)
sendExposeEvent(exposeGeometry);
if (mShellSurface)
@@ -358,7 +365,9 @@ void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, cons
QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins));
mOffset += offset;
+ mInResizeFromApplyConfigure = true;
setGeometry(geometry);
+ mInResizeFromApplyConfigure = false;
}
void QWaylandWindow::sendExposeEvent(const QRect &rect)
@@ -573,29 +582,34 @@ const wl_callback_listener QWaylandWindow::callbackListener = {
Q_UNUSED(callback);
Q_UNUSED(time);
auto *window = static_cast<QWaylandWindow*>(data);
- if (window->thread() != QThread::currentThread())
- QMetaObject::invokeMethod(window, [=] { window->handleFrameCallback(); }, Qt::QueuedConnection);
- else
- window->handleFrameCallback();
+ window->handleFrameCallback();
}
};
void QWaylandWindow::handleFrameCallback()
{
- bool wasExposed = isExposed();
+ // Stop the timer and stop waiting immediately
+ int timerId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
+ mWaitingForFrameCallback = false;
- if (mFrameCallbackTimerId != -1) {
- killTimer(mFrameCallbackTimerId);
- mFrameCallbackTimerId = -1;
- }
+ // The rest can wait until we can run it on the correct thread
+ auto doHandleExpose = [this, timerId]() {
+ if (timerId != -1)
+ killTimer(timerId);
- mWaitingForFrameCallback = false;
- mFrameCallbackTimedOut = false;
+ bool wasExposed = isExposed();
+ mFrameCallbackTimedOut = false;
+ if (!wasExposed && isExposed()) // Did setting mFrameCallbackTimedOut make the window exposed?
+ sendExposeEvent(QRect(QPoint(), geometry().size()));
+ if (wasExposed && hasPendingUpdateRequest())
+ deliverUpdateRequest();
+ };
- if (!wasExposed && isExposed())
- sendExposeEvent(QRect(QPoint(), geometry().size()));
- if (wasExposed && hasPendingUpdateRequest())
- deliverUpdateRequest();
+ if (thread() != QThread::currentThread()) {
+ QMetaObject::invokeMethod(this, doHandleExpose);
+ } else {
+ doHandleExpose();
+ }
}
QMutex QWaylandWindow::mFrameSyncMutex;
@@ -617,11 +631,11 @@ bool QWaylandWindow::waitForFrameSync(int timeout)
}
// Stop current frame timer if any, can't use killTimer directly, because we might be on a diffent thread
- if (mFrameCallbackTimerId != -1) {
- int id = mFrameCallbackTimerId;
- mFrameCallbackTimerId = -1;
- QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
- }
+ // Ordered semantics is needed to avoid stopping the timer twice and not miss it when it's
+ // started by other writes
+ int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
+ if (fcbId != -1)
+ QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
return !mWaitingForFrameCallback;
}
@@ -1077,9 +1091,9 @@ void QWaylandWindow::timerEvent(QTimerEvent *event)
}
}
- if (event->timerId() == mFrameCallbackTimerId) {
- killTimer(mFrameCallbackTimerId);
- mFrameCallbackTimerId = -1;
+
+ if (mFrameCallbackTimerId.testAndSetOrdered(event->timerId(), -1)) {
+ killTimer(event->timerId());
qCDebug(lcWaylandBackingstore) << "Didn't receive frame callback in time, window should now be inexposed";
mFrameCallbackTimedOut = true;
mWaitingForUpdate = false;
@@ -1132,7 +1146,7 @@ void QWaylandWindow::handleUpdate()
// ignore it if it times out before it's cleaned up by the invokeMethod call.
int id = mFallbackUpdateTimerId;
mFallbackUpdateTimerId = -1;
- QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
+ QMetaObject::invokeMethod(this, [this, id] { killTimer(id); }, Qt::QueuedConnection);
}
mFrameCallback = mSurface->frame();
@@ -1141,14 +1155,12 @@ void QWaylandWindow::handleUpdate()
mWaitingForUpdate = false;
// Stop current frame timer if any, can't use killTimer directly, see comment above.
- if (mFrameCallbackTimerId != -1) {
- int id = mFrameCallbackTimerId;
- mFrameCallbackTimerId = -1;
- QMetaObject::invokeMethod(this, [=] { killTimer(id); }, Qt::QueuedConnection);
- }
+ int fcbId = mFrameCallbackTimerId.fetchAndStoreOrdered(-1);
+ if (fcbId != -1)
+ QMetaObject::invokeMethod(this, [this, fcbId] { killTimer(fcbId); }, Qt::QueuedConnection);
// Start a timer for handling the case when the compositor stops sending frame callbacks.
- QMetaObject::invokeMethod(this, [=] { // Again; can't do it directly
+ QMetaObject::invokeMethod(this, [this] { // Again; can't do it directly
if (mWaitingForFrameCallback)
mFrameCallbackTimerId = startTimer(100);
}, Qt::QueuedConnection);
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 5eadc02c..8d8565d7 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -219,7 +219,7 @@ protected:
WId mWindowId;
bool mWaitingForFrameCallback = false;
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out
- int mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
+ QAtomicInt mFrameCallbackTimerId = -1; // Started on commit, reset on frame callback
struct ::wl_callback *mFrameCallback = nullptr;
struct ::wl_event_queue *mFrameQueue = nullptr;
QWaitCondition mFrameSyncWait;
@@ -264,6 +264,7 @@ private:
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
void handleScreensChanged();
+ bool mInResizeFromApplyConfigure = false;
QRect mLastExposeGeometry;
static const wl_callback_listener callbackListener;
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 2d10c638..e2d617c3 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -302,7 +302,7 @@ void QWaylandCompositorPrivate::addPolishObject(QObject *object)
if (initialized) {
QCoreApplication::postEvent(object, new QEvent(QEvent::Polish));
} else {
- polish_objects.append(object);
+ polish_objects.push_back(object);
}
}
diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h
index 2c962421..2437533d 100644
--- a/src/compositor/compositor_api/qwaylandcompositor_p.h
+++ b/src/compositor/compositor_api/qwaylandcompositor_p.h
@@ -60,6 +60,8 @@
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
+#include <vector>
+
#if QT_CONFIG(xkbcommon)
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
@@ -175,7 +177,7 @@ protected:
bool retainSelection = false;
bool preInitialized = false;
bool initialized = false;
- QList<QPointer<QObject> > polish_objects;
+ std::vector<QPointer<QObject> > polish_objects;
#if QT_CONFIG(xkbcommon)
QXkbCommon::ScopedXKBContext mXkbContext;
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index 452be436..c5ec008d 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -366,6 +366,13 @@ void QWaylandKeyboardPrivate::createXKBKeymap()
QByteArray variant = keymap->variant().toLocal8Bit();
QByteArray options = keymap->options().toLocal8Bit();
+ if (!layout.isEmpty() && !layout.contains("us")) {
+ // This is needed for shortucts like "ctrl+c" to function even when
+ // user has selected only non-latin keyboard layouts, e.g. 'ru'.
+ layout.append(",us");
+ variant.append(",");
+ }
+
struct xkb_rule_names rule_names = {
rules.constData(),
model.constData(),
diff --git a/src/compositor/compositor_api/qwaylandoutput.cpp b/src/compositor/compositor_api/qwaylandoutput.cpp
index 7a02d4ca..601f692a 100644
--- a/src/compositor/compositor_api/qwaylandoutput.cpp
+++ b/src/compositor/compositor_api/qwaylandoutput.cpp
@@ -48,6 +48,7 @@
#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
#include <QtWaylandCompositor/private/qwaylandview_p.h>
#include <QtWaylandCompositor/private/qwaylandutils_p.h>
+#include <QtWaylandCompositor/private/qwaylandxdgoutputv1_p.h>
#include <QtCore/QCoreApplication>
#include <QtCore/QtMath>
@@ -162,6 +163,9 @@ void QWaylandOutputPrivate::sendGeometryInfo()
if (resource->version() >= 2)
send_done(resource->handle);
}
+
+ if (xdgOutput)
+ QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone();
}
void QWaylandOutputPrivate::sendMode(const Resource *resource, const QWaylandOutputMode &mode)
@@ -185,6 +189,9 @@ void QWaylandOutputPrivate::sendModesInfo()
if (resource->version() >= 2)
send_done(resource->handle);
}
+
+ if (xdgOutput)
+ QWaylandXdgOutputV1Private::get(xdgOutput)->sendDone();
}
void QWaylandOutputPrivate::handleWindowPixelSizeChanged()
@@ -840,6 +847,9 @@ void QWaylandOutput::setScaleFactor(int scale)
}
Q_EMIT scaleFactorChanged();
+
+ if (d->xdgOutput)
+ QWaylandXdgOutputV1Private::get(d->xdgOutput)->sendDone();
}
/*!
diff --git a/src/compositor/compositor_api/qwaylandoutput_p.h b/src/compositor/compositor_api/qwaylandoutput_p.h
index 4badd379..58188ac3 100644
--- a/src/compositor/compositor_api/qwaylandoutput_p.h
+++ b/src/compositor/compositor_api/qwaylandoutput_p.h
@@ -57,6 +57,7 @@
#include <QtWaylandCompositor/QWaylandOutput>
#include <QtWaylandCompositor/QWaylandClient>
#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandXdgOutputV1>
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
@@ -110,6 +111,8 @@ public:
void handleWindowPixelSizeChanged();
+ QPointer<QWaylandXdgOutputV1> xdgOutput;
+
protected:
void output_bind_resource(Resource *resource) override;
@@ -137,6 +140,8 @@ private:
Q_DECLARE_PUBLIC(QWaylandOutput)
Q_DISABLE_COPY(QWaylandOutputPrivate)
+
+ friend class QWaylandXdgOutputManagerV1Private;
};
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 996177be..ee15a087 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -610,13 +610,17 @@ void QWaylandQuickItem::wheelEvent(QWheelEvent *event)
{
Q_D(QWaylandQuickItem);
if (d->shouldSendInputEvents()) {
- if (!inputRegionContains(event->pos())) {
+ if (!inputRegionContains(event->position())) {
event->ignore();
return;
}
QWaylandSeat *seat = compositor()->seatFor(event);
- seat->sendMouseWheelEvent(event->orientation(), event->delta());
+ // TODO: fix this to send a single event, when diagonal scrolling is supported
+ if (event->angleDelta().x() != 0)
+ seat->sendMouseWheelEvent(Qt::Horizontal, event->angleDelta().x());
+ if (event->angleDelta().y() != 0)
+ seat->sendMouseWheelEvent(Qt::Vertical, event->angleDelta().y());
} else {
event->ignore();
}
@@ -1324,7 +1328,7 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->view->isBufferLocked() && !bufferHasContent && d->paintEnabled)
return oldNode;
- if (!bufferHasContent || !d->paintEnabled) {
+ if (!bufferHasContent || !d->paintEnabled || !surface()) {
delete oldNode;
return nullptr;
}
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 433b5322..2265b41c 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -764,6 +764,29 @@ bool QWaylandSurface::isCursorSurface() const
return d->isCursorSurface;
}
+/*!
+ * \qmlproperty bool QtWaylandCompositor::WaylandSurface::inhibitsIdle
+ *
+ * This property holds whether this surface is intended to inhibit the idle
+ * behavior of the compositor such as screen blanking, locking and screen saving.
+ *
+ * \sa IdleInhibitManagerV1
+ */
+
+/*!
+ * \property QWaylandSurface::inhibitsIdle
+ *
+ * This property holds whether this surface is intended to inhibit the idle
+ * behavior of the compositor such as screen blanking, locking and screen saving.
+ *
+ * \sa QWaylandIdleInhibitManagerV1
+ */
+bool QWaylandSurface::inhibitsIdle() const
+{
+ Q_D(const QWaylandSurface);
+ return !d->idleInhibitors.isEmpty();
+}
+
#if QT_CONFIG(im)
QWaylandInputMethodControl *QWaylandSurface::inputMethodControl() const
{
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index 667f911c..f8cdc443 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -92,6 +92,7 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandSurface : public QWaylandObject
Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged)
Q_PROPERTY(bool hasContent READ hasContent NOTIFY hasContentChanged)
Q_PROPERTY(bool cursorSurface READ isCursorSurface WRITE markAsCursorSurface NOTIFY cursorSurfaceChanged)
+ Q_PROPERTY(bool inhibitsIdle READ inhibitsIdle NOTIFY inhibitsIdleChanged REVISION 14)
public:
enum Origin {
@@ -148,6 +149,8 @@ public:
void markAsCursorSurface(bool cursorSurface);
bool isCursorSurface() const;
+ bool inhibitsIdle() const;
+
#if QT_CONFIG(im)
QWaylandInputMethodControl *inputMethodControl() const;
#endif
@@ -181,6 +184,7 @@ Q_SIGNALS:
void subsurfacePlaceBelow(QWaylandSurface *sibling);
void dragStarted(QWaylandDrag *drag);
void cursorSurfaceChanged();
+ void inhibitsIdleChanged();
void configure(bool hasBuffer);
void redraw();
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 1637d870..97cb19d9 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -74,6 +74,7 @@
#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
#include <QtWaylandCompositor/private/qwaylandviewporter_p.h>
+#include <QtWaylandCompositor/private/qwaylandidleinhibitv1_p.h>
QT_BEGIN_NAMESPACE
@@ -167,6 +168,8 @@ public: //member variables
QList<QPointer<QWaylandSurface>> subsurfaceChildren;
+ QVector<QWaylandIdleInhibitManagerV1Private::Inhibitor *> idleInhibitors;
+
QRegion inputRegion;
QRegion opaqueRegion;
diff --git a/src/compositor/doc/qtwaylandcompositor.qdocconf b/src/compositor/doc/qtwaylandcompositor.qdocconf
index 4fa9f394..45928b64 100644
--- a/src/compositor/doc/qtwaylandcompositor.qdocconf
+++ b/src/compositor/doc/qtwaylandcompositor.qdocconf
@@ -1,4 +1,5 @@
include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf)
+include($QT_INSTALL_DOCS/config/exampleurl-qtwayland.qdocconf)
project = QtWaylandCompositor
description = Qt Wayland Compositor Reference Documentation
diff --git a/src/compositor/extensions/extensions.pri b/src/compositor/extensions/extensions.pri
index 027ea114..61ab043e 100644
--- a/src/compositor/extensions/extensions.pri
+++ b/src/compositor/extensions/extensions.pri
@@ -14,7 +14,9 @@ WAYLANDSERVERSOURCES += \
../3rdparty/protocol/xdg-shell-unstable-v6.xml \
../3rdparty/protocol/xdg-shell.xml \
../3rdparty/protocol/xdg-decoration-unstable-v1.xml \
+ ../3rdparty/protocol/xdg-output-unstable-v1.xml \
../3rdparty/protocol/ivi-application.xml \
+ ../3rdparty/protocol/idle-inhibit-unstable-v1.xml \
HEADERS += \
extensions/qwlqttouch_p.h \
@@ -41,7 +43,11 @@ HEADERS += \
extensions/qwaylandxdgshell_p.h \
extensions/qwaylandxdgdecorationv1.h \
extensions/qwaylandxdgdecorationv1_p.h \
+ extensions/qwaylandxdgoutputv1.h \
+ extensions/qwaylandxdgoutputv1_p.h \
extensions/qwaylandshellsurface.h \
+ extensions/qwaylandidleinhibitv1.h \
+ extensions/qwaylandidleinhibitv1_p.h \
extensions/qwaylandiviapplication.h \
extensions/qwaylandiviapplication_p.h \
extensions/qwaylandivisurface.h \
@@ -61,7 +67,9 @@ SOURCES += \
extensions/qwaylandxdgshellv6.cpp \
extensions/qwaylandxdgshell.cpp \
extensions/qwaylandxdgdecorationv1.cpp \
+ extensions/qwaylandxdgoutputv1.cpp \
extensions/qwaylandshellsurface.cpp \
+ extensions/qwaylandidleinhibitv1.cpp \
extensions/qwaylandiviapplication.cpp \
extensions/qwaylandivisurface.cpp \
@@ -72,6 +80,7 @@ qtHaveModule(quick) {
extensions/qwaylandquickshellsurfaceitem_p.h \
extensions/qwaylandivisurfaceintegration_p.h \
extensions/qwaylandwlshellintegration_p.h \
+ extensions/qwaylandquickxdgoutputv1.h \
extensions/qwaylandxdgshellv5integration_p.h \
extensions/qwaylandxdgshellv6integration_p.h \
extensions/qwaylandxdgshellintegration_p.h \
@@ -81,6 +90,7 @@ qtHaveModule(quick) {
extensions/qwaylandquickshellsurfaceitem.cpp \
extensions/qwaylandivisurfaceintegration.cpp \
extensions/qwaylandwlshellintegration.cpp \
+ extensions/qwaylandquickxdgoutputv1.cpp \
extensions/qwaylandxdgshellv5integration.cpp \
extensions/qwaylandxdgshellv6integration.cpp \
extensions/qwaylandxdgshellintegration.cpp \
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1.cpp b/src/compositor/extensions/qwaylandidleinhibitv1.cpp
new file mode 100644
index 00000000..b97f5813
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
+
+#include "qwaylandidleinhibitv1_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWaylandIdleInhibitManagerV1
+ \inmodule QtWaylandCompositor
+ \since 5.14
+ \brief Provides an extension that allows to inhibit the idle behavior of the compositor
+ \sa QWaylandSurface::inhibitsIdle
+
+ The QWaylandIdleInhibitV1 extension provides a way for a client to inhibit the idle behavior of
+ the compositor when a specific surface is visually relevant to the user.
+
+ QWaylandIdleInhibitManagerV1 corresponds to the Wayland interface, \c zwp_idle_inhibit_manager_v1.
+
+ Inhibited surfaces have the QWaylandSurface::inhibitsIdle property set to \c true.
+*/
+
+/*!
+ \qmltype IdleInhibitManagerV1
+ \inqmlmodule QtWayland.Compositor
+ \since 5.14
+ \brief Provides an extension that allows to inhibit the idle behavior of the compositor
+ \sa WaylandSurface::inhibitsIdle
+
+ The IdleInhibitManagerV1 extension provides a way for a client to inhibit the idle behavior of
+ the compositor when a specific surface is visually relevant to the user.
+
+ IdleInhibitManagerV1 corresponds to the Wayland interface, \c zwp_idle_inhibit_manager_v1.
+
+ To provide the functionality of the extension in a compositor, create an instance of the
+ IdleInhibitManagerV1 component and add it to the list of extensions supported by the compositor:
+
+ \qml \QtMinorVersion
+ import QtWayland.Compositor 1.\1
+
+ WaylandCompositor {
+ IdleInhibitManagerV1 {
+ // ...
+ }
+ }
+ \endqml
+
+ Inhibited surfaces have the WaylandSurface::inhibitsIdle property set to \c true.
+*/
+
+/*!
+ Constructs a QWaylandIdleInhibitManagerV1 object.
+*/
+QWaylandIdleInhibitManagerV1::QWaylandIdleInhibitManagerV1()
+ : QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>(*new QWaylandIdleInhibitManagerV1Private())
+{
+}
+
+/*!
+ Constructs a QWaylandIdleInhibitManagerV1 object for the provided \a compositor.
+*/
+QWaylandIdleInhibitManagerV1::QWaylandIdleInhibitManagerV1(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>(compositor, *new QWaylandIdleInhibitManagerV1Private())
+{
+}
+
+/*!
+ Destructs a QWaylandIdleInhibitManagerV1 object.
+*/
+QWaylandIdleInhibitManagerV1::~QWaylandIdleInhibitManagerV1() = default;
+
+/*!
+ Initializes the extension.
+*/
+void QWaylandIdleInhibitManagerV1::initialize()
+{
+ Q_D(QWaylandIdleInhibitManagerV1);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qCWarning(qLcWaylandCompositor) << "Failed to find QWaylandCompositor when initializing QWaylandIdleInhibitManagerV1";
+ return;
+ }
+ d->init(compositor->display(), d->interfaceVersion());
+}
+
+/*!
+ Returns the Wayland interface for the QWaylandIdleInhibitManagerV1.
+*/
+const wl_interface *QWaylandIdleInhibitManagerV1::interface()
+{
+ return QWaylandIdleInhibitManagerV1Private::interface();
+}
+
+
+void QWaylandIdleInhibitManagerV1Private::zwp_idle_inhibit_manager_v1_create_inhibitor(Resource *resource, uint id, wl_resource *surfaceResource)
+{
+ auto *surface = QWaylandSurface::fromResource(surfaceResource);
+ if (!surface) {
+ qCWarning(qLcWaylandCompositor) << "Couldn't find surface requested for creating an inhibitor";
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "invalid wl_surface@%d", wl_resource_get_id(surfaceResource));
+ return;
+ }
+
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(surface);
+ if (!surfacePrivate) {
+ wl_resource_post_no_memory(resource->handle);
+ return;
+ }
+
+ auto *inhibitor = new Inhibitor(surface, resource->client(), id, resource->version());
+ if (!inhibitor) {
+ wl_resource_post_no_memory(resource->handle);
+ return;
+ }
+ surfacePrivate->idleInhibitors.append(inhibitor);
+
+ if (surfacePrivate->idleInhibitors.size() == 1)
+ Q_EMIT surface->inhibitsIdleChanged();
+}
+
+
+QWaylandIdleInhibitManagerV1Private::Inhibitor::Inhibitor(QWaylandSurface *surface,
+ wl_client *client,
+ quint32 id, quint32 version)
+ : QtWaylandServer::zwp_idle_inhibitor_v1(client, id, qMin<quint32>(version, interfaceVersion()))
+ , m_surface(surface)
+{
+ Q_ASSERT(surface);
+}
+
+void QWaylandIdleInhibitManagerV1Private::Inhibitor::zwp_idle_inhibitor_v1_destroy_resource(Resource *resource)
+{
+ Q_UNUSED(resource);
+ delete this;
+}
+
+void QWaylandIdleInhibitManagerV1Private::Inhibitor::zwp_idle_inhibitor_v1_destroy(Resource *resource)
+{
+ if (m_surface) {
+ auto *surfacePrivate = QWaylandSurfacePrivate::get(m_surface.data());
+ Q_ASSERT(surfacePrivate->idleInhibitors.contains(this));
+ surfacePrivate->idleInhibitors.removeOne(this);
+
+ if (surfacePrivate->idleInhibitors.isEmpty())
+ Q_EMIT m_surface.data()->inhibitsIdleChanged();
+ }
+
+ wl_resource_destroy(resource->handle);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1.h b/src/compositor/extensions/qwaylandidleinhibitv1.h
new file mode 100644
index 00000000..53c09d08
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDIDLEINHIBITV1_H
+#define QWAYLANDIDLEINHIBITV1_H
+
+#include <QtWaylandCompositor/QWaylandCompositorExtension>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandIdleInhibitManagerV1Private;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIdleInhibitManagerV1 : public QWaylandCompositorExtensionTemplate<QWaylandIdleInhibitManagerV1>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandIdleInhibitManagerV1)
+public:
+ QWaylandIdleInhibitManagerV1();
+ explicit QWaylandIdleInhibitManagerV1(QWaylandCompositor *compositor);
+ ~QWaylandIdleInhibitManagerV1();
+
+ void initialize() override;
+
+ static const struct wl_interface *interface();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDIDLEINHIBITV1_H
diff --git a/src/compositor/extensions/qwaylandidleinhibitv1_p.h b/src/compositor/extensions/qwaylandidleinhibitv1_p.h
new file mode 100644
index 00000000..38055180
--- /dev/null
+++ b/src/compositor/extensions/qwaylandidleinhibitv1_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDIDLEINHIBITV1_P_H
+#define QWAYLANDIDLEINHIBITV1_P_H
+
+#include <QtWaylandCompositor/QWaylandSurface>
+#include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1>
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-idle-inhibit-unstable-v1.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandIdleInhibitManagerV1Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zwp_idle_inhibit_manager_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandIdleInhibitManagerV1)
+public:
+ explicit QWaylandIdleInhibitManagerV1Private() = default;
+
+ class Q_WAYLAND_COMPOSITOR_EXPORT Inhibitor
+ : public QtWaylandServer::zwp_idle_inhibitor_v1
+ {
+ public:
+ explicit Inhibitor(QWaylandSurface *surface, wl_client *client, quint32 id, quint32 version);
+
+ protected:
+ void zwp_idle_inhibitor_v1_destroy_resource(Resource *resource) override;
+ void zwp_idle_inhibitor_v1_destroy(Resource *resource) override;
+
+ private:
+ QPointer<QWaylandSurface> m_surface;
+ };
+
+ static QWaylandIdleInhibitManagerV1Private *get(QWaylandIdleInhibitManagerV1 *manager) { return manager ? manager->d_func() : nullptr; }
+
+protected:
+ void zwp_idle_inhibit_manager_v1_create_inhibitor(Resource *resource, uint32_t id, wl_resource *surfaceResource) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDIDLEINHIBITV1_P_H
diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp
new file mode 100644
index 00000000..eb6717a7
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QWaylandCompositor>
+#include <QWaylandOutput>
+
+#include "qwaylandquickxdgoutputv1.h"
+#include "qwaylandxdgoutputv1_p.h"
+
+QWaylandQuickXdgOutputV1::QWaylandQuickXdgOutputV1()
+ : QWaylandXdgOutputV1()
+{
+}
+
+void QWaylandQuickXdgOutputV1::componentComplete()
+{
+ // Try to find the manager from the compositor extensions
+ if (!manager()) {
+ for (auto *p = parent(); p != nullptr; p = p->parent()) {
+ if (auto *c = qobject_cast<QWaylandCompositor *>(p)) {
+ for (auto *extension : c->extensions()) {
+ if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(extension)) {
+ QWaylandXdgOutputV1Private::get(this)->setManager(m);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Try to find the output from the parents
+ if (!output()) {
+ for (auto *p = parent(); p != nullptr; p = p->parent()) {
+ if (auto *o = qobject_cast<QWaylandOutput *>(p)) {
+ QWaylandXdgOutputV1Private::get(this)->setOutput(o);
+ break;
+ }
+ }
+ }
+}
diff --git a/src/compositor/extensions/qwaylandquickxdgoutputv1.h b/src/compositor/extensions/qwaylandquickxdgoutputv1.h
new file mode 100644
index 00000000..c8b16ab8
--- /dev/null
+++ b/src/compositor/extensions/qwaylandquickxdgoutputv1.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDQUICKXDGOUTPUT_V1
+#define QWAYLANDQUICKXDGOUTPUT_V1
+
+#include <QtQml/QQmlListProperty>
+#include <QtQml/QQmlParserStatus>
+#include <QtWaylandCompositor/QWaylandXdgOutputV1>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickXdgOutputV1
+ : public QWaylandXdgOutputV1
+ , public QQmlParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QQmlParserStatus)
+public:
+ explicit QWaylandQuickXdgOutputV1();
+
+protected:
+ void classBegin() override {}
+ void componentComplete() override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDQUICKXDGOUTPUT_V1
diff --git a/src/compositor/extensions/qwaylandwlscaler_p.h b/src/compositor/extensions/qwaylandwlscaler_p.h
index d3c2edd7..10a66f88 100644
--- a/src/compositor/extensions/qwaylandwlscaler_p.h
+++ b/src/compositor/extensions/qwaylandwlscaler_p.h
@@ -55,6 +55,7 @@
QT_BEGIN_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 13)
class QWaylandSurface;
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandWlScalerPrivate
@@ -87,6 +88,7 @@ private:
QPointer<QWaylandSurface> m_surface = nullptr;
};
};
+#endif
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.cpp b/src/compositor/extensions/qwaylandxdgoutputv1.cpp
new file mode 100644
index 00000000..2ab26c16
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QWaylandCompositor>
+
+#include "qwaylandxdgoutputv1_p.h"
+#include "qwaylandoutput_p.h"
+
+#include <wayland-server.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ * \qmltype XdgOutputManagerV1
+ * \inqmlmodule QtWayland.Compositor
+ * \since 5.14
+ * \brief Provides an extension for describing outputs in a desktop oriented fashion
+ *
+ * The XdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way
+ * that is more in line with the concept of an output on desktop oriented systems.
+ *
+ * Some information may not make sense in other applications such as IVI systems.
+ *
+ * Typically the global compositor space on a desktop system is made of a
+ * contiguous or overlapping set of rectangular regions.
+ *
+ * XdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1.
+ *
+ * To provide the functionality of the extension in a compositor, create an instance of the
+ * XdgOutputManagerV1 component and add it to the list of extensions supported by the compositor,
+ * and associated each XdgOutputV1 with its WaylandOutput:
+ *
+ * \qml \QtMinorVersion
+ * import QtWayland.Compositor 1.\1
+ *
+ * WaylandCompositor {
+ * XdgOutputManagerV1 {
+ * WaylandOutput {
+ * id: output1
+ *
+ * position: Qt.point(0, 0)
+ * window: Window {}
+ *
+ * XdgOutputV1 {
+ * name: "WL-1"
+ * logicalPosition: output1.position
+ * logicalSize: Qt.size(output1.geometry.width / output1.scaleFactor,
+ * output1.geometry.height / output1.scaleFactor)
+ * }
+ * }
+ *
+ * WaylandOutput {
+ * id: output2
+ *
+ * position: Qt.point(800, 0)
+ * window: Window {}
+ *
+ * XdgOutputV1 {
+ * name: "WL-2"
+ * logicalPosition: output2.position
+ * logicalSize: Qt.size(output2.geometry.width / output2.scaleFactor,
+ * output2.geometry.height / output2.scaleFactor)
+ * }
+ * }
+ * }
+ * }
+ * \endqml
+ */
+
+/*!
+ * \class QWaylandXdgOutputManagerV1
+ * \inmodule QtWaylandCompositor
+ * \since 5.14
+ * \brief Provides an extension for describing outputs in a desktop oriented fashion
+ *
+ * The QWaylandXdgOutputManagerV1 extension provides a way for a compositor to describe outputs in a way
+ * that is more in line with the concept of an output on desktop oriented systems.
+ *
+ * Some information may not make sense in other applications such as IVI systems.
+ *
+ * QWaylandXdgOutputManagerV1 corresponds to the Wayland interface, \c zxdg_output_manager_v1.
+ */
+
+/*!
+ * Constructs a QWaylandXdgOutputManagerV1 object.
+ */
+QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1()
+ : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(*new QWaylandXdgOutputManagerV1Private())
+{
+}
+
+/*!
+ * Constructs a QWaylandXdgOutputManagerV1 object for the provided \a compositor.
+ */
+QWaylandXdgOutputManagerV1::QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>(compositor, *new QWaylandXdgOutputManagerV1Private())
+{
+}
+
+// QWaylandXdgOutputManagerV1Private
+
+/*!
+ * Initializes the extension.
+ */
+void QWaylandXdgOutputManagerV1::initialize()
+{
+ Q_D(QWaylandXdgOutputManagerV1);
+
+ QWaylandCompositorExtensionTemplate::initialize();
+ QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer());
+ if (!compositor) {
+ qCWarning(qLcWaylandCompositor) << "Failed to find QWaylandCompositor when initializing QWaylandXdgOutputManagerV1";
+ return;
+ }
+ d->init(compositor->display(), d->interfaceVersion());
+}
+
+/*!
+ * Returns the Wayland interface for QWaylandXdgOutputManagerV1.
+ */
+const wl_interface *QWaylandXdgOutputManagerV1::interface()
+{
+ return QWaylandXdgOutputManagerV1Private::interface();
+}
+
+// QWaylandXdgOutputManagerV1Private
+
+void QWaylandXdgOutputManagerV1Private::registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput)
+{
+ if (!xdgOutputs.contains(output)) {
+ xdgOutputs[output] = xdgOutput;
+ QWaylandOutputPrivate::get(output)->xdgOutput = xdgOutput;
+ }
+}
+
+void QWaylandXdgOutputManagerV1Private::unregisterXdgOutput(QWaylandOutput *output)
+{
+ xdgOutputs.remove(output);
+}
+
+void QWaylandXdgOutputManagerV1Private::zxdg_output_manager_v1_get_xdg_output(Resource *resource,
+ uint32_t id,
+ wl_resource *outputResource)
+{
+ Q_Q(QWaylandXdgOutputManagerV1);
+
+ // Verify if the associated output exist
+ auto *output = QWaylandOutput::fromResource(outputResource);
+ if (!output) {
+ qCWarning(qLcWaylandCompositor,
+ "The client is requesting a QWaylandXdgOutputV1 for a "
+ "QWaylandOutput that doesn't exist");
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, "output not found");
+ return;
+ }
+
+ // Do we have a QWaylandXdgOutputV1 for this output?
+ if (!xdgOutputs.contains(output)) {
+ qCWarning(qLcWaylandCompositor,
+ "The client is requesting a QWaylandXdgOutputV1 that the compositor "
+ "didn't create before");
+ wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "compositor didn't create a QWaylandXdgOutputV1 for this zxdg_output_v1 object");
+ return;
+ }
+
+ // Bind QWaylandXdgOutputV1 and initialize
+ auto *xdgOutput = xdgOutputs[output];
+ auto *xdgOutputPrivate = QWaylandXdgOutputV1Private::get(xdgOutput);
+ Q_ASSERT(xdgOutputPrivate);
+ xdgOutputPrivate->setManager(q);
+ xdgOutputPrivate->setOutput(output);
+ xdgOutputPrivate->add(resource->client(), id, qMin(resource->version(), QWaylandXdgOutputV1Private::interfaceVersion()));
+}
+
+// QWaylandXdgOutputV1
+
+QWaylandXdgOutputV1::QWaylandXdgOutputV1()
+ : QObject(*new QWaylandXdgOutputV1Private)
+{
+}
+
+QWaylandXdgOutputV1::QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager)
+ : QObject(*new QWaylandXdgOutputV1Private)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ // Set members before emitting changed signals so that handlers will
+ // see both already set and not nullptr, avoiding potential crashes
+ d->manager = manager;
+ d->output = output;
+
+ QWaylandXdgOutputManagerV1Private::get(d->manager)->registerXdgOutput(output, this);
+
+ emit managerChanged();
+ emit outputChanged();
+}
+
+QWaylandXdgOutputV1::~QWaylandXdgOutputV1()
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->manager)
+ QWaylandXdgOutputManagerV1Private::get(d->manager)->unregisterXdgOutput(d->output);
+}
+
+/*!
+ * \qmlproperty XdgOutputManagerV1 QtWaylandCompositor::XdgOutputV1::manager
+ * \readonly
+ *
+ * This property holds the object that manages this XdgOutputV1.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::manager
+ * \readonly
+ *
+ * This property holds the object that manages this QWaylandXdgOutputV1.
+ */
+QWaylandXdgOutputManagerV1 *QWaylandXdgOutputV1::manager() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->manager;
+}
+
+/*!
+ * \qmlproperty WaylandOutput QtWaylandCompositor::XdgOutputV1::output
+ * \readonly
+ *
+ * This property holds the WaylandOutput associated with this XdgOutputV1.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::output
+ * \readonly
+ *
+ * This property holds the QWaylandOutput associated with this QWaylandXdgOutputV1.
+ */
+QWaylandOutput *QWaylandXdgOutputV1::output() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->output;
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgOutputV1::name
+ *
+ * This property holds the name of this output.
+ *
+ * The naming convention is compositor defined, but limited to alphanumeric
+ * characters and dashes ("-"). Each name is unique and will also remain
+ * consistent across sessions with the same hardware and software configuration.
+ *
+ * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc...
+ * However don't assume the name reflects the underlying technology.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::name
+ *
+ * This property holds the name of this output.
+ *
+ * The naming convention is compositor defined, but limited to alphanumeric
+ * characters and dashes ("-"). Each name is unique and will also remain
+ * consistent across sessions with the same hardware and software configuration.
+ *
+ * Examples of names include "HDMI-A-1", "WL-1", "X11-1" etc...
+ * However don't assume the name reflects the underlying technology.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+QString QWaylandXdgOutputV1::name() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->name;
+}
+
+void QWaylandXdgOutputV1::setName(const QString &name)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->name == name)
+ return;
+
+ // Can't change after clients bound to xdg-output
+ if (d->initialized) {
+ qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::name cannot be changed after initialization");
+ return;
+ }
+
+ d->name = name;
+ emit nameChanged();
+}
+
+/*!
+ * \qmlproperty string QtWaylandCompositor::XdgOutputV1::description
+ *
+ * This property holds the description of this output.
+ *
+ * No convention is defined for the description.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::description
+ *
+ * This property holds the description of this output.
+ *
+ * No convention is defined for the description.
+ *
+ * Changing this property after initialization doesn't take effect.
+ */
+QString QWaylandXdgOutputV1::description() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->description;
+}
+
+void QWaylandXdgOutputV1::setDescription(const QString &description)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->description == description)
+ return;
+
+ // Can't change after clients bound to xdg-output
+ if (d->initialized) {
+ qCWarning(qLcWaylandCompositor, "QWaylandXdgOutputV1::description cannot be changed after initialization");
+ return;
+ }
+
+ d->description = description;
+ emit descriptionChanged();
+}
+
+/*!
+ * \qmlproperty point QtWaylandCompositor::XdgOutputV1::logicalPosition
+ *
+ * This property holds the coordinates of the output within the global compositor space.
+ *
+ * The default value is 0,0.
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalPosition
+ *
+ * This property holds the coordinates of the output within the global compositor space.
+ *
+ * The default value is 0,0.
+ */
+QPoint QWaylandXdgOutputV1::logicalPosition() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->logicalPos;
+}
+
+void QWaylandXdgOutputV1::setLogicalPosition(const QPoint &position)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->logicalPos == position)
+ return;
+
+ d->logicalPos = position;
+ if (d->initialized) {
+ d->sendLogicalPosition(position);
+ d->sendDone();
+ }
+ emit logicalPositionChanged();
+ emit logicalGeometryChanged();
+}
+
+/*!
+ * \qmlproperty size QtWaylandCompositor::XdgOutputV1::logicalSize
+ *
+ * This property holds the size of the output in the global compositor space.
+ *
+ * The default value is -1,-1 which is invalid.
+ *
+ * Please remember that this is the logical size, not the physical size.
+ * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2:
+ * \list
+ * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160.
+ * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080.
+ * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620.
+ * \endlist
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalSize
+ *
+ * This property holds the size of the output in the global compositor space.
+ *
+ * The default value is -1,-1 which is invalid.
+ *
+ * Please remember that this is the logical size, not the physical size.
+ * For example, for a WaylandOutput mode 3840x2160 and a scale factor 2:
+ * \list
+ * \li A compositor not scaling the surface buffers, will report a logical size of 3840x2160.
+ * \li A compositor automatically scaling the surface buffers, will report a logical size of 1920x1080.
+ * \li A compositor using a fractional scale of 1.5, will report a logical size of 2560x1620.
+ * \endlist
+ */
+QSize QWaylandXdgOutputV1::logicalSize() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return d->logicalSize;
+}
+
+void QWaylandXdgOutputV1::setLogicalSize(const QSize &size)
+{
+ Q_D(QWaylandXdgOutputV1);
+
+ if (d->logicalSize == size)
+ return;
+
+ d->logicalSize = size;
+ if (d->initialized) {
+ d->sendLogicalSize(size);
+ d->sendDone();
+ }
+ emit logicalSizeChanged();
+ emit logicalGeometryChanged();
+}
+
+/*!
+ * \qmlproperty rect QtWaylandCompositor::XdgOutputV1::logicalGeometry
+ * \readonly
+ *
+ * This property holds the position and size of the output in the global compositor space.
+ * It's the combination of the logical position and logical size.
+ *
+ * \sa XdgOutputV1::logicalPosition
+ * \sa XdgOutputV1::logicalSize
+ */
+/*!
+ * \property QWaylandXdgOutputV1::logicalGeometry
+ * \readonly
+ *
+ * This property holds the position and size of the output in the global compositor space.
+ * It's the combination of the logical position and logical size.
+ *
+ * \sa QWaylandXdgOutputV1::logicalPosition
+ * \sa QWaylandXdgOutputV1::logicalSize
+ */
+QRect QWaylandXdgOutputV1::logicalGeometry() const
+{
+ Q_D(const QWaylandXdgOutputV1);
+ return QRect(d->logicalPos, d->logicalSize);
+}
+
+// QWaylandXdgOutputV1Private
+
+void QWaylandXdgOutputV1Private::sendLogicalPosition(const QPoint &position)
+{
+ const auto values = resourceMap().values();
+ for (auto *resource : values)
+ send_logical_position(resource->handle, position.x(), position.y());
+ needToSendDone = true;
+}
+
+void QWaylandXdgOutputV1Private::sendLogicalSize(const QSize &size)
+{
+ const auto values = resourceMap().values();
+ for (auto *resource : values)
+ send_logical_size(resource->handle, size.width(), size.height());
+ needToSendDone = true;
+}
+
+void QWaylandXdgOutputV1Private::sendDone()
+{
+ if (needToSendDone) {
+ const auto values = resourceMap().values();
+ for (auto *resource : values) {
+ if (resource->version() < 3)
+ send_done(resource->handle);
+ }
+ needToSendDone = false;
+ }
+}
+
+void QWaylandXdgOutputV1Private::setManager(QWaylandXdgOutputManagerV1 *_manager)
+{
+ Q_Q(QWaylandXdgOutputV1);
+
+ if (!_manager) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a null QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p", this);
+ return;
+ }
+
+ if (manager == _manager)
+ return;
+
+ if (manager) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a different QWaylandXdgOutputManagerV1 to QWaylandXdgOutputV1 %p "
+ "after initialization", this);
+ return;
+ }
+
+ manager = _manager;
+ emit q->managerChanged();
+}
+
+void QWaylandXdgOutputV1Private::setOutput(QWaylandOutput *_output)
+{
+ Q_Q(QWaylandXdgOutputV1);
+
+ if (!_output) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a null QWaylandOutput to QWaylandXdgOutputV1 %p", this);
+ return;
+ }
+
+ if (output == _output)
+ return;
+
+ if (output) {
+ qCWarning(qLcWaylandCompositor,
+ "Cannot associate a different QWaylandOutput to QWaylandXdgOutputV1 %p "
+ "after initialization", this);
+ return;
+ }
+
+ // Assign output above manager, to make both values valid in handlers
+ output = _output;
+
+ if (!manager) {
+ // Try to find the manager from the output parents
+ for (auto *p = output->parent(); p != nullptr; p = p->parent()) {
+ if (auto *m = qobject_cast<QWaylandXdgOutputManagerV1 *>(p)) {
+ manager = m;
+ emit q->managerChanged();
+ break;
+ }
+ }
+ }
+
+ emit q->outputChanged();
+
+ // Register the output
+ if (manager)
+ QWaylandXdgOutputManagerV1Private::get(manager)->registerXdgOutput(output, q);
+}
+
+void QWaylandXdgOutputV1Private::zxdg_output_v1_bind_resource(Resource *resource)
+{
+ send_logical_position(resource->handle, logicalPos.x(), logicalPos.y());
+ send_logical_size(resource->handle, logicalSize.width(), logicalSize.height());
+ if (resource->version() >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)
+ send_name(resource->handle, name);
+ if (resource->version() >= ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION)
+ send_description(resource->handle, description);
+ send_done(resource->handle);
+
+ initialized = true;
+}
+
+void QWaylandXdgOutputV1Private::zxdg_output_v1_destroy(Resource *resource)
+{
+ wl_resource_destroy(resource->handle);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1.h b/src/compositor/extensions/qwaylandxdgoutputv1.h
new file mode 100644
index 00000000..c5f03758
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXDGOUTPUTV1_H
+#define QWAYLANDXDGOUTPUTV1_H
+
+#include <QRect>
+#include <QWaylandCompositorExtension>
+#include <QtWaylandCompositor/qwaylandquickchildren.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandOutput;
+
+class QWaylandXdgOutputManagerV1Private;
+class QWaylandXdgOutputV1Private;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputManagerV1
+ : public QWaylandCompositorExtensionTemplate<QWaylandXdgOutputManagerV1>
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgOutputManagerV1)
+public:
+ explicit QWaylandXdgOutputManagerV1();
+ QWaylandXdgOutputManagerV1(QWaylandCompositor *compositor);
+
+ void initialize() override;
+
+ static const wl_interface *interface();
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1 : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandXdgOutputV1)
+ Q_WAYLAND_COMPOSITOR_DECLARE_QUICK_CHILDREN(QWaylandXdgOutputV1)
+ Q_PROPERTY(QWaylandXdgOutputManagerV1 *manager READ manager NOTIFY managerChanged)
+ Q_PROPERTY(QWaylandOutput *output READ output NOTIFY outputChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged)
+ Q_PROPERTY(QPoint logicalPosition READ logicalPosition WRITE setLogicalPosition NOTIFY logicalPositionChanged)
+ Q_PROPERTY(QSize logicalSize READ logicalSize WRITE setLogicalSize NOTIFY logicalSizeChanged)
+ Q_PROPERTY(QRect logicalGeometry READ logicalGeometry NOTIFY logicalGeometryChanged)
+public:
+ QWaylandXdgOutputV1();
+ QWaylandXdgOutputV1(QWaylandOutput *output, QWaylandXdgOutputManagerV1 *manager);
+ ~QWaylandXdgOutputV1() override;
+
+ QWaylandXdgOutputManagerV1 *manager() const;
+ QWaylandOutput *output() const;
+
+ QString name() const;
+ void setName(const QString &name);
+
+ QString description() const;
+ void setDescription(const QString &name);
+
+ QPoint logicalPosition() const;
+ void setLogicalPosition(const QPoint &position);
+
+ QSize logicalSize() const;
+ void setLogicalSize(const QSize &size);
+
+ QRect logicalGeometry() const;
+
+Q_SIGNALS:
+ void managerChanged();
+ void outputChanged();
+ void logicalPositionChanged();
+ void logicalSizeChanged();
+ void logicalGeometryChanged();
+ void nameChanged();
+ void descriptionChanged();
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGOUTPUTV1_H
diff --git a/src/compositor/extensions/qwaylandxdgoutputv1_p.h b/src/compositor/extensions/qwaylandxdgoutputv1_p.h
new file mode 100644
index 00000000..2e8a6fff
--- /dev/null
+++ b/src/compositor/extensions/qwaylandxdgoutputv1_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXDGOUTPUTV1_P_H
+#define QWAYLANDXDGOUTPUTV1_P_H
+
+#include <QWaylandOutput>
+#include <QWaylandXdgOutputV1>
+#include <QtWaylandCompositor/private/qwaylandcompositorextension_p.h>
+#include <QtWaylandCompositor/private/qwayland-server-xdg-output-unstable-v1.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.
+//
+
+QT_BEGIN_NAMESPACE
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputManagerV1Private
+ : public QWaylandCompositorExtensionPrivate
+ , public QtWaylandServer::zxdg_output_manager_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgOutputManagerV1)
+public:
+ explicit QWaylandXdgOutputManagerV1Private() = default;
+
+ void registerXdgOutput(QWaylandOutput *output, QWaylandXdgOutputV1 *xdgOutput);
+ void unregisterXdgOutput(QWaylandOutput *output);
+
+ static QWaylandXdgOutputManagerV1Private *get(QWaylandXdgOutputManagerV1 *manager) { return manager ? manager->d_func() : nullptr; }
+
+protected:
+ void zxdg_output_manager_v1_get_xdg_output(Resource *resource, uint32_t id,
+ wl_resource *outputResource) override;
+
+private:
+ QHash<QWaylandOutput *, QWaylandXdgOutputV1 *> xdgOutputs;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandXdgOutputV1Private
+ : public QObjectPrivate
+ , public QtWaylandServer::zxdg_output_v1
+{
+ Q_DECLARE_PUBLIC(QWaylandXdgOutputV1)
+public:
+ explicit QWaylandXdgOutputV1Private() = default;
+
+ void sendLogicalPosition(const QPoint &position);
+ void sendLogicalSize(const QSize &size);
+ void sendDone();
+
+ void setManager(QWaylandXdgOutputManagerV1 *manager);
+ void setOutput(QWaylandOutput *output);
+
+ static QWaylandXdgOutputV1Private *get(QWaylandXdgOutputV1 *xdgOutput) { return xdgOutput ? xdgOutput->d_func() : nullptr; }
+
+ bool initialized = false;
+ QWaylandOutput *output = nullptr;
+ QWaylandXdgOutputManagerV1 *manager = nullptr;
+ QPoint logicalPos;
+ QSize logicalSize;
+ QString name;
+ QString description;
+ bool needToSendDone = false;
+
+protected:
+ void zxdg_output_v1_bind_resource(Resource *resource) override;
+ void zxdg_output_v1_destroy(Resource *resource) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWAYLANDXDGOUTPUTV1_P_H
diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
index cb1ee3da..ef6b2648 100644
--- a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
@@ -81,7 +81,7 @@ void ClientBuffer::setDestroyed()
m_committed = false;
m_buffer = nullptr;
- if (!m_refCount)
+ if (!m_refCount.loadAcquire())
delete this;
}
diff --git a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp
index 7514929d..23b24101 100644
--- a/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/linux-dmabuf-unstable-v1/linuxdmabufclientbufferintegration.cpp
@@ -259,22 +259,25 @@ bool LinuxDmabufClientBufferIntegration::initYuvTexture(LinuxDmabufWlBuffer *dma
LinuxDmabufClientBufferIntegration::LinuxDmabufClientBufferIntegration()
{
- m_yuvFormats.insert(DRM_FORMAT_YUYV,
- YuvFormatConversion {
- .inputPlanes = 1,
- .outputPlanes = 2,
- .plane = {{
- .format = DRM_FORMAT_GR88,
- .widthDivisor = 1,
- .heightDivisor = 1,
- .planeIndex = 0
- }, {
- .format = DRM_FORMAT_ARGB8888,
- .widthDivisor = 2,
- .heightDivisor = 1,
- .planeIndex = 0
- }}
- });
+ YuvPlaneConversion firstPlane;
+ firstPlane.format = DRM_FORMAT_GR88;
+ firstPlane.widthDivisor = 1;
+ firstPlane.heightDivisor = 1;
+ firstPlane.planeIndex = 0;
+
+ YuvPlaneConversion secondPlane;
+ secondPlane.format = DRM_FORMAT_ARGB8888;
+ secondPlane.widthDivisor = 2;
+ secondPlane.heightDivisor = 1;
+ secondPlane.planeIndex = 0;
+
+ YuvFormatConversion formatConversion;
+ formatConversion.inputPlanes = 1;
+ formatConversion.outputPlanes = 2;
+ formatConversion.plane[0] = firstPlane;
+ formatConversion.plane[1] = secondPlane;
+
+ m_yuvFormats.insert(DRM_FORMAT_YUYV, formatConversion);
}
LinuxDmabufClientBufferIntegration::~LinuxDmabufClientBufferIntegration()
diff --git a/src/imports/compositor/qwaylandquickcompositorplugin.cpp b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
index 93bab179..7b4d2b5e 100644
--- a/src/imports/compositor/qwaylandquickcompositorplugin.cpp
+++ b/src/imports/compositor/qwaylandquickcompositorplugin.cpp
@@ -66,6 +66,8 @@
#include <QtWaylandCompositor/QWaylandXdgShellV6>
#include <QtWaylandCompositor/QWaylandXdgShell>
#include <QtWaylandCompositor/QWaylandXdgDecorationManagerV1>
+#include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1>
+#include <QtWaylandCompositor/QWaylandQuickXdgOutputV1>
#include <QtWaylandCompositor/QWaylandIviApplication>
#include <QtWaylandCompositor/QWaylandIviSurface>
@@ -76,13 +78,17 @@ QT_BEGIN_NAMESPACE
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CONTAINER_CLASS(QWaylandQuickCompositor)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandQtWindowManager)
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIdleInhibitManagerV1)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandIviApplication)
+#if QT_DEPRECATED_SINCE(5, 13)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlScaler)
+#endif
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandWlShell)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV5)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShellV6)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgShell)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgDecorationManagerV1)
+Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandXdgOutputManagerV1)
Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(QWaylandTextInputManager)
class QmlUrlResolver
@@ -184,7 +190,14 @@ public:
qmlRegisterType<QWaylandXdgDecorationManagerV1QuickExtension>(uri, 1, 3, "XdgDecorationManagerV1");
+#if QT_DEPRECATED_SINCE(5, 13)
qmlRegisterType<QWaylandWlScalerQuickExtension>(uri, 1, 13, "WlScaler");
+#endif
+
+ qmlRegisterType<QWaylandIdleInhibitManagerV1QuickExtension>(uri, 1, 14, "IdleInhibitManagerV1");
+
+ qmlRegisterType<QWaylandXdgOutputManagerV1QuickExtension>(uri, 1, 14, "XdgOutputManagerV1");
+ qmlRegisterType<QWaylandQuickXdgOutputV1>(uri, 1, 14, "XdgOutputV1");
}
};
//![class decl]
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 4ff506c6..7452a928 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -1,10 +1,10 @@
TEMPLATE = subdirs
-qtHaveModule(quick): {
+qtHaveModule(quick):qtHaveModule(waylandcompositor) {
SUBDIRS += \
compositor
- qtConfig(opengl): {
+ qtConfig(opengl):qtHaveModule(waylandclient) {
SUBDIRS += \
texture-sharing \
texture-sharing-extension
diff --git a/src/plugins/hardwareintegration/hardwareintegration.pro b/src/plugins/hardwareintegration/hardwareintegration.pro
index cb7a4b26..12658adf 100644
--- a/src/plugins/hardwareintegration/hardwareintegration.pro
+++ b/src/plugins/hardwareintegration/hardwareintegration.pro
@@ -1,4 +1,4 @@
TEMPLATE=subdirs
-SUBDIRS += client
+qtHaveModule(waylandclient): SUBDIRS += client
qtHaveModule(waylandcompositor): SUBDIRS += compositor
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 9b66b851..e121d92d 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,6 +1,11 @@
TEMPLATE=subdirs
+
+qtHaveModule(waylandclient) {
+ SUBDIRS += \
+ platforms \
+ decorations \
+ shellintegration
+}
+
SUBDIRS += \
- platforms \
- hardwareintegration \
- decorations \
- shellintegration
+ hardwareintegration
diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
index 9309facc..ea725ac3 100644
--- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
+++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp
@@ -48,6 +48,8 @@
#include "qwaylandivisurface_p.h"
+#include <mutex>
+
#include <unistd.h>
QT_BEGIN_NAMESPACE
@@ -95,7 +97,7 @@ uint32_t QWaylandIviShellIntegration::getNextUniqueSurfaceId()
{
const uint32_t PID_MAX_EXPONENTIATION = 22; // 22 bit shift operation
const uint32_t ID_LIMIT = 1 << (32 - PID_MAX_EXPONENTIATION); // 10 bit is unique id
- QMutexLocker locker(&m_mutex);
+ const std::lock_guard<QRecursiveMutex> locker(m_mutex);
if (m_lastSurfaceId == 0) {
QByteArray env = qgetenv("QT_IVI_SURFACE_ID");
diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
index fc16d2f6..13282e43 100644
--- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
+++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.h
@@ -71,7 +71,7 @@ private:
uint32_t m_lastSurfaceId = 0;
uint32_t m_surfaceNumber = 0;
bool m_useEnvSurfaceId = false;
- QMutex m_mutex{QMutex::Recursive};
+ QRecursiveMutex m_mutex;
};
}
diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp
index 02bb5701..9691b857 100644
--- a/src/qtwaylandscanner/qtwaylandscanner.cpp
+++ b/src/qtwaylandscanner/qtwaylandscanner.cpp
@@ -40,7 +40,8 @@
#include <QCoreApplication>
#include <QFile>
#include <QXmlStreamReader>
-#include <QtCore/QList>
+
+#include <vector>
class Scanner
{
@@ -63,7 +64,7 @@ private:
struct WaylandEnum {
QByteArray name;
- QList<WaylandEnumEntry> entries;
+ std::vector<WaylandEnumEntry> entries;
};
struct WaylandArgument {
@@ -78,16 +79,16 @@ private:
bool request;
QByteArray name;
QByteArray type;
- QList<WaylandArgument> arguments;
+ std::vector<WaylandArgument> arguments;
};
struct WaylandInterface {
QByteArray name;
int version;
- QList<WaylandEnum> enums;
- QList<WaylandEvent> events;
- QList<WaylandEvent> requests;
+ std::vector<WaylandEnum> enums;
+ std::vector<WaylandEvent> events;
+ std::vector<WaylandEvent> requests;
};
bool isServerSide();
@@ -101,11 +102,11 @@ private:
Scanner::WaylandInterface readInterface(QXmlStreamReader &xml);
QByteArray waylandToCType(const QByteArray &waylandType, const QByteArray &interface);
QByteArray waylandToQtType(const QByteArray &waylandType, const QByteArray &interface, bool cStyleArray);
- const Scanner::WaylandArgument *newIdArgument(const QList<WaylandArgument> &arguments);
+ const Scanner::WaylandArgument *newIdArgument(const std::vector<WaylandArgument> &arguments);
void printEvent(const WaylandEvent &e, bool omitNames = false, bool withResource = false);
void printEventHandlerSignature(const WaylandEvent &e, const char *interfaceName, bool deepIndent = true);
- void printEnums(const QList<WaylandEnum> &enums);
+ void printEnums(const std::vector<WaylandEnum> &enums);
QByteArray stripInterfaceName(const QByteArray &name);
bool ignoreInterface(const QByteArray &name);
@@ -189,19 +190,22 @@ bool Scanner::boolValue(const QXmlStreamReader &xml, const char *name)
Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
{
- WaylandEvent event;
- event.request = request;
- event.name = byteArrayValue(xml, "name");
- event.type = byteArrayValue(xml, "type");
+ WaylandEvent event = {
+ .request = request,
+ .name = byteArrayValue(xml, "name"),
+ .type = byteArrayValue(xml, "type"),
+ .arguments = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "arg") {
- WaylandArgument argument;
- argument.name = byteArrayValue(xml, "name");
- argument.type = byteArrayValue(xml, "type");
- argument.interface = byteArrayValue(xml, "interface");
- argument.summary = byteArrayValue(xml, "summary");
- argument.allowNull = boolValue(xml, "allowNull");
- event.arguments << argument;
+ WaylandArgument argument = {
+ .name = byteArrayValue(xml, "name"),
+ .type = byteArrayValue(xml, "type"),
+ .interface = byteArrayValue(xml, "interface"),
+ .summary = byteArrayValue(xml, "summary"),
+ .allowNull = boolValue(xml, "allowNull"),
+ };
+ event.arguments.push_back(std::move(argument));
}
xml.skipCurrentElement();
@@ -211,16 +215,19 @@ Scanner::WaylandEvent Scanner::readEvent(QXmlStreamReader &xml, bool request)
Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
{
- WaylandEnum result;
- result.name = byteArrayValue(xml, "name");
+ WaylandEnum result = {
+ .name = byteArrayValue(xml, "name"),
+ .entries = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "entry") {
- WaylandEnumEntry entry;
- entry.name = byteArrayValue(xml, "name");
- entry.value = byteArrayValue(xml, "value");
- entry.summary = byteArrayValue(xml, "summary");
- result.entries << entry;
+ WaylandEnumEntry entry = {
+ .name = byteArrayValue(xml, "name"),
+ .value = byteArrayValue(xml, "value"),
+ .summary = byteArrayValue(xml, "summary"),
+ };
+ result.entries.push_back(std::move(entry));
}
xml.skipCurrentElement();
@@ -231,17 +238,21 @@ Scanner::WaylandEnum Scanner::readEnum(QXmlStreamReader &xml)
Scanner::WaylandInterface Scanner::readInterface(QXmlStreamReader &xml)
{
- WaylandInterface interface;
- interface.name = byteArrayValue(xml, "name");
- interface.version = intValue(xml, "version", 1);
+ WaylandInterface interface = {
+ .name = byteArrayValue(xml, "name"),
+ .version = intValue(xml, "version", 1),
+ .enums = {},
+ .events = {},
+ .requests = {},
+ };
while (xml.readNextStartElement()) {
if (xml.name() == "event")
- interface.events << readEvent(xml, false);
+ interface.events.push_back(readEvent(xml, false));
else if (xml.name() == "request")
- interface.requests << readEvent(xml, true);
+ interface.requests.push_back(readEvent(xml, true));
else if (xml.name() == "enum")
- interface.enums << readEnum(xml);
+ interface.enums.push_back(readEnum(xml));
else
xml.skipCurrentElement();
}
@@ -283,11 +294,11 @@ QByteArray Scanner::waylandToQtType(const QByteArray &waylandType, const QByteAr
return waylandToCType(waylandType, interface);
}
-const Scanner::WaylandArgument *Scanner::newIdArgument(const QList<WaylandArgument> &arguments)
+const Scanner::WaylandArgument *Scanner::newIdArgument(const std::vector<WaylandArgument> &arguments)
{
- for (int i = 0; i < arguments.size(); ++i) {
- if (arguments.at(i).type == "new_id")
- return &arguments.at(i);
+ for (const WaylandArgument &a : arguments) {
+ if (a.type == "new_id")
+ return &a;
}
return nullptr;
}
@@ -305,8 +316,7 @@ void Scanner::printEvent(const WaylandEvent &e, bool omitNames, bool withResourc
needsComma = true;
}
}
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
bool isNewId = a.type == "new_id";
if (isNewId && !isServerSide() && (a.interface.isEmpty() != e.request))
continue;
@@ -346,9 +356,8 @@ void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *inte
printf(" %svoid *data,\n", indent);
printf(" %sstruct ::%s *object", indent, interfaceName);
}
- for (int i = 0; i < e.arguments.size(); ++i) {
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
- const WaylandArgument &a = e.arguments.at(i);
bool isNewId = a.type == "new_id";
if (isServerSide() && isNewId) {
printf(" %suint32_t %s", indent, a.name.constData());
@@ -360,17 +369,13 @@ void Scanner::printEventHandlerSignature(const WaylandEvent &e, const char *inte
printf(")");
}
-void Scanner::printEnums(const QList<WaylandEnum> &enums)
+void Scanner::printEnums(const std::vector<WaylandEnum> &enums)
{
- for (int i = 0; i < enums.size(); ++i) {
+ for (const WaylandEnum &e : enums) {
printf("\n");
- const WaylandEnum &e = enums.at(i);
printf(" enum %s {\n", e.name.constData());
- for (int i = 0; i < e.entries.size(); ++i) {
- const WaylandEnumEntry &entry = e.entries.at(i);
- printf(" %s_%s = %s", e.name.constData(), entry.name.constData(), entry.value.constData());
- if (i < e.entries.size() - 1)
- printf(",");
+ for (const WaylandEnumEntry &entry : e.entries) {
+ printf(" %s_%s = %s,", e.name.constData(), entry.name.constData(), entry.value.constData());
if (!entry.summary.isNull())
printf(" // %s", entry.summary.constData());
printf("\n");
@@ -424,11 +429,11 @@ bool Scanner::process()
//QByteArray preProcessorProtocolName = QByteArray(m_protocolName).replace('-', '_').toUpper();
QByteArray preProcessorProtocolName = QByteArray(m_protocolName).toUpper();
- QList<WaylandInterface> interfaces;
+ std::vector<WaylandInterface> interfaces;
while (m_xml->readNextStartElement()) {
if (m_xml->name() == "interface")
- interfaces << readInterface(*m_xml);
+ interfaces.push_back(readInterface(*m_xml));
else
m_xml->skipCurrentElement();
}
@@ -478,12 +483,16 @@ bool Scanner::process()
printf("\n");
printf("namespace QtWaylandServer {\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
@@ -538,7 +547,7 @@ bool Scanner::process()
printEnums(interface.enums);
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
if (hasEvents) {
printf("\n");
@@ -559,7 +568,7 @@ bool Scanner::process()
printf(" virtual void %s_bind_resource(Resource *resource);\n", interfaceNameStripped);
printf(" virtual void %s_destroy_resource(Resource *resource);\n", interfaceNameStripped);
- bool hasRequests = !interface.requests.isEmpty();
+ bool hasRequests = !interface.requests.empty();
if (hasRequests) {
printf("\n");
@@ -584,8 +593,7 @@ bool Scanner::process()
printf(" static const struct ::%s_interface m_%s_interface;\n", interfaceName, interfaceName);
printf("\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
- const WaylandEvent &e = interface.requests.at(i);
+ for (const WaylandEvent &e : interface.requests) {
printf(" static void ");
printEventHandlerSignature(e, interfaceName);
@@ -603,9 +611,6 @@ bool Scanner::process()
printf(" };\n");
printf(" DisplayDestroyedListener m_displayDestroyedListener;\n");
printf(" };\n");
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
@@ -629,8 +634,7 @@ bool Scanner::process()
printf("namespace QtWaylandServer {\n");
bool needsNewLine = false;
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
@@ -778,7 +782,7 @@ bool Scanner::process()
printf(" }\n");
printf("\n");
- bool hasRequests = !interface.requests.isEmpty();
+ bool hasRequests = !interface.requests.empty();
QByteArray interfaceMember = hasRequests ? "&m_" + interface.name + "_interface" : QByteArray("nullptr");
@@ -816,11 +820,12 @@ bool Scanner::process()
if (hasRequests) {
printf("\n");
printf(" const struct ::%s_interface %s::m_%s_interface = {", interfaceName, interfaceName, interfaceName);
- for (int i = 0; i < interface.requests.size(); ++i) {
- if (i > 0)
+ bool needsComma = false;
+ for (const WaylandEvent &e : interface.requests) {
+ if (needsComma)
printf(",");
+ needsComma = true;
printf("\n");
- const WaylandEvent &e = interface.requests.at(i);
printf(" %s::handle_%s", interfaceName, e.name.constData());
}
printf("\n");
@@ -836,11 +841,10 @@ bool Scanner::process()
}
printf("\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
+ for (const WaylandEvent &e : interface.requests) {
printf("\n");
printf(" void %s::", interfaceName);
- const WaylandEvent &e = interface.requests.at(i);
printEventHandlerSignature(e, interfaceName, false);
printf("\n");
@@ -849,9 +853,8 @@ bool Scanner::process()
printf(" Resource *r = Resource::fromResource(resource);\n");
printf(" static_cast<%s *>(r->%s_object)->%s_%s(\n", interfaceName, interfaceNameStripped, interfaceNameStripped, e.name.constData());
printf(" r");
- for (int i = 0; i < e.arguments.size(); ++i) {
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
- const WaylandArgument &a = e.arguments.at(i);
QByteArray cType = waylandToCType(a.type, a.interface);
QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
const char *argumentName = a.name.constData();
@@ -865,17 +868,15 @@ bool Scanner::process()
}
}
- for (int i = 0; i < interface.events.size(); ++i) {
+ for (const WaylandEvent &e : interface.events) {
printf("\n");
- const WaylandEvent &e = interface.events.at(i);
printf(" void %s::send_", interfaceName);
printEvent(e);
printf("\n");
printf(" {\n");
printf(" send_%s(\n", e.name.constData());
printf(" m_resource->handle");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
printf(" %s", a.name.constData());
}
@@ -888,8 +889,7 @@ bool Scanner::process()
printf("\n");
printf(" {\n");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
if (a.type != "array")
continue;
QByteArray array = a.name + "_data";
@@ -905,8 +905,7 @@ bool Scanner::process()
printf(" %s_send_%s(\n", interfaceName, e.name.constData());
printf(" resource");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
printf(",\n");
QByteArray cType = waylandToCType(a.type, a.interface);
QByteArray qtType = waylandToQtType(a.type, a.interface, e.request);
@@ -962,12 +961,17 @@ bool Scanner::process()
}
printf("\n");
printf("namespace QtWayland {\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
@@ -994,7 +998,7 @@ bool Scanner::process()
printEnums(interface.enums);
- if (!interface.requests.isEmpty()) {
+ if (!interface.requests.empty()) {
printf("\n");
for (const WaylandEvent &e : interface.requests) {
const WaylandArgument *new_id = newIdArgument(e.arguments);
@@ -1011,7 +1015,7 @@ bool Scanner::process()
}
}
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
if (hasEvents) {
printf("\n");
@@ -1028,8 +1032,7 @@ bool Scanner::process()
if (hasEvents) {
printf(" void init_listener();\n");
printf(" static const struct %s_listener m_%s_listener;\n", interfaceName, interfaceName);
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
+ for (const WaylandEvent &e : interface.events) {
printf(" static void ");
printEventHandlerSignature(e, interfaceName);
@@ -1038,9 +1041,6 @@ bool Scanner::process()
}
printf(" struct ::%s *m_%s;\n", interfaceName, interfaceName);
printf(" };\n");
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
printf("\n");
@@ -1077,18 +1077,23 @@ bool Scanner::process()
printf("#endif\n");
printf("}\n");
printf("\n");
- for (int j = 0; j < interfaces.size(); ++j) {
- const WaylandInterface &interface = interfaces.at(j);
+
+ bool needsNewLine = false;
+ for (const WaylandInterface &interface : interfaces) {
if (ignoreInterface(interface.name))
continue;
+ if (needsNewLine)
+ printf("\n");
+ needsNewLine = true;
+
const char *interfaceName = interface.name.constData();
QByteArray stripped = stripInterfaceName(interface.name);
const char *interfaceNameStripped = stripped.constData();
- bool hasEvents = !interface.events.isEmpty();
+ bool hasEvents = !interface.events.empty();
printf(" %s::%s(struct ::wl_registry *registry, int id, int version)\n", interfaceName, interfaceName);
printf(" {\n");
@@ -1152,9 +1157,8 @@ bool Scanner::process()
printf(" return &::%s_interface;\n", interfaceName);
printf(" }\n");
- for (int i = 0; i < interface.requests.size(); ++i) {
+ for (const WaylandEvent &e : interface.requests) {
printf("\n");
- const WaylandEvent &e = interface.requests.at(i);
const WaylandArgument *new_id = newIdArgument(e.arguments);
QByteArray new_id_str = "void ";
if (new_id) {
@@ -1167,8 +1171,7 @@ bool Scanner::process()
printEvent(e);
printf("\n");
printf(" {\n");
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
if (a.type != "array")
continue;
QByteArray array = a.name + "_data";
@@ -1180,12 +1183,11 @@ bool Scanner::process()
printf(" %s.alloc = 0;\n", arrayName);
printf("\n");
}
- int actualArgumentCount = new_id ? e.arguments.size() - 1 : e.arguments.size();
+ int actualArgumentCount = new_id ? int(e.arguments.size()) - 1 : int(e.arguments.size());
printf(" %s%s_%s(\n", new_id ? "return " : "", interfaceName, e.name.constData());
printf(" m_%s%s", interfaceName, actualArgumentCount > 0 ? "," : "");
bool needsComma = false;
- for (int i = 0; i < e.arguments.size(); ++i) {
- const WaylandArgument &a = e.arguments.at(i);
+ for (const WaylandArgument &a : e.arguments) {
bool isNewId = a.type == "new_id";
if (isNewId && !a.interface.isEmpty())
continue;
@@ -1215,8 +1217,7 @@ bool Scanner::process()
if (hasEvents) {
printf("\n");
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
+ for (const WaylandEvent &e : interface.events) {
printf(" void %s::%s_", interfaceName, interfaceNameStripped);
printEvent(e, true);
printf("\n");
@@ -1229,17 +1230,17 @@ bool Scanner::process()
printf(" {\n");
printf(" Q_UNUSED(object);\n");
printf(" static_cast<%s *>(data)->%s_%s(", interfaceName, interfaceNameStripped, e.name.constData());
- for (int i = 0; i < e.arguments.size(); ++i) {
+ bool needsComma = false;
+ for (const WaylandArgument &a : e.arguments) {
+ if (needsComma)
+ printf(",");
+ needsComma = true;
printf("\n");
- const WaylandArgument &a = e.arguments.at(i);
const char *argumentName = a.name.constData();
if (a.type == "string")
printf(" QString::fromUtf8(%s)", argumentName);
else
printf(" %s", argumentName);
-
- if (i < e.arguments.size() - 1)
- printf(",");
}
printf(");\n");
@@ -1247,9 +1248,8 @@ bool Scanner::process()
printf("\n");
}
printf(" const struct %s_listener %s::m_%s_listener = {\n", interfaceName, interfaceName, interfaceName);
- for (int i = 0; i < interface.events.size(); ++i) {
- const WaylandEvent &e = interface.events.at(i);
- printf(" %s::handle_%s%s\n", interfaceName, e.name.constData(), i < interface.events.size() - 1 ? "," : "");
+ for (const WaylandEvent &e : interface.events) {
+ printf(" %s::handle_%s,\n", interfaceName, e.name.constData());
}
printf(" };\n");
printf("\n");
@@ -1259,9 +1259,6 @@ bool Scanner::process()
printf(" %s_add_listener(m_%s, &m_%s_listener, this);\n", interfaceName, interfaceName, interfaceName);
printf(" }\n");
}
-
- if (j < interfaces.size() - 1)
- printf("\n");
}
printf("}\n");
printf("\n");
diff --git a/src/src.pro b/src/src.pro
index d4244de3..3d68c69f 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -3,21 +3,22 @@ include($$OUT_PWD/client/qtwaylandclient-config.pri)
include($$OUT_PWD/compositor/qtwaylandcompositor-config.pri)
QT_FOR_CONFIG += waylandclient-private waylandcompositor-private
-qtConfig(wayland-client) {
+qtConfig(wayland-client)|qtConfig(wayland-server) {
sub_qtwaylandscanner.subdir = qtwaylandscanner
sub_qtwaylandscanner.target = sub-qtwaylandscanner
SUBDIRS += sub_qtwaylandscanner
- sub_client.subdir = client
- sub_client.depends = sub-qtwaylandscanner
- sub_client.target = sub-client
- SUBDIRS += sub_client
+ qtConfig(wayland-client) {
+ sub_client.subdir = client
+ sub_client.depends = sub-qtwaylandscanner
+ sub_client.target = sub-client
+ SUBDIRS += sub_client
+ }
sub_plugins.subdir = plugins
- sub_plugins.depends += sub-qtwaylandscanner sub-client
- qtConfig(wayland-server) {
- sub_plugins.depends += sub-compositor
- }
+ sub_plugins.depends += sub-qtwaylandscanner
+ qtConfig(wayland-client):sub_plugins.depends += sub-client
+ qtConfig(wayland-server):sub_plugins.depends += sub-compositor
sub_plugins.target = sub-plugins
SUBDIRS += sub_plugins
@@ -26,10 +27,11 @@ qtConfig(wayland-client) {
sub_compositor.depends = sub-qtwaylandscanner
sub_compositor.target = sub-compositor
SUBDIRS += sub_compositor
-
- sub_imports.subdir = imports
- sub_imports.depends += sub-compositor sub-client
- sub_imports.target = sub-imports
- SUBDIRS += sub_imports
}
+
+ sub_imports.subdir = imports
+ qtConfig(wayland-client):sub_imports.depends += sub-client
+ qtConfig(wayland-server):sub_imports.depends += sub-compositor
+ sub_imports.target = sub-imports
+ SUBDIRS += sub_imports
}
diff --git a/sync.profile b/sync.profile
index 4d9099e9..5c7ada91 100644
--- a/sync.profile
+++ b/sync.profile
@@ -57,6 +57,7 @@
"$basedir/src/compositor" => [
"^qwayland-server-wayland.h",
"^qwayland-server-hardware-integration.h",
+ "^qwayland-server-idle-inhibit-unstable-v1.h",
"^qwayland-server-ivi-application.h",
"^qwayland-server-qt-windowmanager.h",
"^qwayland-server-qt-key-unstable-v1.h",
@@ -67,9 +68,11 @@
"^qwayland-server-touch-extension.h",
"^qwayland-server-viewporter.h",
"^qwayland-server-xdg-decoration-unstable-v1.h",
+ "^qwayland-server-xdg-output-unstable-v1.h",
"^qwayland-server-xdg-shell-unstable-v6.h",
"^qwayland-server-xdg-shell.h",
"^wayland-hardware-integration-server-protocol.h",
+ "^wayland-idle-inhibit-unstable-v1-server-protocol.h",
"^wayland-ivi-application-server-protocol.h",
"^wayland-qt-windowmanager-server-protocol.h",
"^wayland-qt-key-unstable-v1-server-protocol.h",
@@ -81,6 +84,7 @@
"^wayland-touch-extension-server-protocol.h",
"^wayland-wayland-server-protocol.h",
"^wayland-xdg-decoration-unstable-v1-server-protocol.h",
+ "^wayland-xdg-output-unstable-v1-server-protocol.h",
"^wayland-xdg-shell-server-protocol.h",
"^wayland-xdg-shell-unstable-v6-server-protocol.h",
],
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 4ae3b4f6..032ae47a 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -1,10 +1,10 @@
TEMPLATE=subdirs
QT_FOR_CONFIG += waylandclient-private
-qtConfig(wayland-client): \
+qtHaveModule(waylandclient): \
SUBDIRS += client
-qtConfig(wayland-client):qtHaveModule(waylandcompositor): \
+qtHaveModule(waylandclient):qtHaveModule(waylandcompositor): \
SUBDIRS += cmake
qtHaveModule(waylandcompositor): \
diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
index fe68d520..35ac7252 100644
--- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
+++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
@@ -66,7 +66,7 @@ void tst_datadevicev1::initTestCase()
{
QCOMPOSITOR_TRY_VERIFY(pointer());
QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty());
- QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 4);
+ QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5);
QCOMPOSITOR_TRY_VERIFY(keyboard());
@@ -104,8 +104,11 @@ void tst_datadevicev1::pasteAscii()
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client);
pointer()->sendButton(client, BTN_LEFT, 1);
+ pointer()->sendFrame(client);
pointer()->sendButton(client, BTN_LEFT, 0);
+ pointer()->sendFrame(client);
});
QTRY_COMPARE(window.m_text, "normal ascii");
}
@@ -139,8 +142,11 @@ void tst_datadevicev1::pasteUtf8()
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client);
pointer()->sendButton(client, BTN_LEFT, 1);
+ pointer()->sendFrame(client);
pointer()->sendButton(client, BTN_LEFT, 0);
+ pointer()->sendFrame(client);
});
QTRY_COMPARE(window.m_text, "face with tears of joy: 😂");
}
diff --git a/tests/auto/client/inputcontext/inputcontext.pro b/tests/auto/client/inputcontext/inputcontext.pro
index 4419b3e7..1971d455 100644
--- a/tests/auto/client/inputcontext/inputcontext.pro
+++ b/tests/auto/client/inputcontext/inputcontext.pro
@@ -1,6 +1,4 @@
include (../shared/shared.pri)
-QT += waylandcompositor
-
TARGET = tst_inputcontext
SOURCES += tst_inputcontext.cpp
diff --git a/tests/auto/client/output/tst_output.cpp b/tests/auto/client/output/tst_output.cpp
index 2d2c8efd..29c773cf 100644
--- a/tests/auto/client/output/tst_output.cpp
+++ b/tests/auto/client/output/tst_output.cpp
@@ -196,8 +196,11 @@ void tst_output::removePrimaryScreen()
exec([&] {
auto *surface = xdgToplevel()->surface();
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_LEFT, 1);
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_LEFT, 0);
+ pointer()->sendFrame(client());
});
// Wait to make sure mouse events dont't cause a crash now that the screen has changed
diff --git a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp
index 281e4c5d..216db85c 100644
--- a/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp
+++ b/tests/auto/client/primaryselectionv1/tst_primaryselectionv1.cpp
@@ -268,7 +268,7 @@ void tst_primaryselectionv1::initTestCase()
{
QCOMPOSITOR_TRY_VERIFY(pointer());
QCOMPOSITOR_TRY_VERIFY(!pointer()->resourceMap().empty());
- QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 4);
+ QCOMPOSITOR_TRY_COMPARE(pointer()->resourceMap().first()->version(), 5);
QCOMPOSITOR_TRY_VERIFY(keyboard());
}
@@ -329,8 +329,11 @@ void tst_primaryselectionv1::pasteAscii()
device->sendSelection(offer);
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_MIDDLE, 1);
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_MIDDLE, 0);
+ pointer()->sendFrame(client());
});
QTRY_COMPARE(window.m_formats, QStringList{"text/plain"});
QTRY_COMPARE(window.m_text, "normal ascii");
@@ -372,8 +375,11 @@ void tst_primaryselectionv1::pasteUtf8()
device->sendSelection(offer);
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_MIDDLE, 1);
+ pointer()->sendFrame(client());
pointer()->sendButton(client(), BTN_MIDDLE, 0);
+ pointer()->sendFrame(client());
});
QTRY_COMPARE(window.m_formats, QStringList({"text/plain", "text/plain;charset=utf-8"}));
QTRY_COMPARE(window.m_text, "face with tears of joy: 😂");
@@ -428,8 +434,11 @@ void tst_primaryselectionv1::copy()
auto *surface = xdgSurface()->m_surface;
keyboard()->sendEnter(surface); // Need to set keyboard focus according to protocol
pointer()->sendEnter(surface, {32, 32});
+ pointer()->sendFrame(client());
mouseSerials << pointer()->sendButton(client(), BTN_MIDDLE, 1);
+ pointer()->sendFrame(client());
mouseSerials << pointer()->sendButton(client(), BTN_MIDDLE, 0);
+ pointer()->sendFrame(client());
});
QCOMPOSITOR_TRY_VERIFY(primarySelectionDevice()->m_selectionSource);
QCOMPOSITOR_TRY_VERIFY(mouseSerials.contains(primarySelectionDevice()->m_serial));
diff --git a/tests/auto/client/seatv4/tst_seatv4.cpp b/tests/auto/client/seatv4/tst_seatv4.cpp
index 77304dea..40f8742a 100644
--- a/tests/auto/client/seatv4/tst_seatv4.cpp
+++ b/tests/auto/client/seatv4/tst_seatv4.cpp
@@ -212,22 +212,20 @@ void tst_seatv4::simpleAxis_data()
{
QTest::addColumn<uint>("axis");
QTest::addColumn<qreal>("value");
- QTest::addColumn<Qt::Orientation>("orientation");
QTest::addColumn<QPoint>("angleDelta");
// Directions in regular windows/linux terms (no "natural" scrolling)
- QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << Qt::Vertical << QPoint{0, -12};
- QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << Qt::Vertical << QPoint{0, 12};
- QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << Qt::Horizontal << QPoint{-12, 0};
- QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << Qt::Horizontal << QPoint{12, 0};
- QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << Qt::Vertical << QPoint{0, 120};
+ QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12};
+ QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12};
+ QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0};
+ QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0};
+ QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120};
}
void tst_seatv4::simpleAxis()
{
QFETCH(uint, axis);
QFETCH(qreal, value);
- QFETCH(Qt::Orientation, orientation);
QFETCH(QPoint, angleDelta);
class WheelWindow : QRasterWindow {
@@ -256,27 +254,18 @@ void tst_seatv4::simpleAxis()
// We didn't press any buttons
QCOMPARE(event->buttons(), Qt::NoButton);
- if (event->orientation() == Qt::Horizontal)
- QCOMPARE(event->delta(), event->angleDelta().x());
- else
- QCOMPARE(event->delta(), event->angleDelta().y());
-
// There has been no information about what created the event.
// Documentation says not synthesized is appropriate in such cases
QCOMPARE(event->source(), Qt::MouseEventNotSynthesized);
- m_events.append(Event(event->pixelDelta(), event->angleDelta(), event->orientation()));
+ m_events.append(Event{event->pixelDelta(), event->angleDelta()});
}
struct Event // Because I didn't find a convenient way to copy it entirely
{
- // TODO: Constructors can be removed when we start supporting brace-initializers
Event() = default;
- Event(const QPoint &pixelDelta, const QPoint &angleDelta, Qt::Orientation orientation)
- : pixelDelta(pixelDelta), angleDelta(angleDelta), orientation(orientation)
- {}
+
const QPoint pixelDelta;
const QPoint angleDelta; // eights of a degree, positive is upwards, left
- const Qt::Orientation orientation{};
};
QVector<Event> m_events;
};
@@ -299,7 +288,6 @@ void tst_seatv4::simpleAxis()
QTRY_COMPARE(window.m_events.size(), 1);
auto event = window.m_events.takeFirst();
QCOMPARE(event.angleDelta, angleDelta);
- QCOMPARE(event.orientation, orientation);
}
void tst_seatv4::invalidPointerEvents()
diff --git a/tests/auto/client/seatv5/tst_seatv5.cpp b/tests/auto/client/seatv5/tst_seatv5.cpp
index 5b9235d9..ca8de31a 100644
--- a/tests/auto/client/seatv5/tst_seatv5.cpp
+++ b/tests/auto/client/seatv5/tst_seatv5.cpp
@@ -41,18 +41,11 @@ public:
removeAll<Seat>();
- uint capabilities = MockCompositor::Seat::capability_pointer;
+ uint capabilities = MockCompositor::Seat::capability_pointer | MockCompositor::Seat::capability_touch;
int version = 5;
add<Seat>(capabilities, version);
});
}
-
- Pointer *pointer()
- {
- auto *seat = get<Seat>();
- Q_ASSERT(seat);
- return seat->m_pointer;
- }
};
class tst_seatv5 : public QObject, private SeatV5Compositor
@@ -61,6 +54,8 @@ class tst_seatv5 : public QObject, private SeatV5Compositor
private slots:
void cleanup() { QTRY_VERIFY2(isClean(), qPrintable(dirtyMessage())); }
void bindsToSeat();
+
+ // Pointer tests
void createsPointer();
void setsCursorOnEnter();
void usesEnterSerial();
@@ -69,6 +64,10 @@ private slots:
void fingerScroll();
void fingerScrollSlow();
void wheelDiscreteScroll();
+
+ // Touch tests
+ void createsTouch();
+ void singleTap();
};
void tst_seatv5::bindsToSeat()
@@ -128,12 +127,8 @@ public:
QRasterWindow::wheelEvent(event);
// qDebug() << event << "angleDelta" << event->angleDelta() << "pixelDelta" << event->pixelDelta();
- if (event->phase() == Qt::ScrollUpdate || event->phase() == Qt::NoScrollPhase) {
- // Angle delta should always be provided (says docs, but QPA sends compatibility events
- // for Qt4 with zero angleDelta, and with a delta)
- QVERIFY(!event->angleDelta().isNull() || event->delta());
- } else {
- // Shouldn't have deltas in the other phases
+ if (event->phase() != Qt::ScrollUpdate && event->phase() != Qt::NoScrollPhase) {
+ // Shouldn't have deltas in the these phases
QCOMPARE(event->angleDelta(), QPoint(0, 0));
QCOMPARE(event->pixelDelta(), QPoint(0, 0));
}
@@ -145,13 +140,6 @@ public:
// We didn't press any buttons
QCOMPARE(event->buttons(), Qt::NoButton);
- if (!event->angleDelta().isNull()) {
- if (event->orientation() == Qt::Horizontal)
- QCOMPARE(event->delta(), event->angleDelta().x());
- else
- QCOMPARE(event->delta(), event->angleDelta().y());
- }
-
m_events.append(Event{event});
}
struct Event // Because I didn't find a convenient way to copy it entirely
@@ -161,14 +149,12 @@ public:
: phase(event->phase())
, pixelDelta(event->pixelDelta())
, angleDelta(event->angleDelta())
- , orientation(event->orientation())
, source(event->source())
{
}
const Qt::ScrollPhase phase{};
const QPoint pixelDelta;
const QPoint angleDelta; // eights of a degree, positive is upwards, left
- const Qt::Orientation orientation{};
const Qt::MouseEventSource source{};
};
QVector<Event> m_events;
@@ -178,22 +164,20 @@ void tst_seatv5::simpleAxis_data()
{
QTest::addColumn<uint>("axis");
QTest::addColumn<qreal>("value");
- QTest::addColumn<Qt::Orientation>("orientation");
QTest::addColumn<QPoint>("angleDelta");
// Directions in regular windows/linux terms (no "natural" scrolling)
- QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << Qt::Vertical << QPoint{0, -12};
- QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << Qt::Vertical << QPoint{0, 12};
- QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << Qt::Horizontal << QPoint{-12, 0};
- QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << Qt::Horizontal << QPoint{12, 0};
- QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << Qt::Vertical << QPoint{0, 120};
+ QTest::newRow("down") << uint(Pointer::axis_vertical_scroll) << 1.0 << QPoint{0, -12};
+ QTest::newRow("up") << uint(Pointer::axis_vertical_scroll) << -1.0 << QPoint{0, 12};
+ QTest::newRow("left") << uint(Pointer::axis_horizontal_scroll) << 1.0 << QPoint{-12, 0};
+ QTest::newRow("right") << uint(Pointer::axis_horizontal_scroll) << -1.0 << QPoint{12, 0};
+ QTest::newRow("up big") << uint(Pointer::axis_vertical_scroll) << -10.0 << QPoint{0, 120};
}
void tst_seatv5::simpleAxis()
{
QFETCH(uint, axis);
QFETCH(qreal, value);
- QFETCH(Qt::Orientation, orientation);
QFETCH(QPoint, angleDelta);
WheelWindow window;
@@ -220,7 +204,6 @@ void tst_seatv5::simpleAxis()
// There has been no information about what created the event.
// Documentation says not synthesized is appropriate in such cases
QCOMPARE(e.source, Qt::MouseEventNotSynthesized);
- QCOMPARE(e.orientation, orientation);
QCOMPARE(e.angleDelta, angleDelta);
}
@@ -263,7 +246,7 @@ void tst_seatv5::fingerScroll()
{
auto e = window.m_events.takeFirst();
QCOMPARE(e.phase, Qt::ScrollUpdate);
- QCOMPARE(e.orientation, Qt::Vertical);
+ QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll
// QCOMPARE(e.angleDelta, angleDelta); // TODO: what should this be?
QCOMPARE(e.pixelDelta, QPoint(0, 10));
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
@@ -281,7 +264,7 @@ void tst_seatv5::fingerScroll()
{
auto e = window.m_events.takeFirst();
QCOMPARE(e.phase, Qt::ScrollUpdate);
- QCOMPARE(e.orientation, Qt::Horizontal);
+ QVERIFY(qAbs(e.angleDelta.x()) > qAbs(e.angleDelta.y())); // Horizontal scroll
QCOMPARE(e.pixelDelta, QPoint(10, 0));
QCOMPARE(e.source, Qt::MouseEventSynthesizedBySystem); // A finger is not a wheel
}
@@ -373,7 +356,7 @@ void tst_seatv5::wheelDiscreteScroll()
{
auto e = window.m_events.takeFirst();
QCOMPARE(e.phase, Qt::NoScrollPhase);
- QCOMPARE(e.orientation, Qt::Vertical);
+ QVERIFY(qAbs(e.angleDelta.x()) <= qAbs(e.angleDelta.y())); // Vertical scroll
// According to the docs the angle delta is in eights of a degree and most mice have
// 1 click = 15 degrees. The angle delta should therefore be:
// 15 degrees / (1/8 eights per degrees) = 120 eights of degrees.
@@ -383,5 +366,70 @@ void tst_seatv5::wheelDiscreteScroll()
}
}
+void tst_seatv5::createsTouch()
+{
+ QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().size(), 1);
+ QCOMPOSITOR_TRY_COMPARE(touch()->resourceMap().first()->version(), 5);
+}
+
+class TouchWindow : public QRasterWindow {
+public:
+ TouchWindow()
+ {
+ resize(64, 64);
+ show();
+ }
+ void touchEvent(QTouchEvent *event) override
+ {
+ QRasterWindow::touchEvent(event);
+ m_events.append(Event{event});
+ }
+ struct Event // Because I didn't find a convenient way to copy it entirely
+ {
+ explicit Event() = default;
+ explicit Event(const QTouchEvent *event)
+ : type(event->type())
+ , touchPointStates(event->touchPointStates())
+ , touchPoints(event->touchPoints())
+ {
+ }
+ const QEvent::Type type{};
+ const Qt::TouchPointStates touchPointStates{};
+ const QList<QTouchEvent::TouchPoint> touchPoints;
+ };
+ QVector<Event> m_events;
+};
+
+void tst_seatv5::singleTap()
+{
+ TouchWindow window;
+ QCOMPOSITOR_TRY_VERIFY(xdgSurface() && xdgSurface()->m_committedConfigureSerial);
+
+ exec([=] {
+ auto *t = touch();
+ auto *c = client();
+ t->sendDown(xdgToplevel()->surface(), {32, 32}, 1);
+ t->sendFrame(c);
+ t->sendUp(c, 1);
+ t->sendFrame(c);
+ });
+
+ QTRY_VERIFY(!window.m_events.empty());
+ {
+ auto e = window.m_events.takeFirst();
+ QCOMPARE(e.type, QEvent::TouchBegin);
+ QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointPressed);
+ QCOMPARE(e.touchPoints.length(), 1);
+ QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
+ }
+ {
+ auto e = window.m_events.takeFirst();
+ QCOMPARE(e.type, QEvent::TouchEnd);
+ QCOMPARE(e.touchPointStates, Qt::TouchPointState::TouchPointReleased);
+ QCOMPARE(e.touchPoints.length(), 1);
+ QCOMPARE(e.touchPoints.first().pos(), QPointF(32-window.frameMargins().left(), 32-window.frameMargins().top()));
+ }
+}
+
QCOMPOSITOR_TEST_MAIN(tst_seatv5)
#include "tst_seatv5.moc"
diff --git a/tests/auto/client/shared/coreprotocol.cpp b/tests/auto/client/shared/coreprotocol.cpp
index f9335e78..120c256c 100644
--- a/tests/auto/client/shared/coreprotocol.cpp
+++ b/tests/auto/client/shared/coreprotocol.cpp
@@ -191,12 +191,15 @@ Seat::~Seat()
{
qDeleteAll(m_oldPointers);
delete m_pointer;
+
+ qDeleteAll(m_oldTouchs);
+ delete m_touch;
+
+ qDeleteAll(m_oldKeyboards);
+ delete m_keyboard;
}
void Seat::setCapabilities(uint capabilities) {
- // TODO: Add support for touch
- Q_ASSERT(~capabilities & capability_touch);
-
m_capabilities = capabilities;
if (m_capabilities & capability_pointer) {
@@ -207,6 +210,14 @@ void Seat::setCapabilities(uint capabilities) {
m_pointer = nullptr;
}
+ if (m_capabilities & capability_touch) {
+ if (!m_touch)
+ m_touch = (new Touch(this));
+ } else if (m_touch) {
+ m_oldTouchs << m_touch;
+ m_touch = nullptr;
+ }
+
if (m_capabilities & capability_keyboard) {
if (!m_keyboard)
m_keyboard = (new Keyboard(this));
@@ -234,9 +245,24 @@ void Seat::seat_get_pointer(Resource *resource, uint32_t id)
m_pointer->add(resource->client(), id, resource->version());
}
+void Seat::seat_get_touch(QtWaylandServer::wl_seat::Resource *resource, uint32_t id)
+{
+ if (~m_capabilities & capability_touch) {
+ qWarning() << "Client requested a wl_touch without the capability being available."
+ << "This Could be a race condition when hotunplugging,"
+ << "but is most likely a client error";
+ Touch *touch = new Touch(this);
+ touch->add(resource->client(), id, resource->version());
+ // TODO: mark as destroyed
+ m_oldTouchs << touch;
+ return;
+ }
+ m_touch->add(resource->client(), id, resource->version());
+}
+
void Seat::seat_get_keyboard(QtWaylandServer::wl_seat::Resource *resource, uint32_t id)
{
- if (~m_capabilities & capability_pointer) {
+ if (~m_capabilities & capability_keyboard) {
qWarning() << "Client requested a wl_keyboard without the capability being available."
<< "This Could be a race condition when hotunplugging,"
<< "but is most likely a client error";
@@ -371,6 +397,40 @@ void Pointer::pointer_set_cursor(Resource *resource, uint32_t serial, wl_resourc
emit setCursor(serial);
}
+uint Touch::sendDown(Surface *surface, const QPointF &position, int id)
+{
+ wl_fixed_t x = wl_fixed_from_double(position.x());
+ wl_fixed_t y = wl_fixed_from_double(position.y());
+ uint serial = m_seat->m_compositor->nextSerial();
+ auto time = m_seat->m_compositor->currentTimeMilliseconds();
+ wl_client *client = surface->resource()->client();
+
+ const auto touchResources = resourceMap().values(client);
+ for (auto *r : touchResources)
+ wl_touch::send_down(r->handle, serial, time, surface->resource()->handle, id, x, y);
+
+ return serial;
+}
+
+uint Touch::sendUp(wl_client *client, int id)
+{
+ uint serial = m_seat->m_compositor->nextSerial();
+ auto time = m_seat->m_compositor->currentTimeMilliseconds();
+
+ const auto touchResources = resourceMap().values(client);
+ for (auto *r : touchResources)
+ wl_touch::send_up(r->handle, serial, time, id);
+
+ return serial;
+}
+
+void Touch::sendFrame(wl_client *client)
+{
+ const auto touchResources = resourceMap().values(client);
+ for (auto *r : touchResources)
+ send_frame(r->handle);
+}
+
uint Keyboard::sendEnter(Surface *surface)
{
auto serial = m_seat->m_compositor->nextSerial();
diff --git a/tests/auto/client/shared/coreprotocol.h b/tests/auto/client/shared/coreprotocol.h
index 264c5f69..50812c29 100644
--- a/tests/auto/client/shared/coreprotocol.h
+++ b/tests/auto/client/shared/coreprotocol.h
@@ -38,6 +38,7 @@ namespace MockCompositor {
class WlCompositor;
class Output;
class Pointer;
+class Touch;
class Keyboard;
class CursorRole;
class ShmPool;
@@ -236,7 +237,7 @@ class Seat : public Global, public QtWaylandServer::wl_seat
{
Q_OBJECT
public:
- explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard, int version = 4);
+ explicit Seat(CoreCompositor *compositor, uint capabilities = Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch, int version = 5);
~Seat() override;
void send_capabilities(Resource *resource, uint capabilities) = delete; // Use wrapper instead
void send_capabilities(uint capabilities) = delete; // Use wrapper instead
@@ -247,6 +248,9 @@ public:
Pointer* m_pointer = nullptr;
QVector<Pointer *> m_oldPointers;
+ Touch* m_touch = nullptr;
+ QVector<Touch *> m_oldTouchs;
+
Keyboard* m_keyboard = nullptr;
QVector<Keyboard *> m_oldKeyboards;
@@ -259,8 +263,8 @@ protected:
}
void seat_get_pointer(Resource *resource, uint32_t id) override;
+ void seat_get_touch(Resource *resource, uint32_t id) override;
void seat_get_keyboard(Resource *resource, uint32_t id) override;
-// void seat_get_touch(Resource *resource, uint32_t id) override;
// void seat_release(Resource *resource) override;
};
@@ -307,6 +311,18 @@ public:
Surface *m_surface = nullptr;
};
+class Touch : public QObject, public QtWaylandServer::wl_touch
+{
+ Q_OBJECT
+public:
+ explicit Touch(Seat *seat) : m_seat(seat) {}
+ uint sendDown(Surface *surface, const QPointF &position, int id);
+ uint sendUp(wl_client *client, int id);
+ void sendFrame(wl_client *client);
+
+ Seat *m_seat = nullptr;
+};
+
class Keyboard : public QObject, public QtWaylandServer::wl_keyboard
{
Q_OBJECT
diff --git a/tests/auto/client/shared/mockcompositor.cpp b/tests/auto/client/shared/mockcompositor.cpp
index 6b9af429..5f2d8907 100644
--- a/tests/auto/client/shared/mockcompositor.cpp
+++ b/tests/auto/client/shared/mockcompositor.cpp
@@ -41,7 +41,7 @@ DefaultCompositor::DefaultCompositor()
add<SubCompositor>();
auto *output = add<Output>();
output->m_data.physicalSize = output->m_data.mode.physicalSizeForDpi(96);
- add<Seat>(Seat::capability_pointer | Seat::capability_keyboard);
+ add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
add<XdgWmBase>();
add<Shm>();
// TODO: other shells, viewporter, xdgoutput etc
diff --git a/tests/auto/client/shared/mockcompositor.h b/tests/auto/client/shared/mockcompositor.h
index aa85a4ae..3cb9b337 100644
--- a/tests/auto/client/shared/mockcompositor.h
+++ b/tests/auto/client/shared/mockcompositor.h
@@ -60,6 +60,7 @@ public:
XdgToplevel *xdgToplevel(int i = 0) { return get<XdgWmBase>()->toplevel(i); }
XdgPopup *xdgPopup(int i = 0) { return get<XdgWmBase>()->popup(i); }
Pointer *pointer() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_pointer; }
+ Touch *touch() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_touch; }
Surface *cursorSurface() { auto *p = pointer(); return p ? p->cursorSurface() : nullptr; }
Keyboard *keyboard() { auto *seat = get<Seat>(); Q_ASSERT(seat); return seat->m_keyboard; }
uint sendXdgShellPing();
diff --git a/tests/auto/client/xdgshell/tst_xdgshell.cpp b/tests/auto/client/xdgshell/tst_xdgshell.cpp
index 038ff662..ac5c2498 100644
--- a/tests/auto/client/xdgshell/tst_xdgshell.cpp
+++ b/tests/auto/client/xdgshell/tst_xdgshell.cpp
@@ -214,12 +214,13 @@ void tst_xdgshell::popup()
uint clickSerial = exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
+ auto *c = client();
p->sendEnter(surface, {100, 100});
-// p->sendFrame(); //TODO: uncomment when we support seat v5
+ p->sendFrame(c);
uint serial = p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
- p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
+ p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
return serial;
-// p->sendFrame(); //TODO: uncomment when we support seat v5
+ p->sendFrame(c);
});
QTRY_VERIFY(window.m_popup);
@@ -298,13 +299,14 @@ void tst_xdgshell::tooltipOnPopup()
exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
+ auto *c = client();
p->sendEnter(surface, {100, 100});
-// p->sendFrame(); //TODO: uncomment when we support seat v5
+ p->sendFrame(c);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
-// p->sendFrame();
+ p->sendFrame(c);
p->sendLeave(surface);
-// p->sendFrame();
+ p->sendFrame(c);
});
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
@@ -315,11 +317,12 @@ void tst_xdgshell::tooltipOnPopup()
exec([=] {
auto *surface = xdgPopup()->surface();
auto *p = pointer();
+ auto *c = client();
p->sendEnter(surface, {100, 100});
-// p->sendFrame();
+ p->sendFrame(c);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
-// p->sendFrame();
+ p->sendFrame(c);
});
QCOMPOSITOR_TRY_VERIFY(xdgPopup(1));
@@ -380,13 +383,14 @@ void tst_xdgshell::switchPopups()
exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
+ auto *c = client();
p->sendEnter(surface, {100, 100});
-// p->sendFrame(); //TODO: uncomment when we support seat v5
- p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
- p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
-// p->sendFrame();
+ p->sendFrame(c);
+ p->sendButton(c, BTN_LEFT, Pointer::button_state_pressed);
+ p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
+ p->sendFrame(c);
p->sendLeave(surface);
-// p->sendFrame();
+ p->sendFrame(c);
});
QCOMPOSITOR_TRY_VERIFY(xdgPopup());
@@ -399,11 +403,12 @@ void tst_xdgshell::switchPopups()
exec([=] {
auto *surface = xdgToplevel()->surface();
auto *p = pointer();
+ auto *c = client();
p->sendEnter(surface, {100, 100});
-// p->sendFrame();
- p->sendButton(client(), BTN_LEFT, Pointer::button_state_pressed);
- p->sendButton(client(), BTN_LEFT, Pointer::button_state_released);
-// p->sendFrame();
+ p->sendFrame(c);
+ p->sendButton(c, BTN_LEFT, Pointer::button_state_pressed);
+ p->sendButton(c, BTN_LEFT, Pointer::button_state_released);
+ p->sendFrame(c);
});
// The client will now hide one popup and then show another
@@ -476,10 +481,14 @@ void tst_xdgshell::windowGeometry()
exec([=] { xdgToplevel()->sendCompleteConfigure(); });
- QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committed.windowGeometry, QRect(QPoint(0, 0), window.frameGeometry().size()));
+ QSize marginsSize;
+ marginsSize.setWidth(window.frameMargins().left() + window.frameMargins().right());
+ marginsSize.setHeight(window.frameMargins().top() + window.frameMargins().bottom());
+
+ QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committed.windowGeometry, QRect(QPoint(0, 0), QSize(400, 320) + marginsSize));
window.resize(800, 600);
- QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committed.windowGeometry, QRect(QPoint(0, 0), window.frameGeometry().size()));
+ QCOMPOSITOR_TRY_COMPARE(xdgSurface()->m_committed.windowGeometry, QRect(QPoint(0, 0), QSize(800, 600) + marginsSize));
}
void tst_xdgshell::foreignSurface()
diff --git a/tests/auto/compositor/compositor/compositor.pro b/tests/auto/compositor/compositor/compositor.pro
index 500a92c6..27001659 100644
--- a/tests/auto/compositor/compositor/compositor.pro
+++ b/tests/auto/compositor/compositor/compositor.pro
@@ -14,7 +14,9 @@ WAYLANDCLIENTSOURCES += \
../../../../src/3rdparty/protocol/ivi-application.xml \
../../../../src/3rdparty/protocol/wayland.xml \
../../../../src/3rdparty/protocol/xdg-shell.xml \
- ../../../../src/3rdparty/protocol/viewporter.xml
+ ../../../../src/3rdparty/protocol/viewporter.xml \
+ ../../../../src/3rdparty/protocol/idle-inhibit-unstable-v1.xml \
+ ../../../../src/3rdparty/protocol/xdg-output-unstable-v1.xml
SOURCES += \
tst_compositor.cpp \
@@ -24,7 +26,8 @@ SOURCES += \
mockseat.cpp \
testseat.cpp \
mockkeyboard.cpp \
- mockpointer.cpp
+ mockpointer.cpp \
+ mockxdgoutputv1.cpp
HEADERS += \
testcompositor.h \
@@ -33,4 +36,5 @@ HEADERS += \
mockseat.h \
testseat.h \
mockkeyboard.h \
- mockpointer.h
+ mockpointer.h \
+ mockxdgoutputv1.h
diff --git a/tests/auto/compositor/compositor/mockclient.cpp b/tests/auto/compositor/compositor/mockclient.cpp
index fa4d4c6b..27d1eed8 100644
--- a/tests/auto/compositor/compositor/mockclient.cpp
+++ b/tests/auto/compositor/compositor/mockclient.cpp
@@ -184,11 +184,19 @@ void MockClient::handleGlobal(uint32_t id, const QByteArray &interface)
} else if (interface == "wl_seat") {
wl_seat *s = static_cast<wl_seat *>(wl_registry_bind(registry, id, &wl_seat_interface, 1));
m_seats << new MockSeat(s);
+ } else if (interface == "zwp_idle_inhibit_manager_v1") {
+ idleInhibitManager = static_cast<zwp_idle_inhibit_manager_v1 *>(wl_registry_bind(registry, id, &zwp_idle_inhibit_manager_v1_interface, 1));
+ } else if (interface == "zxdg_output_manager_v1") {
+ xdgOutputManager = new QtWayland::zxdg_output_manager_v1(registry, id, 2);
}
}
void MockClient::handleGlobalRemove(uint32_t id)
{
+ auto *output = m_outputs[id];
+ if (m_xdgOutputs.contains(output))
+ delete m_xdgOutputs.take(output);
+
m_outputs.remove(id);
}
@@ -222,6 +230,23 @@ ivi_surface *MockClient::createIviSurface(wl_surface *surface, uint iviId)
return ivi_application_surface_create(iviApplication, iviId, surface);
}
+zwp_idle_inhibitor_v1 *MockClient::createIdleInhibitor(wl_surface *surface)
+{
+ flushDisplay();
+
+ auto *idleInhibitor = zwp_idle_inhibit_manager_v1_create_inhibitor(
+ idleInhibitManager, surface);
+ zwp_idle_inhibitor_v1_set_user_data(idleInhibitor, this);
+ return idleInhibitor;
+}
+
+MockXdgOutputV1 *MockClient::createXdgOutput(wl_output *output)
+{
+ auto *xdgOutput = new MockXdgOutputV1(xdgOutputManager->get_xdg_output(output));
+ m_xdgOutputs[output] = xdgOutput;
+ return xdgOutput;
+}
+
ShmBuffer::ShmBuffer(const QSize &size, wl_shm *shm)
{
int stride = size.width() * 4;
diff --git a/tests/auto/compositor/compositor/mockclient.h b/tests/auto/compositor/compositor/mockclient.h
index b537e9df..69a0e47c 100644
--- a/tests/auto/compositor/compositor/mockclient.h
+++ b/tests/auto/compositor/compositor/mockclient.h
@@ -30,6 +30,7 @@
#include <qwayland-xdg-shell.h>
#include <wayland-ivi-application-client-protocol.h>
#include "wayland-viewporter-client-protocol.h"
+#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#include <QObject>
#include <QImage>
@@ -37,6 +38,8 @@
#include <QList>
#include <QWaylandOutputMode>
+#include "mockxdgoutputv1.h"
+
class MockSeat;
class ShmBuffer
@@ -63,16 +66,21 @@ public:
xdg_surface *createXdgSurface(wl_surface *surface);
xdg_toplevel *createXdgToplevel(xdg_surface *xdgSurface);
ivi_surface *createIviSurface(wl_surface *surface, uint iviId);
+ zwp_idle_inhibitor_v1 *createIdleInhibitor(wl_surface *surface);
+ MockXdgOutputV1 *createXdgOutput(wl_output *output);
wl_display *display = nullptr;
wl_compositor *compositor = nullptr;
QMap<uint, wl_output *> m_outputs;
+ QMap<wl_output *, MockXdgOutputV1 *> m_xdgOutputs;
wl_shm *shm = nullptr;
wl_registry *registry = nullptr;
wl_shell *wlshell = nullptr;
xdg_wm_base *xdgWmBase = nullptr;
wp_viewporter *viewporter = nullptr;
ivi_application *iviApplication = nullptr;
+ zwp_idle_inhibit_manager_v1 *idleInhibitManager = nullptr;
+ QtWayland::zxdg_output_manager_v1 *xdgOutputManager = nullptr;
QList<MockSeat *> m_seats;
diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.cpp b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp
new file mode 100644
index 00000000..eebc55bb
--- /dev/null
+++ b/tests/auto/compositor/compositor/mockxdgoutputv1.cpp
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** 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 "mockxdgoutputv1.h"
+
+MockXdgOutputV1::MockXdgOutputV1(struct ::zxdg_output_v1 *object)
+ : QtWayland::zxdg_output_v1(object)
+{
+}
+
+MockXdgOutputV1::~MockXdgOutputV1()
+{
+ destroy();
+}
+
+void MockXdgOutputV1::zxdg_output_v1_logical_position(int32_t x, int32_t y)
+{
+ pending.logicalPosition = QPoint(x, y);
+}
+
+void MockXdgOutputV1::zxdg_output_v1_logical_size(int32_t width, int32_t height)
+{
+ pending.logicalSize = QSize(width, height);
+}
+
+void MockXdgOutputV1::zxdg_output_v1_done()
+{
+ // In version 3 we'll have to do this for wl_output.done as well
+ name = pending.name;
+ description = pending.description;
+ logicalPosition = pending.logicalPosition;
+ logicalSize = pending.logicalSize;
+}
+
+void MockXdgOutputV1::zxdg_output_v1_name(const QString &name)
+{
+ pending.name = name;
+}
+
+void MockXdgOutputV1::zxdg_output_v1_description(const QString &description)
+{
+ pending.description = description;
+}
diff --git a/tests/auto/compositor/compositor/mockxdgoutputv1.h b/tests/auto/compositor/compositor/mockxdgoutputv1.h
new file mode 100644
index 00000000..db582069
--- /dev/null
+++ b/tests/auto/compositor/compositor/mockxdgoutputv1.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MOCKXDGOUTPUTV1_H
+#define MOCKXDGOUTPUTV1_H
+
+#include <QPoint>
+#include <QSize>
+#include <QString>
+
+#include "qwayland-xdg-output-unstable-v1.h"
+
+class MockXdgOutputV1 : public QtWayland::zxdg_output_v1
+{
+public:
+ explicit MockXdgOutputV1(struct ::zxdg_output_v1 *object);
+ ~MockXdgOutputV1();
+
+ QString name;
+ QString description;
+ QPoint logicalPosition;
+ QSize logicalSize;
+
+ struct {
+ QString name;
+ QString description;
+ QPoint logicalPosition;
+ QSize logicalSize;
+ } pending;
+
+protected:
+ void zxdg_output_v1_logical_position(int32_t x, int32_t y) override;
+ void zxdg_output_v1_logical_size(int32_t width, int32_t height) override;
+ void zxdg_output_v1_done() override;
+ void zxdg_output_v1_name(const QString &name) override;
+ void zxdg_output_v1_description(const QString &description) override;
+};
+
+#endif // MOCKXDGOUTPUTV1_H
diff --git a/tests/auto/compositor/compositor/tst_compositor.cpp b/tests/auto/compositor/compositor/tst_compositor.cpp
index 66792621..f4f63228 100644
--- a/tests/auto/compositor/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/compositor/tst_compositor.cpp
@@ -29,6 +29,7 @@
#include "mockclient.h"
#include "mockseat.h"
#include "mockpointer.h"
+#include "mockxdgoutputv1.h"
#include "testcompositor.h"
#include "testkeyboardgrabber.h"
#include "testseat.h"
@@ -47,8 +48,12 @@
#include <QtWaylandCompositor/QWaylandResource>
#include <QtWaylandCompositor/QWaylandKeymap>
#include <QtWaylandCompositor/QWaylandViewporter>
+#include <QtWaylandCompositor/QWaylandIdleInhibitManagerV1>
+#include <QtWaylandCompositor/QWaylandXdgOutputManagerV1>
#include <qwayland-xdg-shell.h>
#include <qwayland-ivi-application.h>
+#include <QtWaylandCompositor/private/qwaylandoutput_p.h>
+#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
#include <QtTest/QtTest>
@@ -73,12 +78,14 @@ private slots:
void singleClient();
void multipleClients();
void geometry();
+ void availableGeometry();
void modes();
void comparingModes();
void sizeFollowsWindow();
void mapSurface();
void mapSurfaceHiDpi();
void frameCallback();
+ void pixelFormats();
void outputs();
void customSurface();
@@ -110,6 +117,10 @@ private slots:
void viewportDestinationNoSurfaceError();
void viewportSourceNoSurfaceError();
void viewportHiDpi();
+
+ void idleInhibit();
+
+ void xdgOutput();
};
void tst_WaylandCompositor::init() {
@@ -367,6 +378,22 @@ void tst_WaylandCompositor::geometry()
QTRY_COMPARE(client.refreshRate, 60000);
}
+void tst_WaylandCompositor::availableGeometry()
+{
+ TestCompositor compositor;
+ compositor.create();
+
+ QWaylandOutputMode mode(QSize(1024, 768), 60000);
+ compositor.defaultOutput()->addMode(mode, true);
+ compositor.defaultOutput()->setCurrentMode(mode);
+
+ MockClient client;
+
+ QRect availableGeometry(50, 100, 850, 600);
+ compositor.defaultOutput()->setAvailableGeometry(availableGeometry);
+ QCOMPARE(compositor.defaultOutput()->availableGeometry(), availableGeometry);
+}
+
void tst_WaylandCompositor::modes()
{
TestCompositor compositor;
@@ -513,8 +540,13 @@ void tst_WaylandCompositor::mapSurfaceHiDpi()
QObject::connect(waylandSurface, &QWaylandSurface::hasContentChanged, verifyComittedState);
QSignalSpy hasContentSpy(waylandSurface, SIGNAL(hasContentChanged()));
+#if QT_DEPRECATED_SINCE(5, 13)
QObject::connect(waylandSurface, &QWaylandSurface::sizeChanged, verifyComittedState);
QSignalSpy sizeSpy(waylandSurface, SIGNAL(sizeChanged()));
+#endif
+
+ QObject::connect(waylandSurface, &QWaylandSurface::bufferSizeChanged, verifyComittedState);
+ QSignalSpy bufferSizeSpy(waylandSurface, SIGNAL(bufferSizeChanged()));
QObject::connect(waylandSurface, &QWaylandSurface::destinationSizeChanged, verifyComittedState);
QSignalSpy destinationSizeSpy(waylandSurface, SIGNAL(destinationSizeChanged()));
@@ -538,7 +570,10 @@ void tst_WaylandCompositor::mapSurfaceHiDpi()
wl_surface_commit(surface);
QTRY_COMPARE(hasContentSpy.count(), 1);
+#if QT_DEPRECATED_SINCE(5, 13)
QTRY_COMPARE(sizeSpy.count(), 1);
+#endif
+ QTRY_COMPARE(bufferSizeSpy.count(), 1);
QTRY_COMPARE(destinationSizeSpy.count(), 1);
QTRY_COMPARE(bufferScaleSpy.count(), 1);
QTRY_COMPARE(offsetSpy.count(), 1);
@@ -561,27 +596,27 @@ static void registerFrameCallback(wl_surface *surface, int *counter)
wl_callback_add_listener(wl_surface_frame(surface), &frameCallbackListener, counter);
}
-void tst_WaylandCompositor::frameCallback()
+class BufferView : public QWaylandView
{
- class BufferView : public QWaylandView
+public:
+ void bufferCommitted(const QWaylandBufferRef &ref, const QRegion &damage) override
{
- public:
- void bufferCommitted(const QWaylandBufferRef &ref, const QRegion &damage) override
- {
- Q_UNUSED(damage);
- bufferRef = ref;
- }
+ Q_UNUSED(damage);
+ bufferRef = ref;
+ }
- QImage image() const
- {
- if (bufferRef.isNull() || !bufferRef.isSharedMemory())
- return QImage();
- return bufferRef.image();
- }
+ QImage image() const
+ {
+ if (bufferRef.isNull() || !bufferRef.isSharedMemory())
+ return QImage();
+ return bufferRef.image();
+ }
- QWaylandBufferRef bufferRef;
- };
+ QWaylandBufferRef bufferRef;
+};
+void tst_WaylandCompositor::frameCallback()
+{
TestCompositor compositor;
compositor.create();
@@ -622,6 +657,35 @@ void tst_WaylandCompositor::frameCallback()
wl_surface_destroy(surface);
}
+void tst_WaylandCompositor::pixelFormats()
+{
+ TestCompositor compositor;
+ compositor.create();
+
+ MockClient client;
+
+ wl_surface *surface = client.createSurface();
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+ QWaylandSurface *waylandSurface = compositor.surfaces.at(0);
+ BufferView* view = new BufferView;
+ view->setSurface(waylandSurface);
+ view->setOutput(compositor.defaultOutput());
+
+ QSize size(32, 32);
+ ShmBuffer buffer(size, client.shm); // Will be WL_SHM_FORMAT_ARGB8888;
+ wl_surface_attach(surface, buffer.handle, 0, 0);
+ wl_surface_damage(surface, 0, 0, size.width(), size.height());
+ wl_surface_commit(surface);
+
+ QTRY_COMPARE(waylandSurface->hasContent(), true);
+
+ // According to https://lists.freedesktop.org/archives/wayland-devel/2017-August/034791.html
+ // all RGB formats with alpha are premultiplied. Verify it here:
+ QCOMPARE(view->image().format(), QImage::Format_ARGB32_Premultiplied);
+
+ wl_surface_destroy(surface);
+}
+
void tst_WaylandCompositor::outputs()
{
TestCompositor compositor;
@@ -1699,5 +1763,103 @@ void tst_WaylandCompositor::viewportHiDpi()
wl_surface_destroy(surface);
}
+class IdleInhibitCompositor : public TestCompositor
+{
+ Q_OBJECT
+public:
+ IdleInhibitCompositor() : idleInhibitManager(this) {}
+ QWaylandIdleInhibitManagerV1 idleInhibitManager;
+};
+
+void tst_WaylandCompositor::idleInhibit()
+{
+ IdleInhibitCompositor compositor;
+ compositor.create();
+ MockClient client;
+ QTRY_VERIFY(client.idleInhibitManager);
+
+ auto *surface = client.createSurface();
+ QVERIFY(surface);
+ QTRY_COMPARE(compositor.surfaces.size(), 1);
+
+ QWaylandSurface *waylandSurface = compositor.surfaces.at(0);
+ auto *waylandSurfacePrivate =
+ QWaylandSurfacePrivate::get(waylandSurface);
+ QVERIFY(waylandSurfacePrivate);
+
+ QSignalSpy changedSpy(waylandSurface, SIGNAL(inhibitsIdleChanged()));
+
+ QCOMPARE(waylandSurface->inhibitsIdle(), false);
+
+ auto *idleInhibitor = client.createIdleInhibitor(surface);
+ QVERIFY(idleInhibitor);
+ QTRY_COMPARE(waylandSurfacePrivate->idleInhibitors.size(), 1);
+ QCOMPARE(waylandSurface->inhibitsIdle(), true);
+ QTRY_COMPARE(changedSpy.count(), 1);
+}
+
+class XdgOutputCompositor : public TestCompositor
+{
+ Q_OBJECT
+public:
+ XdgOutputCompositor() : xdgOutputManager(this) {}
+ QWaylandXdgOutputManagerV1 xdgOutputManager;
+};
+
+void tst_WaylandCompositor::xdgOutput()
+{
+ XdgOutputCompositor compositor;
+ compositor.create();
+
+ QWaylandOutputMode mode(QSize(1024, 768), 60000);
+ compositor.defaultOutput()->addMode(mode, true);
+ compositor.defaultOutput()->setCurrentMode(mode);
+
+ MockClient client;
+ QTRY_VERIFY(client.xdgOutputManager);
+ QTRY_COMPARE(client.m_outputs.size(), 1);
+
+ auto *wlOutput = client.m_outputs.first();
+ QVERIFY(wlOutput);
+
+ // Output is not associated yet
+ QCOMPARE(QWaylandOutputPrivate::get(compositor.defaultOutput())->xdgOutput.isNull(), true);
+
+ // Create xdg-output on the server
+ auto *xdgOutputServer = new QWaylandXdgOutputV1(compositor.defaultOutput(), &compositor.xdgOutputManager);
+ QVERIFY(xdgOutputServer);
+ xdgOutputServer->setName(QStringLiteral("OUTPUT1"));
+ xdgOutputServer->setDescription(QStringLiteral("This is a test output"));
+
+ // Create it on the client
+ auto *xdgOutput = client.createXdgOutput(wlOutput);
+ QVERIFY(xdgOutput);
+ QVERIFY(client.m_xdgOutputs.contains(wlOutput));
+
+ // Now it should be associated
+ QCOMPARE(QWaylandOutputPrivate::get(compositor.defaultOutput())->xdgOutput.isNull(), false);
+
+ // Verify initial values
+ QTRY_COMPARE(xdgOutput->name, "OUTPUT1");
+ QTRY_COMPARE(xdgOutput->logicalPosition, QPoint());
+ QTRY_COMPARE(xdgOutput->logicalSize, QSize());
+
+ // Change properties
+ xdgOutputServer->setName(QStringLiteral("OUTPUT2"));
+ xdgOutputServer->setDescription(QStringLiteral("New description"));
+ xdgOutputServer->setLogicalPosition(QPoint(100, 100));
+ xdgOutputServer->setLogicalSize(QSize(1000, 1000));
+ compositor.flushClients();
+
+ // Name and description can't be changed after initialization,
+ // so we expect them to be the same
+ // TODO: With protocol version 3 the description will be allowed to change,
+ // but we implement version 2 now
+ QTRY_COMPARE(xdgOutput->name, "OUTPUT1");
+ QTRY_COMPARE(xdgOutput->description, "This is a test output");
+ QTRY_COMPARE(xdgOutput->logicalPosition, QPoint(100, 100));
+ QTRY_COMPARE(xdgOutput->logicalSize, QSize(1000, 1000));
+}
+
#include <tst_compositor.moc>
QTEST_MAIN(tst_WaylandCompositor);