diff options
Diffstat (limited to 'examples')
74 files changed, 3480 insertions, 1652 deletions
diff --git a/examples/wayland/custom-extension/client/.gitignore b/examples/wayland/custom-extension/client/.gitignore new file mode 100644 index 000000000..b4961e189 --- /dev/null +++ b/examples/wayland/custom-extension/client/.gitignore @@ -0,0 +1,4 @@ +qwayland-custom.cpp +qwayland-custom.h +wayland-custom-client-protocol.h +wayland-custom-protocol.c diff --git a/examples/wayland/custom-extension/client/client.json b/examples/wayland/custom-extension/client/client.json new file mode 100644 index 000000000..7aab544e5 --- /dev/null +++ b/examples/wayland/custom-extension/client/client.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "custom-wayland" ] +} diff --git a/examples/wayland/custom-extension/client/client.pro b/examples/wayland/custom-extension/client/client.pro new file mode 100644 index 000000000..9ba72bc9c --- /dev/null +++ b/examples/wayland/custom-extension/client/client.pro @@ -0,0 +1,26 @@ +CONFIG += wayland-scanner +CONFIG += link_pkgconfig + +TARGET = custom-wayland + +QT += waylandclient-private +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += wayland-client +} else { + LIBS += -lwayland-client +} + +WAYLANDCLIENTSOURCES += ../protocol/custom.xml + +OTHER_FILES += client.json + +SOURCES += main.cpp \ + customextension.cpp + +HEADERS += customextension.h + +PLUGIN_TYPE = platforms +load(qt_plugin) + +# Installation into a "proper" Qt location is most unexpected for from an example. +CONFIG += install_ok diff --git a/examples/wayland/custom-extension/client/customextension.cpp b/examples/wayland/custom-extension/client/customextension.cpp new file mode 100644 index 000000000..050b0d5c2 --- /dev/null +++ b/examples/wayland/custom-extension/client/customextension.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customextension.h" +#include <QtWaylandClient/private/qwaylanddisplay_p.h> +#include <QtWaylandClient/private/qwaylandintegration_p.h> + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +CustomExtension::CustomExtension() + : QWaylandClientExtensionTemplate(/* Supported protocol version */ 1 ) +{ +} + +void CustomExtension::sendRequest(const QString &text, int value) +{ + qDebug() << "Client-side plugin sending request:" << text << value; + qtrequest(text, value); +} + +void CustomExtension::example_extension_qtevent(struct wl_surface *surface, + uint32_t time, + const QString &text, + uint32_t value) +{ + qDebug() << "Client-side plugin received an event:" << surface << time << text << value; + emit eventReceived(text, value); +} + + +QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/textureblitter.h b/examples/wayland/custom-extension/client/customextension.h index 85e2bbfb4..a041d5a7e 100644 --- a/examples/wayland/qwindow-compositor/textureblitter.h +++ b/examples/wayland/custom-extension/client/customextension.h @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the examples of the Qt Wayland module ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -38,38 +38,36 @@ ** ****************************************************************************/ -#ifndef TEXTUREBLITTER_H -#define TEXTUREBLITTER_H +#ifndef CUSTOMEXTENSION_H +#define CUSTOMEXTENSION_H -#include <QtGui/QMatrix4x4> +#include <qpa/qwindowsysteminterface.h> +#include <QtWaylandClient/private/qwayland-wayland.h> +#include <QtWaylandClient/qwaylandclientextension.h> +#include "qwayland-custom.h" QT_BEGIN_NAMESPACE -class QOpenGLShaderProgram; -class TextureBlitter +class CustomExtension : public QWaylandClientExtensionTemplate<CustomExtension>, public QtWayland::qt_example_extension { + Q_OBJECT public: - TextureBlitter(); - ~TextureBlitter(); - void bind(quint32 target); - void release(); - void drawTexture(int textureId, const QRectF &sourceGeometry, - const QSize &targetRect, int depth, - bool targethasInvertedY, bool sourceHasInvertedY); + CustomExtension(); -private: - QOpenGLShaderProgram *m_shaderProgram; - QOpenGLShaderProgram *m_shaderProgramExternal; - QOpenGLShaderProgram *m_currentProgram; - QMatrix4x4 m_transformMatrix; +public slots: + void sendRequest(const QString &text, int value); + +signals: + void eventReceived(const QString &text, uint value); - int m_matrixLocation; - int m_vertexCoordEntry; - int m_textureCoordEntry; +private: + void example_extension_qtevent(struct wl_surface *surface, + uint32_t time, + const QString &text, + uint32_t value) Q_DECL_OVERRIDE; - quint32 m_currentTarget; }; QT_END_NAMESPACE -#endif // TEXTUREBLITTER_H +#endif // CUSTOMEXTENSION_H diff --git a/examples/wayland/custom-extension/client/main.cpp b/examples/wayland/custom-extension/client/main.cpp new file mode 100644 index 000000000..8c27fa77d --- /dev/null +++ b/examples/wayland/custom-extension/client/main.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qpa/qplatformintegrationplugin.h> +#include <QtWaylandClient/private/qwaylandintegration_p.h> +#include "customextension.h" + +#include <QGuiApplication> +#include <QDebug> + +QT_BEGIN_NAMESPACE + +static CustomExtension * extension_global; + +class CustomIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "client.json") +public: + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; +}; + + QPlatformIntegration *CustomIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + Q_UNUSED(system); + + qDebug() << "************* The Qt Custom Extension Example Plugin is active ************"; + + extension_global = new CustomExtension(); + + // We need a way for client apps to get hold of the extension. The proper API for this is + // QPlatformNativeInterface, but that's a low-level API using void*. There will be a nice + // client API at some point, but in the meantime, it is easier to use QObject::findChild(). + + extension_global->setParent(qApp); + extension_global->setObjectName("qt_example_custom_extension"); + + return extension_global->integration(); +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/examples/wayland/custom-extension/compositor/.gitignore b/examples/wayland/custom-extension/compositor/.gitignore new file mode 100644 index 000000000..2532eb22a --- /dev/null +++ b/examples/wayland/custom-extension/compositor/.gitignore @@ -0,0 +1,8 @@ +custom-compositor +qwayland-custom.cpp +qwayland-custom.h +qwayland-server-custom.cpp +qwayland-server-custom.h +wayland-custom-client-protocol.h +wayland-custom-protocol.c +wayland-custom-server-protocol.h diff --git a/examples/wayland/custom-extension/compositor/compositor.pro b/examples/wayland/custom-extension/compositor/compositor.pro new file mode 100644 index 000000000..4ffafdb8b --- /dev/null +++ b/examples/wayland/custom-extension/compositor/compositor.pro @@ -0,0 +1,34 @@ +QT += core gui qml + +QT += waylandcompositor-private + +CONFIG += wayland-scanner +CONFIG += c++11 +SOURCES += \ + main.cpp \ + customextension.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/Screen.qml \ + images/background.jpg + +WAYLANDSERVERSOURCES += \ + ../protocol/custom.xml + +RESOURCES += compositor.qrc + +contains(QT_CONFIG, no-pkg-config) { + LIBS += -lwayland-server +} else { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-server +} + +TARGET = custom-compositor + +HEADERS += \ + customextension.h + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-extension/compositor +INSTALLS += target diff --git a/examples/wayland/custom-extension/compositor/compositor.qrc b/examples/wayland/custom-extension/compositor/compositor.qrc new file mode 100644 index 000000000..db3a8075a --- /dev/null +++ b/examples/wayland/custom-extension/compositor/compositor.qrc @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.png</file> + <file>qml/main.qml</file> + <file>qml/Screen.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/custom-extension/compositor/customextension.cpp b/examples/wayland/custom-extension/compositor/customextension.cpp new file mode 100644 index 000000000..6c1f05977 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/customextension.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customextension.h" + +#include <QWaylandSurface> + +#include <QDebug> + +namespace QtWayland { + +CustomExtension::CustomExtension() +{ +} + +void CustomExtension::initialize() +{ + QWaylandCompositorExtensionTemplate::initialize(); + QWaylandCompositor *compositor = static_cast<QWaylandCompositor *>(extensionContainer()); + init(compositor->display(), 1); +} + +void CustomExtension::sendEvent(QWaylandSurface *surface, uint time, const QString &text, uint value) +{ + if (surface) { + Resource *target = resourceMap().value(surface->waylandClient()); + if (target) { + qDebug() << "Server-side extension sending an event:" << text << value; + send_qtevent(target->handle, surface->resource(), time, text, value); + } + } +} + +void CustomExtension::example_extension_qtrequest(QtWaylandServer::qt_example_extension::Resource *resource, const QString &text, int32_t value) +{ + Q_UNUSED(resource); + qDebug() << "Server-side extension received a request:" << text << value; + emit requestReceived(text, value); +} + +} diff --git a/examples/wayland/custom-extension/compositor/customextension.h b/examples/wayland/custom-extension/compositor/customextension.h new file mode 100644 index 000000000..8419eeea3 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/customextension.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMEXTENSION_H +#define CUSTOMEXTENSION_H + +#include "wayland-util.h" + +#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate> +#include <QtWaylandCompositor/QWaylandQuickExtension> +#include <QtWaylandCompositor/QWaylandCompositor> +#include "qwayland-server-custom.h" + +namespace QtWayland { + +class CustomExtension : public QWaylandCompositorExtensionTemplate<CustomExtension>, public QtWaylandServer::qt_example_extension +{ + Q_OBJECT +public: + CustomExtension(); + void initialize() Q_DECL_OVERRIDE; + Q_INVOKABLE void sendEvent(QWaylandSurface *surface, uint time, const QString &text, uint value); + +signals: + void requestReceived(const QString &text, uint value); +protected: + virtual void example_extension_qtrequest(Resource *resource, const QString &text, int32_t value) Q_DECL_OVERRIDE; +}; + +Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(CustomExtension) + +} + +#endif // CUSTOMEXTENSION_H diff --git a/examples/wayland/custom-extension/compositor/images/background.png b/examples/wayland/custom-extension/compositor/images/background.png Binary files differnew file mode 100644 index 000000000..2429df115 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/images/background.png diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/custom-extension/compositor/main.cpp index 7d855016f..867e4c0de 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.cpp +++ b/examples/wayland/custom-extension/compositor/main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Wayland module ** @@ -38,24 +38,26 @@ ** ****************************************************************************/ -#include "compositorwindow.h" -#include <QTouchEvent> +#include <QtCore/QUrl> +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlApplicationEngine> -CompositorWindow::CompositorWindow(const QSurfaceFormat &format, const QRect &geometry) - : m_format(format) +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> + +#include "customextension.h" + +static void registerTypes() { - setSurfaceType(QWindow::OpenGLSurface); - setGeometry(geometry); - setFormat(format); - create(); - m_context = new QOpenGLContext; - m_context->setFormat(format); - m_context->create(); + qmlRegisterType<QtWayland::CustomExtensionQuickExtension>("com.theqtcompany.customextension", 1, 0, "CustomExtension"); } -void CompositorWindow::touchEvent(QTouchEvent *event) +int main(int argc, char *argv[]) { - // Do not want any automatically synthesized mouse events - // so make sure the touch is always accepted. - event->accept(); + QGuiApplication app(argc, argv); + registerTypes(); + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); } diff --git a/examples/wayland/custom-extension/compositor/qml/Screen.qml b/examples/wayland/custom-extension/compositor/qml/Screen.qml new file mode 100644 index 000000000..3173c7a08 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/qml/Screen.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.2 +import QtWayland.Compositor 1.0 + +WaylandOutput { + id: output + property alias surfaceArea: background + window: Window { + id: screen + + property QtObject output + + width: 1024 + height: 768 + visible: true + + WaylandMouseTracker { + id: mouseTracker + anchors.fill: parent + + enableWSCursor: true + Image { + id: background + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.png" + smooth: false + } + WaylandCursorItem { + id: cursor + inputEventsEnabled: false + x: mouseTracker.mouseX - hotspotX + y: mouseTracker.mouseY - hotspotY + + inputDevice: output.compositor.defaultInputDevice + } + Rectangle { + anchors.bottom: parent.bottom + anchors.right: parent.right + width: 75 + height: 75 + color: "#BADA55" + MouseArea { + anchors.fill: parent + onClicked: { + comp.sendEvent(); + } + } + } + } + } +} diff --git a/examples/wayland/custom-extension/compositor/qml/main.qml b/examples/wayland/custom-extension/compositor/qml/main.qml new file mode 100644 index 000000000..097bfe30b --- /dev/null +++ b/examples/wayland/custom-extension/compositor/qml/main.qml @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtWayland.Compositor 1.0 + +import com.theqtcompany.customextension 1.0 + +WaylandCompositor { + id: comp + + property var lastItem: null + + property int counter : 0 + + function sendEvent() { + if (lastItem != null) { + console.log("Compositor sending event: " + counter); + custom.sendEvent(lastItem.shellSurface.surface, 0, "test", counter); + counter++; + } + } + + Screen { + compositor: comp + } + + Component { + id: chromeComponent + ShellSurfaceItem { + id: chrome + onSurfaceDestroyed: { + if (chrome === lastItem) + lastItem = null; + chrome.destroy() + } + } + } + + extensions: [ + WlShell { + id: defaultShell + + onShellSurfaceCreated: { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": shellSurface } ); + lastItem = item; + } + }, + CustomExtension { + id: custom + onRequestReceived: { + console.log("Compositor received a request: \"" + text + "\", " + value) + } + } + + ] + +} diff --git a/examples/wayland/custom-extension/custom-extension.pro b/examples/wayland/custom-extension/custom-extension.pro new file mode 100644 index 000000000..73e1eff7e --- /dev/null +++ b/examples/wayland/custom-extension/custom-extension.pro @@ -0,0 +1,10 @@ +TEMPLATE=subdirs + +SUBDIRS += client \ + qmltestapp +SUBDIRS += compositor +SUBDIRS += testapp + +qmltestapp.depends = client + +OTHER_FILES += protocol/custom.xml diff --git a/examples/wayland/custom-extension/protocol/custom.xml b/examples/wayland/custom-extension/protocol/custom.xml new file mode 100644 index 000000000..bda678299 --- /dev/null +++ b/examples/wayland/custom-extension/protocol/custom.xml @@ -0,0 +1,62 @@ +<protocol name="custom"> + + <copyright> + Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + This file is part of the examples of the Qt Wayland module + + $QT_BEGIN_LICENSE:BSD$ + You may use this file under the terms of the BSD license as follows: + + "Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of The Qt Company Ltd nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + + $QT_END_LICENSE$ + </copyright> + + <interface name="qt_example_extension" version="1"> + <event name="qtevent"> + <description summary="Qt example event"> + Example event from server to client + </description> + + <arg name="surface" type="object" interface="wl_surface"/> + <arg name="time" type="uint"/> + <arg name="text" type="string"/> + <arg name="value" type="uint"/> + </event> + + <request name="qtrequest"> + <description summary="Qt example event"> + Example request from client to server + </description> + + <arg name="text" type="string"/> + <arg name="value" type="int"/> + </request> + </interface> +</protocol> diff --git a/examples/wayland/custom-extension/qmltestapp/main.cpp b/examples/wayland/custom-extension/qmltestapp/main.cpp new file mode 100644 index 000000000..6140862d9 --- /dev/null +++ b/examples/wayland/custom-extension/qmltestapp/main.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Erik Larsson. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QtQml/QQmlApplicationEngine> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> +#include "../client/customextension.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + qmlRegisterType<CustomExtension>("com.theqtcompany.customextension", 1, 0, "CustomExtension"); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} + diff --git a/examples/wayland/custom-extension/qmltestapp/main.qml b/examples/wayland/custom-extension/qmltestapp/main.qml new file mode 100644 index 000000000..10e413efc --- /dev/null +++ b/examples/wayland/custom-extension/qmltestapp/main.qml @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Erik Larsson. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.0 +import com.theqtcompany.customextension 1.0 + +Window { + visible: true + Rectangle { + anchors.fill: parent + color: "#297A4A" + } + + MouseArea { + anchors.fill: parent + onClicked: { + console.log("Clicked outside", mouseX) + if (extensionLoader.item && extensionLoader.item.active) + extensionLoader.item.sendRequest("Clicked outside", mouseX) + } + } + + MouseArea { + anchors.centerIn: parent + width: 100; height: 100 + onClicked: { + var obj = mapToItem(parent, mouse.x, mouse.y) + console.log("Clicked inside", obj.x) + if (extensionLoader.item && extensionLoader.item.active) + extensionLoader.item.sendRequest("Clicked inside", obj.x) + } + + Rectangle { + anchors.fill: parent + color: "#34FD85" + } + } + + MouseArea { + anchors.right: parent.right + anchors.bottom: parent.bottom + width: 150; height: 25 + + Rectangle { + anchors.fill: parent + color: "#010101" + Text { + anchors.centerIn: parent + color: "white" + text: extensionLoader.item ? "Unload client extension" : "Load client extension" + } + } + onClicked: { + extensionLoader.active = !extensionLoader.active + } + } + + Component { + id: extensionComponent + CustomExtension { + id: customExtension + onActiveChanged: console.log("Custom extension is active?", active) + } + } + + Loader { + id: extensionLoader + sourceComponent: extensionComponent + } + + Connections { + target: extensionLoader.item + onEventReceived: console.log("Event received", text, value) + } +} + diff --git a/examples/wayland/custom-extension/qmltestapp/qml.qrc b/examples/wayland/custom-extension/qmltestapp/qml.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/examples/wayland/custom-extension/qmltestapp/qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/custom-extension/qmltestapp/qmltestapp.pro b/examples/wayland/custom-extension/qmltestapp/qmltestapp.pro new file mode 100644 index 000000000..786faeb0b --- /dev/null +++ b/examples/wayland/custom-extension/qmltestapp/qmltestapp.pro @@ -0,0 +1,28 @@ +TEMPLATE = app + +QT += qml quick waylandclient-private + +CONFIG += c++11 +CONFIG += wayland-scanner +CONFIG += link_pkgconfig + +WAYLANDCLIENTSOURCES += ../protocol/custom.xml + +!contains(QT_CONFIG, no-pkg-config) { + PKGCONFIG += wayland-client +} else { + LIBS += -lwayland-client +} + +SOURCES += main.cpp \ + ../client/customextension.cpp + +HEADERS += \ + ../client/customextension.h + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-extension/qmltestapp +INSTALLS += target + + diff --git a/examples/wayland/custom-extension/testapp/main.cpp b/examples/wayland/custom-extension/testapp/main.cpp new file mode 100644 index 000000000..59738128d --- /dev/null +++ b/examples/wayland/custom-extension/testapp/main.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** + ** + ** Copyright (C) 2015 The Qt Company Ltd. + ** Contact: http://www.qt.io/licensing/ + ** + ** This file is part of the examples of the Qt Wayland module + ** + ** $QT_BEGIN_LICENSE:BSD$ + ** You may use this file under the terms of the BSD license as follows: + ** + ** "Redistribution and use in source and binary forms, with or without + ** modification, are permitted provided that the following conditions are + ** met: + ** * Redistributions of source code must retain the above copyright + ** notice, this list of conditions and the following disclaimer. + ** * Redistributions in binary form must reproduce the above copyright + ** notice, this list of conditions and the following disclaimer in + ** the documentation and/or other materials provided with the + ** distribution. + ** * Neither the name of The Qt Company Ltd nor the names of its + ** contributors may be used to endorse or promote products derived + ** from this software without specific prior written permission. + ** + ** + ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + ** + ** $QT_END_LICENSE$ + ** + ****************************************************************************/ + +#include <QGuiApplication> +#include <QRasterWindow> +#include <QPainter> +#include <QMouseEvent> + +#include <QDebug> + +static QObject *s_custom; + +class TestWindow : public QRasterWindow +{ + Q_OBJECT + +public: + TestWindow() + { + if (s_custom) + connect(s_custom, SIGNAL(eventReceived(const QString &, uint)), + this, SLOT(handleEvent(const QString &, uint))); + } + +public slots: + void handleEvent(const QString &text, uint value) + { + qDebug() << "Client application received event" << text << value; + } + +protected: + void paintEvent(QPaintEvent *) + { + QPainter p(this); + p.fillRect(QRect(0,0,width(),height()),Qt::gray); + p.fillRect(50,50,100,100, QColor("#C0FFEE")); + } + + void mousePressEvent(QMouseEvent *ev) Q_DECL_OVERRIDE + { + Q_ASSERT(s_custom); + bool insideRect = QRect(50,50,100,100).contains(ev->pos()); + + QString text = insideRect ? "Click inside" : "Click outside"; + int value = ev->pos().x(); + + qDebug() << "Client application sending request:" << text << value; + + QMetaObject::invokeMethod(s_custom, "sendRequest", Qt::DirectConnection, + Q_ARG(QString, text), + Q_ARG(int, value)); + } + +private: + +}; + +int main (int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + s_custom = app.findChild<QObject*>("qt_example_custom_extension"); + if (!s_custom) { + qCritical() << "This example requires the Qt Custom Extension platform plugin,\n" + "add -platform custom-wayland to the command line"; + return -1; + } + TestWindow window; + window.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/examples/wayland/custom-extension/testapp/testapp.pro b/examples/wayland/custom-extension/testapp/testapp.pro new file mode 100644 index 000000000..062210e9a --- /dev/null +++ b/examples/wayland/custom-extension/testapp/testapp.pro @@ -0,0 +1,6 @@ +SOURCES += main.cpp + +CONFIG += c++11 + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/custom-extension/testapp +INSTALLS += target diff --git a/examples/wayland/minimal-cpp/README b/examples/wayland/minimal-cpp/README new file mode 100644 index 000000000..3a9a4b1b2 --- /dev/null +++ b/examples/wayland/minimal-cpp/README @@ -0,0 +1,7 @@ +A minimal example showing what is required to get a C++ based compositor up +and running. Input events are not delivered to clients, to avoid the logic +for finding the correct window and map the coordinates. + +See the qwindow-compositor example for information on how to implement +support for key and mouse events, and everything else a proper desktop +compositor needs. diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp new file mode 100644 index 000000000..ea685923b --- /dev/null +++ b/examples/wayland/minimal-cpp/compositor.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "compositor.h" +#include "window.h" + +#include <QtWaylandCompositor/qwaylandoutput.h> +#include <QOpenGLFunctions> + +GLuint View::getTexture() { + if (advance()) { + QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions(); + if (m_texture) + functions->glDeleteTextures(1, &m_texture); + + functions->glGenTextures(1, &m_texture); + functions->glBindTexture(GL_TEXTURE_2D, m_texture); + functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + currentBuffer().bindToTexture(); + } + return m_texture; +} + +bool View::isCursor() const +{ + return surface()->isCursorSurface(); +} + +Compositor::Compositor(Window *window) + : QWaylandCompositor() + , m_window(window) +{ +} + +Compositor::~Compositor() +{ +} + +void Compositor::create() +{ + new QWaylandOutput(this, m_window); + QWaylandCompositor::create(); + + connect(this, &QWaylandCompositor::surfaceCreated, this, &Compositor::onSurfaceCreated); +} + +void Compositor::onSurfaceCreated(QWaylandSurface *surface) +{ + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &Compositor::onSurfaceDestroyed); + connect(surface, &QWaylandSurface::redraw, this, &Compositor::triggerRender); + View *view = new View; + view->setSurface(surface); + view->setOutput(outputFor(m_window)); + m_views << view; + connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed); +} + +void Compositor::onSurfaceDestroyed() +{ + triggerRender(); +} + +void Compositor::viewSurfaceDestroyed() +{ + View *view = qobject_cast<View*>(sender()); + m_views.removeAll(view); + delete view; +} + +void Compositor::triggerRender() +{ + m_window->requestUpdate(); +} + +void Compositor::startRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->frameStarted(); +} + +void Compositor::endRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->sendFrameCallbacks(); +} diff --git a/examples/wayland/minimal-cpp/compositor.h b/examples/wayland/minimal-cpp/compositor.h new file mode 100644 index 000000000..fe379082c --- /dev/null +++ b/examples/wayland/minimal-cpp/compositor.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COMPOSITOR_H +#define COMPOSITOR_H + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandView> + +QT_BEGIN_NAMESPACE + +class Window; + +class View : public QWaylandView +{ + Q_OBJECT +public: + View() : m_texture(0) {} + GLuint getTexture(); + bool isCursor() const; +private: + friend class Compositor; + GLuint m_texture; +}; + +class Compositor : public QWaylandCompositor +{ + Q_OBJECT +public: + Compositor(Window *window); + ~Compositor(); + void create() Q_DECL_OVERRIDE; + + QList<View*> views() const { return m_views; } + + void startRender(); + void endRender(); + +private slots: + void onSurfaceCreated(QWaylandSurface *surface); + void onSurfaceDestroyed(); + void triggerRender(); + + void viewSurfaceDestroyed(); +private: + Window *m_window; + QList<View*> m_views; +}; + +QT_END_NAMESPACE + +#endif // COMPOSITOR_H diff --git a/examples/wayland/minimal-cpp/main.cpp b/examples/wayland/minimal-cpp/main.cpp new file mode 100644 index 000000000..db4a67ac6 --- /dev/null +++ b/examples/wayland/minimal-cpp/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include "window.h" +#include "compositor.h" + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + Window window; + Compositor compositor(&window); + window.setCompositor(&compositor); + compositor.create(); + window.resize(800,600); + window.show(); + + return app.exec(); +} diff --git a/examples/wayland/minimal-cpp/minimal-cpp.pro b/examples/wayland/minimal-cpp/minimal-cpp.pro new file mode 100644 index 000000000..46e422f69 --- /dev/null +++ b/examples/wayland/minimal-cpp/minimal-cpp.pro @@ -0,0 +1,20 @@ +QT += gui gui-private core-private waylandcompositor waylandcompositor-private + +LIBS += -L ../../lib + +HEADERS += \ + compositor.h \ + window.h + +SOURCES += main.cpp \ + compositor.cpp \ + window.cpp + +# to make QtWaylandCompositor/... style includes working without installing +INCLUDEPATH += $$PWD/../../include + + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/minimal-cpp +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minimal-cpp.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/minimal-cpp +INSTALLS += target sources diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp new file mode 100644 index 000000000..25ea6b64f --- /dev/null +++ b/examples/wayland/minimal-cpp/window.cpp @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" +#include "compositor.h" + +#include <QPainter> +#include <QMatrix4x4> +#include <QOpenGLFunctions> + +Window::Window() + : m_compositor(0) +{ +} + +void Window::setCompositor(Compositor *comp) { + m_compositor = comp; +} + +void Window::initializeGL() +{ + m_textureBlitter.create(); +} + +static int sillyrandom(int range) +{ + if (range <= 0) + range = 200; + return qrand() % range; +} + +void Window::paintGL() +{ + m_compositor->startRender(); + + QOpenGLFunctions *functions = context()->functions(); + functions->glClearColor(.4f, .7f, .1f, 0.5f); + functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + m_textureBlitter.bind(); + functions->glEnable(GL_BLEND); + functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + qsrand(31337); + + Q_FOREACH (View *view, m_compositor->views()) { + if (view->isCursor()) + continue; + GLuint textureId = view->getTexture(); + QWaylandSurface *surface = view->surface(); + if (surface && surface->isMapped()) { + QSize s = surface->size(); + QPointF pos(sillyrandom(width() - s.width()), sillyrandom(height() - s.height())); + QRectF surfaceGeometry(pos, s); + QOpenGLTextureBlitter::Origin surfaceOrigin = + view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft + ? QOpenGLTextureBlitter::OriginTopLeft + : QOpenGLTextureBlitter::OriginBottomLeft; + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size())); + m_textureBlitter.blit(textureId, targetTransform, surfaceOrigin); + } + } + m_textureBlitter.release(); + m_compositor->endRender(); +} diff --git a/examples/wayland/qwindow-compositor/compositorwindow.h b/examples/wayland/minimal-cpp/window.h index 24c50c535..c468abbbe 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.h +++ b/examples/wayland/minimal-cpp/window.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the examples of the Qt Wayland module @@ -38,27 +38,31 @@ ** ****************************************************************************/ -#ifndef COMPOSITORWINDOW_H -#define COMPOSITORWINDOW_H +#ifndef WINDOW_H +#define WINDOW_H -#include <QWindow> -#include <QOpenGLContext> -#include <QSurfaceFormat> +#include <QOpenGLWindow> +#include <QtGui/private/qopengltextureblitter_p.h> -class CompositorWindow : public QWindow +QT_BEGIN_NAMESPACE + +class Compositor; + +class Window : public QOpenGLWindow { public: - CompositorWindow(const QSurfaceFormat &format, const QRect &geometry); - QOpenGLContext* context() { return m_context; } - bool makeCurrent() { return m_context->makeCurrent(this); } - void swapBuffers() { m_context->swapBuffers(this); } + Window(); + void setCompositor(Compositor *comp); protected: - void touchEvent(QTouchEvent *event); + void initializeGL() Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; private: - QOpenGLContext *m_context; - QSurfaceFormat m_format; + QOpenGLTextureBlitter m_textureBlitter; + Compositor *m_compositor; }; -#endif // COMPOSITORWINDOW_H +QT_END_NAMESPACE + +#endif //WINDOW_H diff --git a/examples/wayland/minimal-qml/main.cpp b/examples/wayland/minimal-qml/main.cpp new file mode 100644 index 000000000..17e44b34b --- /dev/null +++ b/examples/wayland/minimal-qml/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine appEngine(QUrl("qrc:///main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/minimal-qml/main.qml b/examples/wayland/minimal-qml/main.qml new file mode 100644 index 000000000..dde223859 --- /dev/null +++ b/examples/wayland/minimal-qml/main.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.6 +import QtQuick.Window 2.2 +import QtWayland.Compositor 1.0 + +WaylandCompositor { + id: wlcompositor + // The output defines the screen. + WaylandOutput { + compositor: wlcompositor + window: Window { + width: 1024 + height: 768 + visible: true + Rectangle { + id: surfaceArea + color: "#1337af" + anchors.fill: parent + } + } + } + // The chrome defines the window look and behavior. + // Here we use the built-in ShellSurfaceItem. + Component { + id: chromeComponent + ShellSurfaceItem { + onSurfaceDestroyed: destroy() + } + } + // Extensions are additions to the core Wayland + // protocol. We choose to support two different + // shells (window management protocols). When the + // client creates a new window, we instantiate a + // chromeComponent on the output. + extensions: [ + WlShell { + onShellSurfaceCreated: + chromeComponent.createObject(surfaceArea, { "shellSurface": shellSurface } ); + }, + XdgShell { + onXdgSurfaceCreated: + chromeComponent.createObject(surfaceArea, { "shellSurface": xdgSurface } ); + } + ] +} diff --git a/examples/wayland/minimal-qml/minimal-qml.pro b/examples/wayland/minimal-qml/minimal-qml.pro new file mode 100644 index 000000000..a0c4f4ad9 --- /dev/null +++ b/examples/wayland/minimal-qml/minimal-qml.pro @@ -0,0 +1,14 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + main.qml + +RESOURCES += minimal-qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/minimal-qml +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS minimal-qml.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/minimal-qml +INSTALLS += target sources diff --git a/examples/wayland/minimal-qml/minimal-qml.qrc b/examples/wayland/minimal-qml/minimal-qml.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/examples/wayland/minimal-qml/minimal-qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/multi-output/doc/src/multi-output.qdoc b/examples/wayland/multi-output/doc/src/multi-output.qdoc new file mode 100644 index 000000000..32b9aa696 --- /dev/null +++ b/examples/wayland/multi-output/doc/src/multi-output.qdoc @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \title Qt Wayland Compositor Examples - Multi Output + \example multi-output + \brief Multi Output is an example that demonstrates a compositor with multiple outputs. + \ingroup qtwaylandcompositor-examples + + Multi Output demonstrates how to display the same clients on different + \l{WaylandOutput}{WaylandOutputs} with different types of composition. + + The example opens two different windows, one for each output. When a client connects, its + WaylandSurface is displayed in a GridView on one of the outputs, while a ShellSurface + associated with the WaylandSurface is displayed with desktop-style composition on + the other output. +*/ diff --git a/examples/wayland/qml-compositor/background.jpg b/examples/wayland/multi-output/images/background.jpg Binary files differindex 445567fbd..445567fbd 100644 --- a/examples/wayland/qml-compositor/background.jpg +++ b/examples/wayland/multi-output/images/background.jpg diff --git a/examples/wayland/qml-compositor/WindowChrome.qml b/examples/wayland/multi-output/main.cpp index 5a29032da..7ee6779d0 100644 --- a/examples/wayland/qml-compositor/WindowChrome.qml +++ b/examples/wayland/multi-output/main.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. ** @@ -38,26 +38,18 @@ ** ****************************************************************************/ -import QtQuick 2.0 +#include <QtCore/QUrl> +#include <QtCore/QDebug> -Item { - id: chrome - anchors.fill: parent +#include <QtGui/QGuiApplication> - property variant window: parent; - property bool selected: root.selectedWindow === window +#include <QtQml/QQmlApplicationEngine> - MouseArea { - anchors.fill: parent - enabled: !window.focus - hoverEnabled: !window.focus - onClicked: { - if (selected) { - window.takeFocus(); - } else { - root.selectedWindow = window - root.focus = true - } - } - } +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); } diff --git a/examples/wayland/multi-output/multi-output.pro b/examples/wayland/multi-output/multi-output.pro new file mode 100644 index 000000000..468dc2e09 --- /dev/null +++ b/examples/wayland/multi-output/multi-output.pro @@ -0,0 +1,16 @@ +QT += core gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/GridScreen.qml \ + qml/ShellScreen.qml \ + qml/ShellChrome.qml \ + images/background.jpg \ + +RESOURCES += multi-output.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/multi-output +INSTALLS += target diff --git a/examples/wayland/multi-output/multi-output.qrc b/examples/wayland/multi-output/multi-output.qrc new file mode 100644 index 000000000..86df88177 --- /dev/null +++ b/examples/wayland/multi-output/multi-output.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.jpg</file> + <file>qml/main.qml</file> + <file>qml/GridScreen.qml</file> + <file>qml/ShellScreen.qml</file> + <file>qml/ShellChrome.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/multi-output/qml/GridScreen.qml b/examples/wayland/multi-output/qml/GridScreen.qml new file mode 100644 index 000000000..6b1d574cd --- /dev/null +++ b/examples/wayland/multi-output/qml/GridScreen.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.2 +import QtWayland.Compositor 1.0 + +WaylandOutput { + id: output + property alias gridSurfaces: listModel + + window: Window { + width: 1024 + height: 760 + visible: true + + Image { + id: background + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + GridView { + id: gridView + anchors.fill: parent + model: ListModel { + id: listModel + } + interactive: false + cellWidth: 200 + cellHeight: 200 + delegate: WaylandQuickItem { + id: item + surface: gridSurface + width: gridView.cellWidth + height: gridView.cellHeight + sizeFollowsSurface: false + inputEventsEnabled: false + view.discardFrontBuffers: true + MouseArea { + anchors.fill: parent + onClicked: item.surface.activated() + } + } + } + } + } +} diff --git a/examples/wayland/multi-output/qml/ShellChrome.qml b/examples/wayland/multi-output/qml/ShellChrome.qml new file mode 100644 index 000000000..dac3eb096 --- /dev/null +++ b/examples/wayland/multi-output/qml/ShellChrome.qml @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtWayland.Compositor 1.0 + +ShellSurfaceItem { + id: rootChrome + + onSurfaceDestroyed: { + view.bufferLock = true; + destroyAnimation.start(); + } + + SequentialAnimation { + id: destroyAnimation + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } + } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } + ScriptAction { script: { rootChrome.destroy(); } } + } + + transform: [ + Scale { + id:scaleTransform + origin.x: rootChrome.width / 2 + origin.y: rootChrome.height / 2 + + } + ] +} diff --git a/examples/wayland/multi-output/qml/ShellScreen.qml b/examples/wayland/multi-output/qml/ShellScreen.qml new file mode 100644 index 000000000..77fbeb828 --- /dev/null +++ b/examples/wayland/multi-output/qml/ShellScreen.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Window 2.2 +import QtWayland.Compositor 1.0 + +WaylandOutput { + id: output + property alias surfaceArea: background + + window: Window { + width: 1024 + height: 760 + visible: true + + WaylandMouseTracker { + id: mouseTracker + anchors.fill: parent + + enableWSCursor: true + Image { + id: background + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + } + WaylandCursorItem { + id: cursor + inputEventsEnabled: false + x: mouseTracker.mouseX - hotspotX + y: mouseTracker.mouseY - hotspotY + + inputDevice : output.compositor.defaultInputDevice + } + } + } +} diff --git a/examples/wayland/qml-compositor/ContrastEffect.qml b/examples/wayland/multi-output/qml/main.qml index 562d637e9..6a1483bca 100644 --- a/examples/wayland/qml-compositor/ContrastEffect.qml +++ b/examples/wayland/multi-output/qml/main.qml @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: http://www.qt-project.org/legal ** ** This file is part of the examples of the Qt Toolkit. ** @@ -39,52 +39,61 @@ ****************************************************************************/ import QtQuick 2.0 +import QtWayland.Compositor 1.0 -ShaderEffect { - property variant source: null; - property color color: "#ffffff" - property real blend; +WaylandCompositor { + id: comp - onSourceChanged: { - if (source != null) { - source.setPaintEnabled(false); - } + defaultOutput: shellScreen + ShellScreen { + id: shellScreen + compositor: comp + } + + GridScreen { + id: gridScreen + compositor: comp } - property string vShaderInvertedY: " - uniform highp mat4 qt_Matrix; - attribute highp vec4 qt_Vertex; - attribute highp vec2 qt_MultiTexCoord0; - varying highp vec2 qt_TexCoord0; - void main() { - qt_TexCoord0 = qt_MultiTexCoord0; - gl_Position = qt_Matrix * qt_Vertex; + Component { + id: chromeComponent + ShellChrome { + } } - " - property string vShader: " - uniform highp mat4 qt_Matrix; - attribute highp vec4 qt_Vertex; - attribute highp vec2 qt_MultiTexCoord0; - varying highp vec2 qt_TexCoord0; - void main() { - qt_TexCoord0 = vec2(0, 1) + qt_MultiTexCoord0 * vec2(1, -1); - gl_Position = qt_Matrix * qt_Vertex; + + Component { + id: surfaceComponent + WaylandSurface { + id: surface + signal activated() + onMappedChanged: { + if (isMapped && !cursorSurface) { + gridScreen.gridSurfaces.append( { "gridSurface" : surface } ); + } else { + for (var i = 0; i < gridScreen.gridSurfaces.count; i++) { + if (gridScreen.gridSurfaces.get(i).gridSurface === surface) { + gridScreen.gridSurfaces.remove(i,1); + break; + } + } + } + } + } } - " - vertexShader: source && source.isYInverted ? vShaderInvertedY : vShader + extensions: [ + WlShell { + id: defaultShell + + onShellSurfaceCreated: { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": shellSurface } ); + item.surface.activated.connect(item.raise); + } + } + ] - fragmentShader: " - uniform lowp sampler2D source; - uniform highp float qt_Opacity; - uniform highp vec4 color; - uniform highp float blend; - varying highp vec2 qt_TexCoord0; - void main() { - highp vec4 sourceColor = texture2D(source, qt_TexCoord0); - highp vec3 delta = sourceColor.rgb - vec3(0.5); - highp vec3 lowerContrast = vec3(0.5) + 0.4 * delta; - gl_FragColor = qt_Opacity * mix(sourceColor, color * sourceColor.a * dot(lowerContrast, vec3(11, 16, 5) * (1. / 32.)), blend); + onCreateSurface: { + var surface = surfaceComponent.createObject(comp, { } ); + surface.initialize(comp, client, id, version); } - " } diff --git a/examples/wayland/pure-qml/doc/src/pure-qml.qdoc b/examples/wayland/pure-qml/doc/src/pure-qml.qdoc new file mode 100644 index 000000000..18ca73ec5 --- /dev/null +++ b/examples/wayland/pure-qml/doc/src/pure-qml.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \title Qt Wayland Compositor Examples - Pure QML + \example pure-qml + \brief Pure QML is an example that demonstrates how to write a Wayland compositor in pure QML. + \ingroup qtwaylandcompositor-examples + + Pure QML is a small desktop-style Wayland compositor example that demonstrates the power and ease + of the Qt Wayland Compositor QML APIs. +*/ diff --git a/examples/wayland/pure-qml/images/background.jpg b/examples/wayland/pure-qml/images/background.jpg Binary files differnew file mode 100644 index 000000000..445567fbd --- /dev/null +++ b/examples/wayland/pure-qml/images/background.jpg diff --git a/examples/wayland/pure-qml/main.cpp b/examples/wayland/pure-qml/main.cpp new file mode 100644 index 000000000..7ee6779d0 --- /dev/null +++ b/examples/wayland/pure-qml/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QUrl> +#include <QtCore/QDebug> + +#include <QtGui/QGuiApplication> + +#include <QtQml/QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); + + return app.exec(); +} diff --git a/examples/wayland/pure-qml/pure-qml.pro b/examples/wayland/pure-qml/pure-qml.pro new file mode 100644 index 000000000..20fc529ed --- /dev/null +++ b/examples/wayland/pure-qml/pure-qml.pro @@ -0,0 +1,18 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/Screen.qml \ + qml/Chrome.qml \ + qml/Keyboard.qml \ + images/background.jpg \ + +RESOURCES += pure-qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/pure-qml +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS pure-qml.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/pure-qml +INSTALLS += target sources diff --git a/examples/wayland/pure-qml/pure-qml.qrc b/examples/wayland/pure-qml/pure-qml.qrc new file mode 100644 index 000000000..8c95434d3 --- /dev/null +++ b/examples/wayland/pure-qml/pure-qml.qrc @@ -0,0 +1,9 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.jpg</file> + <file>qml/main.qml</file> + <file>qml/Screen.qml</file> + <file>qml/Chrome.qml</file> + <file>qml/Keyboard.qml</file> + </qresource> +</RCC> diff --git a/examples/wayland/pure-qml/qml/Chrome.qml b/examples/wayland/pure-qml/qml/Chrome.qml new file mode 100644 index 000000000..1c9066ef1 --- /dev/null +++ b/examples/wayland/pure-qml/qml/Chrome.qml @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtWayland.Compositor 1.0 + +ShellSurfaceItem { + id: rootChrome + + onSurfaceDestroyed: { + view.bufferLock = true; + destroyAnimation.start(); + } + + Connections { + target: shellSurface + + // some signals are not available on wl_shell, so let's ignore them + ignoreUnknownSignals: true + + onActivatedChanged: { // xdg_shell only + if (shellSurface.activated) { + receivedFocusAnimation.start(); + } + } + } + + SequentialAnimation { + id: destroyAnimation + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } + } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } + ScriptAction { script: { rootChrome.destroy(); } } + } + + SequentialAnimation { + id: receivedFocusAnimation + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } + } + ParallelAnimation { + NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } + } + } + + transform: [ + Scale { + id:scaleTransform + origin.x: rootChrome.width / 2 + origin.y: rootChrome.height / 2 + } + ] +} diff --git a/examples/wayland/pure-qml/qml/Keyboard.qml b/examples/wayland/pure-qml/qml/Keyboard.qml new file mode 100644 index 000000000..de88808e9 --- /dev/null +++ b/examples/wayland/pure-qml/qml/Keyboard.qml @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.VirtualKeyboard 2.1 + +InputPanel { + id: inputPanel + visible: active + y: active ? parent.height - inputPanel.height : parent.height + anchors.left: parent.left + anchors.right: parent.right +} + diff --git a/examples/wayland/pure-qml/qml/Screen.qml b/examples/wayland/pure-qml/qml/Screen.qml new file mode 100644 index 000000000..2043fa8b4 --- /dev/null +++ b/examples/wayland/pure-qml/qml/Screen.qml @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import QtQuick.Window 2.2 +import QtWayland.Compositor 1.0 + +WaylandOutput { + id: output + property alias surfaceArea: background + window: Window { + id: screen + + property QtObject output + + width: 1024 + height: 760 + visible: true + + WaylandMouseTracker { + id: mouseTracker + anchors.fill: parent + + enableWSCursor: true + Image { + id: background + anchors.fill: parent + fillMode: Image.Tile + source: "qrc:/images/background.jpg" + smooth: true + } + Loader { + anchors.fill: parent + source: "Keyboard.qml" + } + WaylandCursorItem { + id: cursor + inputEventsEnabled: false + x: mouseTracker.mouseX - hotspotX + y: mouseTracker.mouseY - hotspotY + + inputDevice: output.compositor.defaultInputDevice + } + } + + Shortcut { + sequence: "Meta+F" + onActivated: qtWindowManager.showIsFullScreen = !qtWindowManager.showIsFullScreen + } + + Shortcut { + sequence: "Ctrl+Alt+Backspace" + onActivated: Qt.quit() + } + } +} diff --git a/examples/wayland/pure-qml/qml/main.qml b/examples/wayland/pure-qml/qml/main.qml new file mode 100644 index 000000000..6ee09f802 --- /dev/null +++ b/examples/wayland/pure-qml/qml/main.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtWayland.Compositor 1.0 + +WaylandCompositor { + id: comp + + property var primarySurfacesArea: null + + Screen { + compositor: comp + } + + Component { + id: chromeComponent + Chrome { + } + } + + Component { + id: surfaceComponent + WaylandSurface { + } + } + + extensions: [ + WindowManager { + id: qtWindowManager + onShowIsFullScreenChanged: console.debug("Show is fullscreen hint for Qt applications:", showIsFullScreen) + }, + WlShell { + onShellSurfaceCreated: { + chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": shellSurface } ); + } + }, + XdgShell { + onXdgSurfaceCreated: { + chromeComponent.createObject(defaultOutput.surfaceArea, { "shellSurface": xdgSurface } ); + } + }, + TextInputManager { + } + ] + + onCreateSurface: { + var surface = surfaceComponent.createObject(comp, { } ); + surface.initialize(comp, client, id, version); + + } +} diff --git a/examples/wayland/qml-compositor/WindowContainer.qml b/examples/wayland/qml-compositor/WindowContainer.qml deleted file mode 100644 index 253daf7a9..000000000 --- a/examples/wayland/qml-compositor/WindowContainer.qml +++ /dev/null @@ -1,212 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtQuick.Window 2.0 -import QtCompositor 1.0 - -Item { - id: container - - x: targetX - y: targetY - width: targetWidth - height: targetHeight - scale: targetScale - - visible: isFullscreen || !root.hasFullscreenWindow - onVisibleChanged: { - child.surface.clientRenderingEnabled = visible - } - - opacity: 0 - - property real targetX - property real targetY - property real targetWidth - property real targetHeight - property real targetScale - - property variant child: null - property variant chrome: null - property bool animationsEnabled: false - property bool isFullscreen: state === "fullscreen" - property int index - - state: child && chrome && chrome.selected && child.focus ? "fullscreen" : "normal" - - Behavior on x { - enabled: container.animationsEnabled; - NumberAnimation { easing.type: Easing.InCubic; duration: 200; } - } - - Behavior on y { - enabled: container.animationsEnabled; - NumberAnimation { easing.type: Easing.InQuad; duration: 200; } - } - - Behavior on width { - enabled: container.animationsEnabled; - NumberAnimation { easing.type: Easing.InCubic; duration: 200; } - } - - Behavior on height { - enabled: container.animationsEnabled; - NumberAnimation { easing.type: Easing.InCubic; duration: 200; } - } - - Behavior on scale { - enabled: container.animationsEnabled; - NumberAnimation { easing.type: Easing.InQuad; duration: 200; } - } - - Behavior on opacity { - enabled: true; - NumberAnimation { easing.type: Easing.Linear; duration: 250; } - } - - ContrastEffect { - id: effect - source: child - anchors.fill: parent - blend: { if (child && chrome && (chrome.selected || child.focus)) 0.0; else 0.6 } - opacity: 1.0 - z: 1 - - Behavior on blend { - enabled: true; - NumberAnimation { easing.type: Easing.Linear; duration: 200; } - } - } - - transform: [ - Scale { id: scaleTransform; origin.x: container.width / 2; origin.y: container.height / 2; xScale: 1; yScale: 1 } - ] - - property real fullscreenScale: Math.min(root.width / width, root.height / height) - - transitions: [ - Transition { - from: "*"; to: "normal" - SequentialAnimation { - ScriptAction { - script: { - compositor.fullscreenSurface = null - background.opacity = 1 - } - } - ParallelAnimation { - NumberAnimation { target: container; property: "x"; easing.type: Easing.Linear; to: targetX; duration: 400; } - NumberAnimation { target: container; property: "y"; easing.type: Easing.Linear; to: targetY; duration: 400; } - NumberAnimation { target: container; property: "scale"; easing.type: Easing.Linear; to: targetScale; duration: 400; } - } - ScriptAction { - script: container.z = 0 - } - } - }, - Transition { - from: "*"; to: "fullscreen" - SequentialAnimation { - ScriptAction { - script: { - container.z = 1 - background.opacity = 0 - } - } - ParallelAnimation { - NumberAnimation { target: container; property: "x"; easing.type: Easing.Linear; to: (root.width - container.width) / 2; duration: 400; } - NumberAnimation { target: container; property: "y"; easing.type: Easing.Linear; to: (root.height - container.height) / 2; duration: 400; } - NumberAnimation { target: container; property: "scale"; easing.type: Easing.Linear; to: fullscreenScale; duration: 400; } - } - ScriptAction { - script: compositor.fullscreenSurface = child.surface - } - } - } - ] - - SequentialAnimation { - id: destroyAnimation - NumberAnimation { target: scaleTransform; property: "yScale"; easing.type: Easing.Linear; to: 0.01; duration: 200; } - NumberAnimation { target: scaleTransform; property: "xScale"; easing.type: Easing.Linear; to: 0.01; duration: 150; } - NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; } - ScriptAction { script: container.parent.removeWindow(container) } - } - SequentialAnimation { - id: unmapAnimation - NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; } - ScriptAction { script: container.parent.removeWindow(container) } - } - - Connections { - target: container.child ? container.child.surface : null - onUnmapped: unmapAnimation.start() - } - Connections { - target: container.child ? container.child : null - onSurfaceDestroyed: { - destroyAnimation.start(); - } - } - - Image { - source: "closebutton.png" - smooth: true - - opacity: !isFullscreen && chrome && chrome.selected ? 1 : 0 - Behavior on opacity { - NumberAnimation { easing.type: Easing.InCubic; duration: 200; } - } - - x: parent.width - 32 - y: 4 - width: 24 - height: 24 - z: 4 - - MouseArea { - anchors.fill: parent - onClicked: { - child.surface.destroySurface() - } - } - } -} diff --git a/examples/wayland/qml-compositor/closebutton.png b/examples/wayland/qml-compositor/closebutton.png Binary files differdeleted file mode 100644 index 5b5616e98..000000000 --- a/examples/wayland/qml-compositor/closebutton.png +++ /dev/null diff --git a/examples/wayland/qml-compositor/compositor.js b/examples/wayland/qml-compositor/compositor.js deleted file mode 100644 index 8baa2dd02..000000000 --- a/examples/wayland/qml-compositor/compositor.js +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -var windowList = null; -var indexes = null; - -function relayout() { - if (windowList === null || windowList.length == 0) - return; - - var dim = Math.ceil(Math.sqrt(windowList.length)); - - var cols = dim; - var rows = Math.ceil(windowList.length / cols); - - var w = root.width / dim; - var h = root.height / rows; - - var i; - var ix = 0; - var iy = 0; - var lastDim = 1; - - indexes = new Array(dim * dim); - - for (i = 0; i < windowList.length; ++i) { - if (i > 0) { - var currentDim = Math.ceil(Math.sqrt(i + 1)); - if (currentDim == lastDim) { - if (iy < currentDim - 1) { - ++iy; - if (iy == currentDim - 1) - ix = 0; - } else { - ++ix; - } - } else { - iy = 0; - ix = currentDim - 1; - } - lastDim = currentDim; - } - - indexes[iy * dim + ix] = i; - windowList[i].index = iy * dim + ix; - - var cx = (ix + 0.5) * w; - var cy = (iy + 0.5) * h; - - windowList[i].targetScale = 0.98 * Math.min(w / windowList[i].width, h / windowList[i].height); - - windowList[i].targetX = (cx - windowList[i].width / 2); - windowList[i].targetY = (cy - windowList[i].height / 2); - } -} - -function addWindow(window) -{ - if (windowList == null) - windowList = new Array(0); - - windowList.push(window); - relayout(); -} - -function removeWindow(window) -{ - var i; - for (i = 0; i < windowList.length; ++i) { - if (windowList[i] == window) - break; - } - - var index = windowList[i].index; - var dim = Math.ceil(Math.sqrt(windowList.length)); - var maxY = Math.floor((windowList.length-1) / dim); - - var shrinking = Math.ceil(Math.sqrt(windowList.length - 1)) != dim; - - while (true) { - var ix = index % dim; - var iy = Math.floor(index / dim); - - if (shrinking) { - if (iy > 0) - --iy; - else if (++ix == dim) - break; - } else { - if (iy < maxY) { - if (ix > 0) - --ix; - else - ++iy; - } else { - ++ix; - } - } - - var next = iy * dim + ix; - - var currentIndex = indexes[index]; - var nextIndex = indexes[next]; - - if (nextIndex == null) - break; - - var temp = windowList[currentIndex]; - windowList[currentIndex] = windowList[nextIndex]; - windowList[currentIndex].index = currentIndex; - windowList[nextIndex] = temp; - - index = next; - } - - windowList.splice(indexes[index], 1); - relayout(); -} diff --git a/examples/wayland/qml-compositor/main.cpp b/examples/wayland/qml-compositor/main.cpp deleted file mode 100644 index ab8589986..000000000 --- a/examples/wayland/qml-compositor/main.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwaylandquickcompositor.h" -#include "qwaylandquicksurface.h" - -#include <QtCompositor/qwaylandsurfaceitem.h> -#include <QtCompositor/qwaylandoutput.h> - -#include <QGuiApplication> -#include <QTimer> -#include <QPainter> -#include <QMouseEvent> - -#include <QQmlContext> - -#include <QQuickItem> -#include <QQuickView> - -class QmlCompositor : public QQuickView, public QWaylandQuickCompositor -{ - Q_OBJECT - Q_PROPERTY(QWaylandQuickSurface* fullscreenSurface READ fullscreenSurface WRITE setFullscreenSurface NOTIFY fullscreenSurfaceChanged) - -public: - QmlCompositor() - : QWaylandQuickCompositor(0, DefaultExtensions | SubSurfaceExtension) - , m_fullscreenSurface(0) - { - setSource(QUrl("main.qml")); - setResizeMode(QQuickView::SizeRootObjectToView); - setColor(Qt::black); - winId(); - addDefaultShell(); - createOutput(this, "", ""); - - connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks())); - } - - QWaylandQuickSurface *fullscreenSurface() const - { - return m_fullscreenSurface; - } - - Q_INVOKABLE QWaylandSurfaceItem *item(QWaylandSurface *surf) - { - return static_cast<QWaylandSurfaceItem *>(surf->views().first()); - } - -signals: - void windowAdded(QVariant window); - void windowResized(QVariant window); - void fullscreenSurfaceChanged(); - -public slots: - void destroyWindow(QVariant window) { - qvariant_cast<QObject *>(window)->deleteLater(); - } - - void setFullscreenSurface(QWaylandQuickSurface *surface) { - if (surface == m_fullscreenSurface) - return; - m_fullscreenSurface = surface; - emit fullscreenSurfaceChanged(); - } - -private slots: - void surfaceMapped() { - QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender()); - emit windowAdded(QVariant::fromValue(surface)); - } - void surfaceUnmapped() { - QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender()); - if (surface == m_fullscreenSurface) - m_fullscreenSurface = 0; - } - - void surfaceDestroyed() { - QWaylandQuickSurface *surface = static_cast<QWaylandQuickSurface *>(sender()); - if (surface == m_fullscreenSurface) - m_fullscreenSurface = 0; - } - - void sendCallbacks() { - if (m_fullscreenSurface) - sendFrameCallbacks(QList<QWaylandSurface *>() << m_fullscreenSurface); - else - sendFrameCallbacks(surfaces()); - } - -protected: - void resizeEvent(QResizeEvent *event) - { - QQuickView::resizeEvent(event); - QWaylandCompositor::setOutputGeometry(QRect(0, 0, width(), height())); - } - - void surfaceCreated(QWaylandSurface *surface) { - connect(surface, SIGNAL(surfaceDestroyed()), this, SLOT(surfaceDestroyed())); - connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped())); - connect(surface,SIGNAL(unmapped()), this,SLOT(surfaceUnmapped())); - } - -private: - QWaylandQuickSurface *m_fullscreenSurface; -}; - -int main(int argc, char *argv[]) -{ - QGuiApplication app(argc, argv); - - QmlCompositor compositor; - compositor.setTitle(QLatin1String("QML Compositor")); - compositor.setGeometry(0, 0, 1024, 768); - compositor.show(); - - compositor.rootContext()->setContextProperty("compositor", &compositor); - - QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant))); - QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant))); - - return app.exec(); -} - -#include "main.moc" diff --git a/examples/wayland/qml-compositor/main.qml b/examples/wayland/qml-compositor/main.qml deleted file mode 100644 index 5c1a2a67f..000000000 --- a/examples/wayland/qml-compositor/main.qml +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.0 -import QtCompositor 1.0 -import "compositor.js" as CompositorLogic - -Item { - id: root - - property variant selectedWindow: null - property bool hasFullscreenWindow: typeof compositor != "undefined" && compositor.fullscreenSurface !== null - - Image { - id: background - Behavior on opacity { - NumberAnimation { easing.type: Easing.InCubic; duration: 400; } - } - anchors.fill: parent - fillMode: Image.Tile - source: "background.jpg" - smooth: true - } - - MouseArea { - anchors.fill: parent - onClicked: { - root.selectedWindow = null - root.focus = true - } - } - - MouseArea { - anchors.right: parent.right - anchors.bottom: parent.bottom - width: 2 - height: 2 - hoverEnabled: true - onEntered: { - root.selectedWindow = null - root.focus = true - } - z: 10 - } - - function windowAdded(window) { - var windowContainerComponent = Qt.createComponent("WindowContainer.qml"); - if (windowContainerComponent.status != Component.Ready) { - console.warn("Error loading WindowContainer.qml: " + windowContainerComponent.errorString()); - return; - } - var windowContainer = windowContainerComponent.createObject(root); - - windowContainer.child = compositor.item(window); - windowContainer.child.parent = windowContainer; - windowContainer.child.touchEventsEnabled = true; - - windowContainer.targetWidth = window.size.width; - windowContainer.targetHeight = window.size.height; - - var windowChromeComponent = Qt.createComponent("WindowChrome.qml"); - if (windowChromeComponent.status != Component.Ready) { - console.warn("Error loading WindowChrome.qml: " + windowChromeComponent.errorString()); - return; - } - var windowChrome = windowChromeComponent.createObject(windowContainer.child); - - CompositorLogic.addWindow(windowContainer); - - windowContainer.opacity = 1 - windowContainer.animationsEnabled = true; - windowContainer.chrome = windowChrome; - } - - function windowResized(window) { - window.width = window.surface.size.width; - window.height = window.surface.size.height; - - CompositorLogic.relayout(); - } - - function removeWindow(window) { - CompositorLogic.removeWindow(window); - window.chrome.destroy(); - window.destroy(); - } - - onHeightChanged: CompositorLogic.relayout(); - onWidthChanged: CompositorLogic.relayout(); -} diff --git a/examples/wayland/qml-compositor/qml-compositor.pro b/examples/wayland/qml-compositor/qml-compositor.pro deleted file mode 100644 index 98ff96f83..000000000 --- a/examples/wayland/qml-compositor/qml-compositor.pro +++ /dev/null @@ -1,27 +0,0 @@ -DEFINES += QT_COMPOSITOR_QUICK - -LIBS += -L ../../lib - -QT += quick qml -QT += quick-private - -QT += compositor - -# if you want to compile QtCompositor as part of the application -# instead of linking to it, remove the QT += compositor and uncomment -# the following line -#include (../../src/compositor/compositor.pri) - -SOURCES += main.cpp - -qml.files = \ - ContrastEffect.qml \ - WindowChrome.qml \ - WindowContainer.qml \ - background.jpg \ - closebutton.png \ - compositor.js \ - main.qml -qml.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor -INSTALLS += target qml diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp new file mode 100644 index 000000000..c60ecc6b5 --- /dev/null +++ b/examples/wayland/qwindow-compositor/compositor.cpp @@ -0,0 +1,496 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "compositor.h" + +#include <QMouseEvent> +#include <QKeyEvent> +#include <QTouchEvent> + +#include <QtWaylandCompositor/QWaylandXdgShell> +#include <QtWaylandCompositor/QWaylandWlShellSurface> +#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylanddrag.h> + +#include <QDebug> +#include <QOpenGLContext> + +#ifndef GL_TEXTURE_EXTERNAL_OES +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#endif + +View::View() + : m_textureTarget(GL_TEXTURE_2D) + , m_texture(0) + , m_wlShellSurface(nullptr) + , m_xdgSurface(nullptr) + , m_xdgPopup(nullptr) + , m_parentView(nullptr) +{} + +GLuint View::getTexture(GLenum *target) +{ + QWaylandBufferRef buf = currentBuffer(); + GLuint streamingTexture = buf.textureForPlane(0); + if (streamingTexture) + m_texture = streamingTexture; + + if (!buf.isShm() && buf.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) + m_textureTarget = GL_TEXTURE_EXTERNAL_OES; + + if (advance()) { + buf = currentBuffer(); + if (!m_texture) + glGenTextures(1, &m_texture); + + glBindTexture(m_textureTarget, m_texture); + if (buf.isShm()) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + buf.bindToTexture(); + } + + buf.updateTexture(); + + if (target) + *target = m_textureTarget; + + return m_texture; +} + +bool View::isCursor() const +{ + return surface()->isCursorSurface(); +} + +void View::onXdgSetMaximized() +{ + m_xdgSurface->requestMaximized(output()->geometry().size()); + + // An improvement here, would have been to wait for the commit after the ack_configure for the + // request above before moving the window. This would have prevented the window from being + // moved until the contents of the window had actually updated. This improvement is left as an + // exercise for the reader. + setPosition(QPoint(0, 0)); +} + +void View::onXdgUnsetMaximized() +{ + m_xdgSurface->requestUnMaximized(); +} + +void View::onXdgSetFullscreen(QWaylandOutput* clientPreferredOutput) +{ + QWaylandOutput *outputToFullscreen = clientPreferredOutput + ? clientPreferredOutput + : output(); + + m_xdgSurface->requestFullscreen(outputToFullscreen->geometry().size()); + + // An improvement here, would have been to wait for the commit after the ack_configure for the + // request above before moving the window. This would have prevented the window from being + // moved until the contents of the window had actually updated. This improvement is left as an + // exercise for the reader. + setPosition(outputToFullscreen->position()); +} + +void View::onOffsetForNextFrame(const QPoint &offset) +{ + m_offset = offset; + setPosition(position() + offset); +} + +void View::onXdgUnsetFullscreen() +{ + onXdgUnsetMaximized(); +} + +Compositor::Compositor(QWindow *window) + : QWaylandCompositor() + , m_window(window) + , m_wlShell(new QWaylandWlShell(this)) + , m_xdgShell(new QWaylandXdgShell(this)) +{ + connect(m_wlShell, &QWaylandWlShell::shellSurfaceCreated, this, &Compositor::onWlShellSurfaceCreated); + connect(m_xdgShell, &QWaylandXdgShell::xdgSurfaceCreated, this, &Compositor::onXdgSurfaceCreated); + connect(m_xdgShell, &QWaylandXdgShell::createXdgPopup, this, &Compositor::onCreateXdgPopup); +} + +Compositor::~Compositor() +{ +} + +void Compositor::create() +{ + new QWaylandOutput(this, m_window); + QWaylandCompositor::create(); + + connect(this, &QWaylandCompositor::surfaceCreated, this, &Compositor::onSurfaceCreated); + connect(defaultInputDevice(), &QWaylandInputDevice::cursorSurfaceRequest, this, &Compositor::adjustCursorSurface); + connect(defaultInputDevice()->drag(), &QWaylandDrag::dragStarted, this, &Compositor::startDrag); + + connect(this, &QWaylandCompositor::subsurfaceChanged, this, &Compositor::onSubsurfaceChanged); +} + +void Compositor::onSurfaceCreated(QWaylandSurface *surface) +{ + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &Compositor::surfaceDestroyed); + connect(surface, &QWaylandSurface::mappedChanged, this, &Compositor::surfaceMappedChanged); + connect(surface, &QWaylandSurface::redraw, this, &Compositor::triggerRender); + + connect(surface, &QWaylandSurface::subsurfacePositionChanged, this, &Compositor::onSubsurfacePositionChanged); + + View *view = new View; + view->setSurface(surface); + view->setOutput(outputFor(m_window)); + m_views << view; + connect(view, &QWaylandView::surfaceDestroyed, this, &Compositor::viewSurfaceDestroyed); + connect(surface, &QWaylandSurface::offsetForNextFrame, view, &View::onOffsetForNextFrame); +} + +void Compositor::surfaceMappedChanged() +{ + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + if (surface->isMapped()) { + if (surface->role() == QWaylandWlShellSurface::role() + || surface->role() == QWaylandXdgSurface::role() + || surface->role() == QWaylandXdgPopup::role()) { + defaultInputDevice()->setKeyboardFocus(surface); + } + } else if (popupActive()) { + for (int i = 0; i < m_popupViews.count(); i++) { + if (m_popupViews.at(i)->surface() == surface) { + m_popupViews.removeAt(i); + break; + } + } + } + triggerRender(); +} + +void Compositor::surfaceDestroyed() +{ + triggerRender(); +} + +void Compositor::viewSurfaceDestroyed() +{ + View *view = qobject_cast<View*>(sender()); + m_views.removeAll(view); + delete view; +} + +View * Compositor::findView(const QWaylandSurface *s) const +{ + Q_FOREACH (View* view, m_views) { + if (view->surface() == s) + return view; + } + return Q_NULLPTR; +} + +void Compositor::onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface) +{ + connect(wlShellSurface, &QWaylandWlShellSurface::startMove, this, &Compositor::onStartMove); + connect(wlShellSurface, &QWaylandWlShellSurface::startResize, this, &Compositor::onWlStartResize); + connect(wlShellSurface, &QWaylandWlShellSurface::setTransient, this, &Compositor::onSetTransient); + connect(wlShellSurface, &QWaylandWlShellSurface::setPopup, this, &Compositor::onSetPopup); + + View *view = findView(wlShellSurface->surface()); + Q_ASSERT(view); + view->m_wlShellSurface = wlShellSurface; +} + +void Compositor::onXdgSurfaceCreated(QWaylandXdgSurface *xdgSurface) +{ + connect(xdgSurface, &QWaylandXdgSurface::startMove, this, &Compositor::onStartMove); + connect(xdgSurface, &QWaylandXdgSurface::startResize, this, &Compositor::onXdgStartResize); + + View *view = findView(xdgSurface->surface()); + Q_ASSERT(view); + view->m_xdgSurface = xdgSurface; + + connect(xdgSurface, &QWaylandXdgSurface::setMaximized, view, &View::onXdgSetMaximized); + connect(xdgSurface, &QWaylandXdgSurface::setFullscreen, view, &View::onXdgSetFullscreen); + connect(xdgSurface, &QWaylandXdgSurface::unsetMaximized, view, &View::onXdgUnsetMaximized); + connect(xdgSurface, &QWaylandXdgSurface::unsetFullscreen, view, &View::onXdgUnsetFullscreen); +} + +void Compositor::onCreateXdgPopup(QWaylandSurface *surface, QWaylandSurface *parent, + QWaylandInputDevice *inputDevice, const QPoint &position, + const QWaylandResource &resource) +{ + Q_UNUSED(inputDevice); + + QWaylandXdgPopup *xdgPopup = new QWaylandXdgPopup(m_xdgShell, surface, parent, resource); + + View *view = findView(surface); + Q_ASSERT(view); + + View *parentView = findView(parent); + Q_ASSERT(parentView); + + view->setPosition(parentView->position() + position); + view->m_xdgPopup = xdgPopup; +} + +void Compositor::onStartMove() +{ + closePopups(); + emit startMove(); +} + +void Compositor::onWlStartResize(QWaylandInputDevice *, QWaylandWlShellSurface::ResizeEdge edges) +{ + closePopups(); + emit startResize(int(edges), false); +} + +void Compositor::onXdgStartResize(QWaylandInputDevice *inputDevice, + QWaylandXdgSurface::ResizeEdge edges) +{ + Q_UNUSED(inputDevice); + emit startResize(int(edges), true); +} + +void Compositor::onSetTransient(QWaylandSurface *parent, const QPoint &relativeToParent, QWaylandWlShellSurface::FocusPolicy focusPolicy) +{ + Q_UNUSED(focusPolicy); + QWaylandWlShellSurface *wlShellSurface = qobject_cast<QWaylandWlShellSurface*>(sender()); + View *view = findView(wlShellSurface->surface()); + + if (view) { + raise(view); + View *parentView = findView(parent); + if (parentView) + view->setPosition(parentView->position() + relativeToParent); + } +} + +void Compositor::onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent) +{ + Q_UNUSED(inputDevice); + QWaylandWlShellSurface *surface = qobject_cast<QWaylandWlShellSurface*>(sender()); + View *view = findView(surface->surface()); + m_popupViews << view; + if (view) { + raise(view); + View *parentView = findView(parent); + if (parentView) + view->setPosition(parentView->position() + relativeToParent); + } +} + +void Compositor::onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent) +{ + View *view = findView(child); + View *parentView = findView(parent); + view->setParentView(parentView); +} + +void Compositor::onSubsurfacePositionChanged(const QPoint &position) +{ + QWaylandSurface *surface = qobject_cast<QWaylandSurface*>(sender()); + if (!surface) + return; + View *view = findView(surface); + view->setPosition(position); + triggerRender(); +} + +void Compositor::triggerRender() +{ + m_window->requestUpdate(); +} + +void Compositor::startRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->frameStarted(); +} + +void Compositor::endRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->sendFrameCallbacks(); +} + +void Compositor::updateCursor() +{ + m_cursorView.advance(); + QImage image = m_cursorView.currentBuffer().image(); + if (!image.isNull()) + m_window->setCursor(QCursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY)); +} + +void Compositor::adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) +{ + if ((m_cursorView.surface() != surface)) { + if (m_cursorView.surface()) + disconnect(m_cursorView.surface(), &QWaylandSurface::redraw, this, &Compositor::updateCursor); + if (surface) + connect(surface, &QWaylandSurface::redraw, this, &Compositor::updateCursor); + } + + m_cursorView.setSurface(surface); + m_cursorHotspotX = hotspotX; + m_cursorHotspotY = hotspotY; + + if (surface && surface->isMapped()) + updateCursor(); +} + +void Compositor::closePopups() +{ + Q_FOREACH (View *view, m_popupViews) { + if (view->m_wlShellSurface) + view->m_wlShellSurface->sendPopupDone(); + } + m_popupViews.clear(); + + m_xdgShell->closeAllPopups(); +} + +void Compositor::handleMouseEvent(QWaylandView *target, QMouseEvent *me) +{ + if (target && popupActive() && me->type() == QEvent::MouseButtonPress + && target->surface()->client() != m_popupViews.first()->surface()->client()) { + closePopups(); + } + QWaylandInputDevice *input = defaultInputDevice(); + QWaylandSurface *surface = target ? target->surface() : nullptr; + switch (me->type()) { + case QEvent::MouseButtonPress: + input->sendMousePressEvent(me->button()); + if (surface != input->keyboardFocus()) { + if (surface == nullptr + || surface->role() == QWaylandWlShellSurface::role() + || surface->role() == QWaylandXdgSurface::role() + || surface->role() == QWaylandXdgPopup::role()) { + input->setKeyboardFocus(surface); + } + } + break; + case QEvent::MouseButtonRelease: + input->sendMouseReleaseEvent(me->button()); + break; + case QEvent::MouseMove: + input->sendMouseMoveEvent(target, me->localPos(), me->globalPos()); + default: + break; + } +} + +void Compositor::handleResize(View *target, const QSize &initialSize, const QPoint &delta, int edge) +{ + QWaylandWlShellSurface *wlShellSurface = target->m_wlShellSurface; + if (wlShellSurface) { + QWaylandWlShellSurface::ResizeEdge edges = QWaylandWlShellSurface::ResizeEdge(edge); + QSize newSize = wlShellSurface->sizeForResize(initialSize, delta, edges); + wlShellSurface->sendConfigure(newSize, edges); + } + + QWaylandXdgSurface *xdgSurface = target->m_xdgSurface; + if (xdgSurface) { + QWaylandXdgSurface::ResizeEdge edges = static_cast<QWaylandXdgSurface::ResizeEdge>(edge); + QSize newSize = xdgSurface->sizeForResize(initialSize, delta, edges); + xdgSurface->requestResizing(newSize); + } +} + +void Compositor::startDrag() +{ + QWaylandDrag *currentDrag = defaultInputDevice()->drag(); + Q_ASSERT(currentDrag); + View *iconView = findView(currentDrag->icon()); + iconView->setPosition(m_window->mapFromGlobal(QCursor::pos())); + + emit dragStarted(iconView); +} + +void Compositor::handleDrag(View *target, QMouseEvent *me) +{ + QPointF pos = me->localPos(); + QWaylandSurface *surface = 0; + if (target) { + pos -= target->position(); + surface = target->surface(); + } + QWaylandDrag *currentDrag = defaultInputDevice()->drag(); + currentDrag->dragMove(surface, pos); + if (me->buttons() == Qt::NoButton) { + m_views.removeOne(findView(currentDrag->icon())); + currentDrag->drop(); + } +} + +// We only have a flat list of views, plus pointers from child to parent, +// so maintaining a stacking order gets a bit complex. A better data +// structure is left as an exercise for the reader. + +static int findEndOfChildTree(const QList<View*> &list, int index) +{ + int n = list.count(); + View *parent = list.at(index); + while (index + 1 < n) { + if (list.at(index+1)->parentView() != parent) + break; + index = findEndOfChildTree(list, index + 1); + } + return index; +} + +void Compositor::raise(View *view) +{ + int startPos = m_views.indexOf(view); + int endPos = findEndOfChildTree(m_views, startPos); + + int n = m_views.count(); + int tail = n - endPos - 1; + + //bubble sort: move the child tree to the end of the list + for (int i = 0; i < tail; i++) { + int source = endPos + 1 + i; + int dest = startPos + i; + for (int j = source; j > dest; j--) + m_views.swap(j, j-1); + } +} diff --git a/examples/wayland/qwindow-compositor/compositor.h b/examples/wayland/qwindow-compositor/compositor.h new file mode 100644 index 000000000..8eec0a58f --- /dev/null +++ b/examples/wayland/qwindow-compositor/compositor.h @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef WINDOWCOMPOSITOR_H +#define WINDOWCOMPOSITOR_H + +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandSurface> +#include <QtWaylandCompositor/QWaylandView> +#include <QtWaylandCompositor/QWaylandWlShellSurface> +#include <QtWaylandCompositor/QWaylandXdgSurface> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QWaylandWlShell; +class QWaylandWlShellSurface; +class QWaylandXdgShell; + +class View : public QWaylandView +{ + Q_OBJECT +public: + View(); + GLuint getTexture(GLenum *target = 0); + QPointF position() const { return m_position; } + void setPosition(const QPointF &pos) { m_position = pos; } + bool isCursor() const; + bool hasShell() const { return m_wlShellSurface; } + void setParentView(View *parent) { m_parentView = parent; } + View *parentView() const { return m_parentView; } + QPointF parentPosition() const { return m_parentView ? (m_parentView->position() + m_parentView->parentPosition()) : QPointF(); } + QSize windowSize() { return m_xdgSurface ? m_xdgSurface->windowGeometry().size() : surface()->size(); } + QPoint offset() const { return m_offset; } + +private: + friend class Compositor; + GLenum m_textureTarget; + GLuint m_texture; + QPointF m_position; + QWaylandWlShellSurface *m_wlShellSurface; + QWaylandXdgSurface *m_xdgSurface; + QWaylandXdgPopup *m_xdgPopup; + View *m_parentView; + QPoint m_offset; + +public slots: + void onXdgSetMaximized(); + void onXdgUnsetMaximized(); + void onXdgSetFullscreen(QWaylandOutput *output); + void onXdgUnsetFullscreen(); + void onOffsetForNextFrame(const QPoint &offset); +}; + +class Compositor : public QWaylandCompositor +{ + Q_OBJECT +public: + Compositor(QWindow *window); + ~Compositor(); + void create() Q_DECL_OVERRIDE; + + void startRender(); + void endRender(); + + QList<View*> views() const { return m_views; } + void raise(View *view); + + void handleMouseEvent(QWaylandView *target, QMouseEvent *me); + void handleResize(View *target, const QSize &initialSize, const QPoint &delta, int edge); + void handleDrag(View *target, QMouseEvent *me); + + bool popupActive() const { return !m_popupViews.isEmpty(); } + void closePopups(); +protected: + void adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); + +signals: + void startMove(); + void startResize(int edge, bool anchored); + void dragStarted(View *dragIcon); + void frameOffset(const QPoint &offset); + +private slots: + void surfaceMappedChanged(); + void surfaceDestroyed(); + void viewSurfaceDestroyed(); + void onStartMove(); + void onWlStartResize(QWaylandInputDevice *inputDevice, QWaylandWlShellSurface::ResizeEdge edges); + void onXdgStartResize(QWaylandInputDevice *inputDevice, QWaylandXdgSurface::ResizeEdge edges); + + void startDrag(); + + void triggerRender(); + + void onSurfaceCreated(QWaylandSurface *surface); + void onWlShellSurfaceCreated(QWaylandWlShellSurface *wlShellSurface); + void onXdgSurfaceCreated(QWaylandXdgSurface *xdgSurface); + void onCreateXdgPopup(QWaylandSurface *surface, QWaylandSurface *parent, QWaylandInputDevice *inputDevice, + const QPoint &position, const QWaylandResource &resource); + void onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, QWaylandWlShellSurface::FocusPolicy focusPolicy); + void onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent); + + void onSubsurfaceChanged(QWaylandSurface *child, QWaylandSurface *parent); + void onSubsurfacePositionChanged(const QPoint &position); + + void updateCursor(); +private: + View *findView(const QWaylandSurface *s) const; + QWindow *m_window; + QList<View*> m_views; + QList<View*> m_popupViews; + QWaylandWlShell *m_wlShell; + QWaylandXdgShell *m_xdgShell; + QWaylandView m_cursorView; + int m_cursorHotspotX; + int m_cursorHotspotY; +}; + + +QT_END_NAMESPACE + +#endif // WINDOWCOMPOSITOR_H diff --git a/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc b/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc new file mode 100644 index 000000000..d268aca43 --- /dev/null +++ b/examples/wayland/qwindow-compositor/doc/src/qwindow-compositor.qdoc @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \title Qt Wayland Compositor Examples - QWindow Compositor + \example qwindow-compositor + \brief QWindow Compositor is an example that demonstrates how to write a Wayland compositor in C++. + \ingroup qtwaylandcompositor-examples + + QWindow Compositor is a desktop-style Wayland compositor example that demonstrates the power + of the Qt Wayland Compositor C++ APIs. +*/ diff --git a/examples/wayland/qwindow-compositor/main.cpp b/examples/wayland/qwindow-compositor/main.cpp index b4be143b5..7ca868fce 100644 --- a/examples/wayland/qwindow-compositor/main.cpp +++ b/examples/wayland/qwindow-compositor/main.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the examples of the Qt Wayland module ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -38,36 +38,19 @@ ** ****************************************************************************/ -#include "compositorwindow.h" -#include "qwindowcompositor.h" - #include <QGuiApplication> -#include <QStringList> -#include <QScreen> -#include <QSurfaceFormat> +#include "window.h" +#include "compositor.h" int main(int argc, char *argv[]) { - // Enable the following to have touch events generated from mouse events. - // Very handy for testing touch event delivery without a real touch device. - // QGuiApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); - QGuiApplication app(argc, argv); - QScreen *screen = QGuiApplication::primaryScreen(); - QRect screenGeometry = screen->availableGeometry(); - - QSurfaceFormat format; - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - - QRect geom = screenGeometry; - if (QCoreApplication::arguments().contains(QLatin1String("-nofullscreen"))) - geom = QRect(screenGeometry.width() / 4, screenGeometry.height() / 4, - screenGeometry.width() / 2, screenGeometry.height() / 2); - - CompositorWindow window(format, geom); - QWindowCompositor compositor(&window); + Window window; + Compositor compositor(&window); + window.setCompositor(&compositor); + compositor.create(); + window.resize(800,600); window.show(); return app.exec(); diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.pro b/examples/wayland/qwindow-compositor/qwindow-compositor.pro index ad222860e..8cc7279d1 100644 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.pro +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.pro @@ -1,25 +1,18 @@ -QT += gui gui-private core-private compositor +QT += gui gui-private core-private waylandcompositor waylandcompositor-private LIBS += -L ../../lib -#include (../../src/qt-compositor/qt-compositor.pri) HEADERS += \ - compositorwindow.h \ - qwindowcompositor.h \ - textureblitter.h + window.h \ + compositor.h SOURCES += main.cpp \ - compositorwindow.cpp \ - qwindowcompositor.cpp \ - textureblitter.cpp + window.cpp \ + compositor.cpp -# to make QtCompositor/... style includes working without installing +# to make QtWaylandCompositor/... style includes working without installing INCLUDEPATH += $$PWD/../../include -# if you want to compile QtCompositor as part of the application -# instead of linking to it, remove the QT += compositor and uncomment -# the following line -#include(../../src/compositor/compositor.pri) RESOURCES += qwindow-compositor.qrc diff --git a/examples/wayland/qwindow-compositor/qwindow-compositor.qrc b/examples/wayland/qwindow-compositor/qwindow-compositor.qrc index 20dd10a53..688dd900e 100644 --- a/examples/wayland/qwindow-compositor/qwindow-compositor.qrc +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.qrc @@ -1,5 +1,5 @@ <RCC> <qresource prefix="/"> - <file alias="background.jpg">../qml-compositor/background.jpg</file> + <file alias="background.jpg">../pure-qml/images/background.jpg</file> </qresource> </RCC> diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp deleted file mode 100644 index 4e3f6336b..000000000 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwindowcompositor.h" - -#include <QMouseEvent> -#include <QKeyEvent> -#include <QTouchEvent> -#include <QOpenGLFunctions> -#include <QOpenGLTexture> -#include <QGuiApplication> -#include <QCursor> -#include <QPixmap> -#include <QLinkedList> -#include <QScreen> -#include <QPainter> - -#include <QtCompositor/qwaylandinput.h> -#include <QtCompositor/qwaylandbufferref.h> -#include <QtCompositor/qwaylandsurfaceview.h> -#include <QtCompositor/qwaylandoutput.h> - -QT_BEGIN_NAMESPACE - -class BufferAttacher : public QWaylandBufferAttacher -{ -public: - BufferAttacher() - : QWaylandBufferAttacher() - , shmTex(0) - { - } - - ~BufferAttacher() - { - delete shmTex; - } - - void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE - { - if (bufferRef) { - if (bufferRef.isShm()) { - delete shmTex; - shmTex = 0; - } else { - bufferRef.destroyTexture(); - } - } - - bufferRef = ref; - - if (bufferRef) { - if (bufferRef.isShm()) { - shmTex = new QOpenGLTexture(bufferRef.image(), QOpenGLTexture::DontGenerateMipMaps); - shmTex->setWrapMode(QOpenGLTexture::ClampToEdge); - texture = shmTex->textureId(); - textureTarget = GL_TEXTURE_2D; - } else { - texture = bufferRef.createTexture(); - textureTarget = bufferRef.textureTarget(); - } - } - } - - void unmap() - { - delete shmTex; - shmTex = 0; - bufferRef = QWaylandBufferRef(); - } - - QImage image() const - { - if (!bufferRef || !bufferRef.isShm()) - return QImage(); - return bufferRef.image(); - } - - void updateTexture() - { - if (bufferRef) - bufferRef.updateTexture(); - } - - QOpenGLTexture *shmTex; - QWaylandBufferRef bufferRef; - GLuint texture; - GLenum textureTarget; -}; - -QWindowCompositor::QWindowCompositor(CompositorWindow *window) - : QWaylandCompositor(0, DefaultExtensions | SubSurfaceExtension) - , m_window(window) - , m_backgroundTexture(0) - , m_textureBlitter(0) - , m_renderScheduler(this) - , m_draggingWindow(0) - , m_dragKeyIsPressed(false) - , m_cursorSurface(0) - , m_cursorHotspotX(0) - , m_cursorHotspotY(0) - , m_modifiers(Qt::NoModifier) -{ - m_window->makeCurrent(); - - m_textureBlitter = new TextureBlitter(); - m_backgroundImage = makeBackgroundImage(QLatin1String(":/background.jpg")); - m_renderScheduler.setSingleShot(true); - connect(&m_renderScheduler,SIGNAL(timeout()),this,SLOT(render())); - - QOpenGLFunctions *functions = m_window->context()->functions(); - functions->glGenFramebuffers(1, &m_surface_fbo); - - window->installEventFilter(this); - - setRetainedSelectionEnabled(true); - - createOutput(window, "", ""); - addDefaultShell(); -} - -QWindowCompositor::~QWindowCompositor() -{ - delete m_textureBlitter; -} - - -QImage QWindowCompositor::makeBackgroundImage(const QString &fileName) -{ - Q_ASSERT(m_window); - - int width = m_window->width(); - int height = m_window->height(); - QImage baseImage(fileName); - QImage patternedBackground(width, height, baseImage.format()); - QPainter painter(&patternedBackground); - - QSize imageSize = baseImage.size(); - for (int y = 0; y < height; y += imageSize.height()) { - for (int x = 0; x < width; x += imageSize.width()) { - painter.drawImage(x, y, baseImage); - } - } - - return patternedBackground; -} - -void QWindowCompositor::ensureKeyboardFocusSurface(QWaylandSurface *oldSurface) -{ - QWaylandSurface *kbdFocus = defaultInputDevice()->keyboardFocus(); - if (kbdFocus == oldSurface || !kbdFocus) - defaultInputDevice()->setKeyboardFocus(m_surfaces.isEmpty() ? 0 : m_surfaces.last()); -} - -void QWindowCompositor::surfaceDestroyed() -{ - QWaylandSurface *surface = static_cast<QWaylandSurface *>(sender()); - m_surfaces.removeOne(surface); - ensureKeyboardFocusSurface(surface); - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceMapped() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - QPoint pos; - if (!m_surfaces.contains(surface)) { - if (surface->windowType() != QWaylandSurface::Popup) { - uint px = 0; - uint py = 0; - if (!QCoreApplication::arguments().contains(QLatin1String("-stickytopleft"))) { - px = 1 + (qrand() % (m_window->width() - surface->size().width() - 2)); - py = 1 + (qrand() % (m_window->height() - surface->size().height() - 2)); - } - pos = QPoint(px, py); - QWaylandSurfaceView *view = surface->views().first(); - view->setPos(pos); - } - } else { - m_surfaces.removeOne(surface); - } - - if (surface->windowType() == QWaylandSurface::Popup) { - QWaylandSurfaceView *view = surface->views().first(); - view->setPos(surface->transientParent()->views().first()->pos() + surface->transientOffset()); - } - - m_surfaces.append(surface); - defaultInputDevice()->setKeyboardFocus(surface); - - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceUnmapped() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - if (m_surfaces.removeOne(surface)) - m_surfaces.insert(0, surface); - - ensureKeyboardFocusSurface(surface); - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceCommitted() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - surfaceCommitted(surface); -} - -void QWindowCompositor::surfacePosChanged() -{ - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceCommitted(QWaylandSurface *surface) -{ - Q_UNUSED(surface) - m_renderScheduler.start(0); -} - -void QWindowCompositor::surfaceCreated(QWaylandSurface *surface) -{ - connect(surface, SIGNAL(surfaceDestroyed()), this, SLOT(surfaceDestroyed())); - connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped())); - connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped())); - connect(surface, SIGNAL(redraw()), this, SLOT(surfaceCommitted())); - connect(surface, SIGNAL(extendedSurfaceReady()), this, SLOT(sendExpose())); - m_renderScheduler.start(0); - - surface->setBufferAttacher(new BufferAttacher); -} - -void QWindowCompositor::sendExpose() -{ - QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); - surface->sendOnScreenVisibilityChange(true); -} - -void QWindowCompositor::updateCursor(bool hasBuffer) -{ - Q_UNUSED(hasBuffer) - if (!m_cursorSurface) - return; - - QImage image = static_cast<BufferAttacher *>(m_cursorSurface->bufferAttacher())->image(); - - QCursor cursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY); - static bool cursorIsSet = false; - if (cursorIsSet) { - QGuiApplication::changeOverrideCursor(cursor); - } else { - QGuiApplication::setOverrideCursor(cursor); - cursorIsSet = true; - } -} - -QPointF QWindowCompositor::toView(QWaylandSurfaceView *view, const QPointF &pos) const -{ - return pos - view->pos(); -} - -void QWindowCompositor::setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) -{ - if ((m_cursorSurface != surface) && surface) - connect(surface, SIGNAL(configure(bool)), this, SLOT(updateCursor(bool))); - - m_cursorSurface = surface; - m_cursorHotspotX = hotspotX; - m_cursorHotspotY = hotspotY; - if (m_cursorSurface && !m_cursorSurface->bufferAttacher()) - m_cursorSurface->setBufferAttacher(new BufferAttacher); -} - -QWaylandSurfaceView *QWindowCompositor::viewAt(const QPointF &point, QPointF *local) -{ - for (int i = m_surfaces.size() - 1; i >= 0; --i) { - QWaylandSurface *surface = m_surfaces.at(i); - foreach (QWaylandSurfaceView *view, surface->views()) { - QRectF geo(view->pos(), surface->size()); - if (geo.contains(point)) { - if (local) - *local = toView(view, point); - return view; - } - } - } - return 0; -} - -void QWindowCompositor::render() -{ - m_window->makeCurrent(); - frameStarted(); - - cleanupGraphicsResources(); - - if (!m_backgroundTexture) - m_backgroundTexture = new QOpenGLTexture(m_backgroundImage, QOpenGLTexture::DontGenerateMipMaps); - - m_textureBlitter->bind(GL_TEXTURE_2D); - // Draw the background image texture - m_textureBlitter->drawTexture(m_backgroundTexture->textureId(), - QRect(QPoint(0, 0), m_backgroundImage.size()), - m_window->size(), - 0, false, true); - - foreach (QWaylandSurface *surface, m_surfaces) { - if (!surface->visible()) - continue; - BufferAttacher *ba = static_cast<BufferAttacher *>(surface->bufferAttacher()); - ba->updateTexture(); - const GLuint texture = ba->texture; - const GLenum target = ba->textureTarget; - m_textureBlitter->bind(target); - foreach (QWaylandSurfaceView *view, surface->views()) { - QRect geo(view->pos().toPoint(),surface->size()); - m_textureBlitter->drawTexture(texture,geo,m_window->size(),0,false,surface->isYInverted()); - foreach (QWaylandSurface *child, surface->subSurfaces()) { - drawSubSurface(view->pos().toPoint(), child); - } - } - } - - m_textureBlitter->release(); - sendFrameCallbacks(surfaces()); - - // N.B. Never call glFinish() here as the busylooping with vsync 'feature' of the nvidia binary driver is not desirable. - m_window->swapBuffers(); -} - -void QWindowCompositor::drawSubSurface(const QPoint &offset, QWaylandSurface *surface) -{ - GLuint texture = static_cast<BufferAttacher *>(surface->bufferAttacher())->texture; - QWaylandSurfaceView *view = surface->views().first(); - QPoint pos = view->pos().toPoint() + offset; - QRect geo(pos, surface->size()); - m_textureBlitter->drawTexture(texture, geo, m_window->size(), 0, false, surface->isYInverted()); - foreach (QWaylandSurface *child, surface->subSurfaces()) { - drawSubSurface(pos, child); - } -} - -bool QWindowCompositor::eventFilter(QObject *obj, QEvent *event) -{ - if (obj != m_window) - return false; - - QWaylandInputDevice *input = defaultInputDevice(); - - switch (event->type()) { - case QEvent::Expose: - m_renderScheduler.start(0); - if (m_window->isExposed()) { - // Alt-tabbing away normally results in the alt remaining in - // pressed state in the clients xkb state. Prevent this by sending - // a release. This is not an issue in a "real" compositor but - // is very annoying when running in a regular window on xcb. - Qt::KeyboardModifiers mods = QGuiApplication::queryKeyboardModifiers(); - if (m_modifiers != mods && input->keyboardFocus()) { - Qt::KeyboardModifiers stuckMods = m_modifiers ^ mods; - if (stuckMods & Qt::AltModifier) - input->sendKeyReleaseEvent(64); // native scancode for left alt - m_modifiers = mods; - } - } - break; - case QEvent::MouseButtonPress: { - QPointF local; - QMouseEvent *me = static_cast<QMouseEvent *>(event); - QWaylandSurfaceView *target = viewAt(me->localPos(), &local); - if (m_dragKeyIsPressed && target) { - m_draggingWindow = target; - m_drag_diff = local; - } else { - if (target && input->keyboardFocus() != target->surface()) { - input->setKeyboardFocus(target->surface()); - m_surfaces.removeOne(target->surface()); - m_surfaces.append(target->surface()); - m_renderScheduler.start(0); - } - input->sendMousePressEvent(me->button(), local, me->localPos()); - } - return true; - } - case QEvent::MouseButtonRelease: { - QWaylandSurfaceView *target = input->mouseFocus(); - if (m_draggingWindow) { - m_draggingWindow = 0; - m_drag_diff = QPointF(); - } else { - QMouseEvent *me = static_cast<QMouseEvent *>(event); - QPointF localPos; - if (target) - localPos = toView(target, me->localPos()); - input->sendMouseReleaseEvent(me->button(), localPos, me->localPos()); - } - return true; - } - case QEvent::MouseMove: { - QMouseEvent *me = static_cast<QMouseEvent *>(event); - if (m_draggingWindow) { - m_draggingWindow->setPos(me->localPos() - m_drag_diff); - m_renderScheduler.start(0); - } else { - QPointF local; - QWaylandSurfaceView *target = viewAt(me->localPos(), &local); - input->sendMouseMoveEvent(target, local, me->localPos()); - } - break; - } - case QEvent::Wheel: { - QWheelEvent *we = static_cast<QWheelEvent *>(event); - input->sendMouseWheelEvent(we->orientation(), we->delta()); - break; - } - case QEvent::KeyPress: { - QKeyEvent *ke = static_cast<QKeyEvent *>(event); - if (ke->key() == Qt::Key_Meta || ke->key() == Qt::Key_Super_L) { - m_dragKeyIsPressed = true; - } - m_modifiers = ke->modifiers(); - QWaylandSurface *targetSurface = input->keyboardFocus(); - if (targetSurface) - input->sendKeyPressEvent(ke->nativeScanCode()); - break; - } - case QEvent::KeyRelease: { - QKeyEvent *ke = static_cast<QKeyEvent *>(event); - if (ke->key() == Qt::Key_Meta || ke->key() == Qt::Key_Super_L) { - m_dragKeyIsPressed = false; - } - m_modifiers = ke->modifiers(); - QWaylandSurface *targetSurface = input->keyboardFocus(); - if (targetSurface) - input->sendKeyReleaseEvent(ke->nativeScanCode()); - break; - } - case QEvent::TouchBegin: - case QEvent::TouchUpdate: - case QEvent::TouchEnd: - { - QWaylandSurfaceView *target = 0; - QTouchEvent *te = static_cast<QTouchEvent *>(event); - QList<QTouchEvent::TouchPoint> points = te->touchPoints(); - QPoint pointPos; - if (!points.isEmpty()) { - pointPos = points.at(0).pos().toPoint(); - target = viewAt(pointPos); - } - if (target && target != input->mouseFocus()) - input->setMouseFocus(target, pointPos, pointPos); - if (input->mouseFocus()) - input->sendFullTouchEvent(te); - break; - } - default: - break; - } - return false; -} - -QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/textureblitter.cpp b/examples/wayland/qwindow-compositor/textureblitter.cpp deleted file mode 100644 index df4fa18d8..000000000 --- a/examples/wayland/qwindow-compositor/textureblitter.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Compositor. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "textureblitter.h" - -#include <QtGui/QOpenGLShaderProgram> -#include <QtGui/QOpenGLContext> -#include <QtGui/QOpenGLFunctions> - -#ifndef GL_TEXTURE_EXTERNAL_OES -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#endif - -QT_BEGIN_NAMESPACE - -TextureBlitter::TextureBlitter() - : m_shaderProgram(new QOpenGLShaderProgram) - , m_shaderProgramExternal(new QOpenGLShaderProgram) - , m_currentProgram(0) - , m_currentTarget(GL_TEXTURE_2D) -{ - static const char *textureVertexProgram = - "uniform highp mat4 matrix;\n" - "attribute highp vec3 vertexCoordEntry;\n" - "attribute highp vec2 textureCoordEntry;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " textureCoord = textureCoordEntry;\n" - " gl_Position = matrix * vec4(vertexCoordEntry, 1);\n" - "}\n"; - - static const char *textureFragmentProgram = - "uniform sampler2D texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord);\n" - "}\n"; - - static const char *textureFragmentProgramExternal = - "#extension GL_OES_EGL_image_external : require\n" - "uniform samplerExternalOES texture;\n" - "varying highp vec2 textureCoord;\n" - "void main() {\n" - " gl_FragColor = texture2D(texture, textureCoord);\n" - "}\n"; - - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); - m_shaderProgram->link(); - - m_shaderProgramExternal->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); - m_shaderProgramExternal->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgramExternal); - m_shaderProgramExternal->link(); -} - -TextureBlitter::~TextureBlitter() -{ - delete m_shaderProgram; - delete m_shaderProgramExternal; -} - -void TextureBlitter::bind(quint32 target) -{ - m_currentTarget = target; - switch (target) { - case GL_TEXTURE_2D: - m_currentProgram = m_shaderProgram; - break; - case GL_TEXTURE_EXTERNAL_OES: - m_currentProgram = m_shaderProgramExternal; - break; - default: - qFatal("INVALID TARGET TYPE %d", target); - break; - } - - m_currentProgram->bind(); - - m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry"); - m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry"); - m_matrixLocation = m_shaderProgram->uniformLocation("matrix"); - - //Enable transparent windows - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -} - -void TextureBlitter::release() -{ - m_currentProgram->release(); -} - -void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const QSize &targetSize, int depth, bool targethasInvertedY, bool sourceHasInvertedY) -{ - - glViewport(0,0,targetSize.width(),targetSize.height()); - GLfloat zValue = depth / 1000.0f; - //Set Texture and Vertex coordinates - const GLfloat textureCoordinates[] = { - 0, 0, - 1, 0, - 1, 1, - 0, 1 - }; - - GLfloat x1 = targetRect.left(); - GLfloat x2 = targetRect.right(); - GLfloat y1, y2; - if (targethasInvertedY) { - if (sourceHasInvertedY) { - y1 = targetRect.top(); - y2 = targetRect.bottom(); - } else { - y1 = targetRect.bottom(); - y2 = targetRect.top(); - } - } else { - if (sourceHasInvertedY) { - y1 = targetSize.height() - targetRect.top(); - y2 = targetSize.height() - targetRect.bottom(); - } else { - y1 = targetSize.height() - targetRect.bottom(); - y2 = targetSize.height() - targetRect.top(); - } - } - - const GLfloat vertexCoordinates[] = { - GLfloat(x1), GLfloat(y1), zValue, - GLfloat(x2), GLfloat(y1), zValue, - GLfloat(x2), GLfloat(y2), zValue, - GLfloat(x1), GLfloat(y2), zValue - }; - - //Set matrix to transfrom geometry values into gl coordinate space. - m_transformMatrix.setToIdentity(); - m_transformMatrix.scale( 2.0f / targetSize.width(), 2.0f / targetSize.height() ); - m_transformMatrix.translate(-targetSize.width() / 2.0f, -targetSize.height() / 2.0f); - - //attach the data! - QOpenGLContext *currentContext = QOpenGLContext::currentContext(); - currentContext->functions()->glEnableVertexAttribArray(m_vertexCoordEntry); - currentContext->functions()->glEnableVertexAttribArray(m_textureCoordEntry); - - currentContext->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates); - currentContext->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates); - - m_currentProgram->setUniformValue(m_matrixLocation, m_transformMatrix); - - glBindTexture(m_currentTarget, textureId); - - glTexParameterf(m_currentTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(m_currentTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - - glBindTexture(m_currentTarget, 0); - - currentContext->functions()->glDisableVertexAttribArray(m_vertexCoordEntry); - currentContext->functions()->glDisableVertexAttribArray(m_textureCoordEntry); -} - -QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/window.cpp b/examples/wayland/qwindow-compositor/window.cpp new file mode 100644 index 000000000..c3fc9b7df --- /dev/null +++ b/examples/wayland/qwindow-compositor/window.cpp @@ -0,0 +1,277 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Wayland module +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "window.h" + +#include <QMouseEvent> +#include <QOpenGLWindow> +#include <QOpenGLTexture> +#include <QOpenGLFunctions> +#include <QMatrix4x4> + +#include "compositor.h" +#include <QtWaylandCompositor/qwaylandinput.h> + +Window::Window() + : m_backgroundTexture(0) + , m_compositor(0) + , m_grabState(NoGrab) + , m_dragIconView(0) +{ +} + +void Window::setCompositor(Compositor *comp) { + m_compositor = comp; + connect(m_compositor, &Compositor::startMove, this, &Window::startMove); + connect(m_compositor, &Compositor::startResize, this, &Window::startResize); + connect(m_compositor, &Compositor::dragStarted, this, &Window::startDrag); +} + +void Window::initializeGL() +{ + QImage backgroundImage = QImage(QLatin1String(":/background.jpg")); + m_backgroundTexture = new QOpenGLTexture(backgroundImage, QOpenGLTexture::DontGenerateMipMaps); + m_backgroundTexture->setMinificationFilter(QOpenGLTexture::Nearest); + m_backgroundImageSize = backgroundImage.size(); + m_textureBlitter.create(); +} + +void Window::drawBackground() +{ + for (int y = 0; y < height(); y += m_backgroundImageSize.height()) { + for (int x = 0; x < width(); x += m_backgroundImageSize.width()) { + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(x,y), m_backgroundImageSize), QRect(QPoint(0,0), size())); + m_textureBlitter.blit(m_backgroundTexture->textureId(), + targetTransform, + QOpenGLTextureBlitter::OriginTopLeft); + } + } +} + +QPointF Window::getAnchorPosition(const QPointF &position, int resizeEdge, const QSize &windowSize) +{ + float y = position.y(); + if (resizeEdge & QWaylandXdgSurface::ResizeEdge::TopEdge) + y += windowSize.height(); + + float x = position.x(); + if (resizeEdge & QWaylandXdgSurface::ResizeEdge::LeftEdge) + x += windowSize.width(); + + return QPointF(x, y); +} + +QPointF Window::getAnchoredPosition(const QPointF &anchorPosition, int resizeEdge, const QSize &windowSize) +{ + return anchorPosition - getAnchorPosition(QPointF(), resizeEdge, windowSize); +} + +void Window::paintGL() +{ + m_compositor->startRender(); + QOpenGLFunctions *functions = context()->functions(); + functions->glClearColor(1.f, .6f, .0f, 0.5f); + functions->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + m_textureBlitter.bind(); + drawBackground(); + + functions->glEnable(GL_BLEND); + functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + GLenum currentTarget = GL_TEXTURE_2D; + Q_FOREACH (View *view, m_compositor->views()) { + if (view->isCursor()) + continue; + GLenum target; + GLuint textureId = view->getTexture(&target); + if (!textureId || !target) + continue; + if (target != currentTarget) { + currentTarget = target; + m_textureBlitter.bind(currentTarget); + } + QWaylandSurface *surface = view->surface(); + if (surface && surface->isMapped()) { + QSize s = surface->size(); + if (!s.isEmpty()) { + if (m_mouseView == view && m_grabState == ResizeGrab && m_resizeAnchored) + view->setPosition(getAnchoredPosition(m_resizeAnchorPosition, m_resizeEdge, s)); + QPointF pos = view->position() + view->parentPosition(); + QRectF surfaceGeometry(pos, s); + QOpenGLTextureBlitter::Origin surfaceOrigin = + view->currentBuffer().origin() == QWaylandSurface::OriginTopLeft + ? QOpenGLTextureBlitter::OriginTopLeft + : QOpenGLTextureBlitter::OriginBottomLeft; + QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size())); + m_textureBlitter.blit(textureId, targetTransform, surfaceOrigin); + } + } + } + functions->glDisable(GL_BLEND); + + m_textureBlitter.release(); + m_compositor->endRender(); +} + +View *Window::viewAt(const QPointF &point) +{ + View *ret = 0; + Q_FOREACH (View *view, m_compositor->views()) { + if (view == m_dragIconView) + continue; + QPointF topLeft = view->position(); + QWaylandSurface *surface = view->surface(); + QRectF geo(topLeft, surface->size()); + if (geo.contains(point)) + ret = view; + } + return ret; +} + +void Window::startMove() +{ + m_grabState = MoveGrab; +} + +void Window::startResize(int edge, bool anchored) +{ + m_initialSize = m_mouseView->windowSize(); + m_grabState = ResizeGrab; + m_resizeEdge = edge; + m_resizeAnchored = anchored; + m_resizeAnchorPosition = getAnchorPosition(m_mouseView->position(), edge, m_mouseView->surface()->size()); +} + +void Window::startDrag(View *dragIcon) +{ + m_grabState = DragGrab; + m_dragIconView = dragIcon; + m_compositor->raise(dragIcon); +} + +void Window::mousePressEvent(QMouseEvent *e) +{ + if (mouseGrab()) + return; + if (m_mouseView.isNull()) { + m_mouseView = viewAt(e->localPos()); + if (!m_mouseView) { + m_compositor->closePopups(); + return; + } + if (e->modifiers() == Qt::AltModifier || e->modifiers() == Qt::MetaModifier) + m_grabState = MoveGrab; //start move + else + m_compositor->raise(m_mouseView); + m_initialMousePos = e->localPos(); + m_mouseOffset = e->localPos() - m_mouseView->position(); + + QMouseEvent moveEvent(QEvent::MouseMove, e->localPos(), e->globalPos(), Qt::NoButton, Qt::NoButton, e->modifiers()); + sendMouseEvent(&moveEvent, m_mouseView); + } + sendMouseEvent(e, m_mouseView); +} + +void Window::mouseReleaseEvent(QMouseEvent *e) +{ + if (!mouseGrab()) + sendMouseEvent(e, m_mouseView); + if (e->buttons() == Qt::NoButton) { + if (m_grabState == DragGrab) { + View *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + } + m_mouseView = 0; + m_grabState = NoGrab; + } +} + +void Window::mouseMoveEvent(QMouseEvent *e) +{ + switch (m_grabState) { + case NoGrab: { + View *view = m_mouseView ? m_mouseView.data() : viewAt(e->localPos()); + sendMouseEvent(e, view); + if (!view) + setCursor(Qt::ArrowCursor); + } + break; + case MoveGrab: { + m_mouseView->setPosition(e->localPos() - m_mouseOffset); + update(); + } + break; + case ResizeGrab: { + QPoint delta = (e->localPos() - m_initialMousePos).toPoint(); + m_compositor->handleResize(m_mouseView, m_initialSize, delta, m_resizeEdge); + } + break; + case DragGrab: { + View *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + if (m_dragIconView) { + m_dragIconView->setPosition(e->localPos() + m_dragIconView->offset()); + update(); + } + } + break; + } +} + +void Window::sendMouseEvent(QMouseEvent *e, View *target) +{ + if (!target) + return; + + QPointF mappedPos = e->localPos() - target->position(); + QMouseEvent viewEvent(e->type(), mappedPos, e->localPos(), e->button(), e->buttons(), e->modifiers()); + m_compositor->handleMouseEvent(target, &viewEvent); +} + +void Window::keyPressEvent(QKeyEvent *e) +{ + m_compositor->defaultInputDevice()->sendKeyPressEvent(e->nativeScanCode()); +} + +void Window::keyReleaseEvent(QKeyEvent *e) +{ + m_compositor->defaultInputDevice()->sendKeyReleaseEvent(e->nativeScanCode()); +} diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.h b/examples/wayland/qwindow-compositor/window.h index cb70369c2..9a01e2831 100644 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.h +++ b/examples/wayland/qwindow-compositor/window.h @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the Qt Compositor. +** This file is part of the examples of the Qt Wayland module ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: @@ -38,80 +38,67 @@ ** ****************************************************************************/ -#ifndef QWINDOWCOMPOSITOR_H -#define QWINDOWCOMPOSITOR_H +#ifndef COMPOSITORWINDOW_H +#define COMPOSITORWINDOW_H -#include "qwaylandcompositor.h" -#include "qwaylandsurface.h" -#include "textureblitter.h" -#include "compositorwindow.h" - -#include <QtGui/private/qopengltexturecache_p.h> -#include <QObject> -#include <QTimer> +#include <QOpenGLWindow> +#include <QPointer> +#include <QtGui/private/qopengltextureblitter_p.h> QT_BEGIN_NAMESPACE -class QWaylandSurfaceView; +class Compositor; +class View; class QOpenGLTexture; -class QWindowCompositor : public QObject, public QWaylandCompositor +class Window : public QOpenGLWindow { - Q_OBJECT public: - QWindowCompositor(CompositorWindow *window); - ~QWindowCompositor(); + Window(); -private slots: - void surfaceDestroyed(); - void surfaceMapped(); - void surfaceUnmapped(); - void surfaceCommitted(); - void surfacePosChanged(); + void setCompositor(Compositor *comp); - void render(); protected: - void surfaceCommitted(QWaylandSurface *surface); - void surfaceCreated(QWaylandSurface *surface); - - QWaylandSurfaceView* viewAt(const QPointF &point, QPointF *local = 0); - - bool eventFilter(QObject *obj, QEvent *event); - QPointF toView(QWaylandSurfaceView *view, const QPointF &pos) const; + void initializeGL() Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; - void setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; - void ensureKeyboardFocusSurface(QWaylandSurface *oldSurface); - QImage makeBackgroundImage(const QString &fileName); + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void keyReleaseEvent(QKeyEvent *e) Q_DECL_OVERRIDE; private slots: - void sendExpose(); - void updateCursor(bool hasBuffer); + void startMove(); + void startResize(int edge, bool anchored); + void startDrag(View *dragIcon); private: - void drawSubSurface(const QPoint &offset, QWaylandSurface *surface); + enum GrabState { NoGrab, MoveGrab, ResizeGrab, DragGrab }; - CompositorWindow *m_window; - QImage m_backgroundImage; - QOpenGLTexture *m_backgroundTexture; - QList<QWaylandSurface *> m_surfaces; - TextureBlitter *m_textureBlitter; - GLuint m_surface_fbo; - QTimer m_renderScheduler; - - //Dragging windows around - QWaylandSurfaceView *m_draggingWindow; - bool m_dragKeyIsPressed; - QPointF m_drag_diff; + View *viewAt(const QPointF &point); + bool mouseGrab() const { return m_grabState != NoGrab ;} + void drawBackground(); + void sendMouseEvent(QMouseEvent *e, View *target); + static QPointF getAnchoredPosition(const QPointF &anchorPosition, int resizeEdge, const QSize &windowSize); + static QPointF getAnchorPosition(const QPointF &position, int resizeEdge, const QSize &windowSize); - //Cursor - QWaylandSurface *m_cursorSurface; - int m_cursorHotspotX; - int m_cursorHotspotY; - - Qt::KeyboardModifiers m_modifiers; + QOpenGLTextureBlitter m_textureBlitter; + QSize m_backgroundImageSize; + QOpenGLTexture *m_backgroundTexture; + Compositor *m_compositor; + QPointer<View> m_mouseView; + GrabState m_grabState; + QSize m_initialSize; + int m_resizeEdge; + bool m_resizeAnchored; + QPointF m_resizeAnchorPosition; + QPointF m_mouseOffset; + QPointF m_initialMousePos; + View *m_dragIconView; }; QT_END_NAMESPACE -#endif // QWINDOWCOMPOSITOR_H +#endif // COMPOSITORWINDOW_H diff --git a/examples/wayland/server-buffer/client/client.pro b/examples/wayland/server-buffer/client/client.pro index 8aef051c1..6e5cc87e6 100644 --- a/examples/wayland/server-buffer/client/client.pro +++ b/examples/wayland/server-buffer/client/client.pro @@ -4,11 +4,11 @@ INCLUDEPATH += . QT += waylandclient-private -!contains(QT_CONFIG, no-pkg-config) { - PKGCONFIG += wayland-client - CONFIG += link_pkgconfig -} else { +contains(QT_CONFIG, no-pkg-config) { LIBS += -lwayland-client +} else { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-client } CONFIG += wayland-scanner diff --git a/examples/wayland/server-buffer/compositor/compositor.pro b/examples/wayland/server-buffer/compositor/compositor.pro index df291fbfd..28a781bd0 100644 --- a/examples/wayland/server-buffer/compositor/compositor.pro +++ b/examples/wayland/server-buffer/compositor/compositor.pro @@ -1,24 +1,27 @@ -QT += core-private gui-private quick-private compositor-private +QT += core-private gui-private quick-private waylandcompositor-private -LIBS += -lwayland-server +contains(QT_CONFIG, no-pkg-config) { + LIBS += -lwayland-server +} else { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-server +} SOURCES += \ main.cpp \ serverbufferitem.cpp + HEADERS += \ serverbufferitem.h \ serverbuffertextureprovider.h OTHER_FILES = \ - qml/main.qml \ - images/background.jpg \ + images/background.jpg RESOURCES += compositor.qrc -CONFIG +=wayland-scanner +CONFIG += wayland-scanner WAYLANDSERVERSOURCES += ../share-buffer.xml -DEFINES += QT_COMPOSITOR_QUICK - target.path = $$[QT_INSTALL_EXAMPLES]/wayland/server-buffer/compositor INSTALLS += target diff --git a/examples/wayland/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp index 312cff2c5..57ca647b6 100644 --- a/examples/wayland/server-buffer/compositor/main.cpp +++ b/examples/wayland/server-buffer/compositor/main.cpp @@ -41,7 +41,7 @@ #include "qwaylandquickcompositor.h" #include "qwaylandsurface.h" -#include "qwaylandsurfaceitem.h" +#include "qwaylandquickitem.h" #include <QGuiApplication> #include <QTimer> @@ -55,47 +55,61 @@ #include <QQuickView> #include "qwayland-server-share-buffer.h" -#include <QtCompositor/qwaylandoutput.h> -#include <QtCompositor/private/qwlcompositor_p.h> -#include <QtCompositor/private/qwlserverbufferintegration_p.h> +#include <QtWaylandCompositor/QWaylandQuickOutput> +#include <QtWaylandCompositor/QWaylandCompositor> +#include <QtWaylandCompositor/QWaylandQuickItem> +#include <QtWaylandCompositor/private/qwaylandcompositor_p.h> +#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h> #include "serverbufferitem.h" #include <QtGui/private/qdistancefield_p.h> class QmlCompositor - : public QQuickView - , public QWaylandQuickCompositor + : public QWaylandQuickCompositor , public QtWaylandServer::qt_share_buffer { Q_OBJECT public: QmlCompositor() - : QWaylandQuickCompositor(0, DefaultExtensions | SubSurfaceExtension) - , QtWaylandServer::qt_share_buffer(QWaylandCompositor::handle()->wl_display(), 1) + : QWaylandQuickCompositor() + , QtWaylandServer::qt_share_buffer(QWaylandCompositor::display(), 1) , m_server_buffer_32_bit(0) , m_server_buffer_item_32_bit(0) , m_server_buffer_8_bit(0) , m_server_buffer_item_8_bit(0) { - setSource(QUrl("qrc:/qml/main.qml")); - setResizeMode(QQuickView::SizeRootObjectToView); - setColor(Qt::black); create(); - grabWindow(); - createOutput(this, "", ""); - addDefaultShell(); + m_view.setSource(QUrl("qrc:/qml/main.qml")); + m_view.setResizeMode(QQuickView::SizeRootObjectToView); + m_view.setColor(Qt::black); + m_view.create(); + m_output = new QWaylandQuickOutput(this, &m_view); - connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks())); + connect(&m_view, &QQuickView::afterRendering, this, &QmlCompositor::sendCallbacks); - connect(this, SIGNAL(sceneGraphInitialized()), this, SLOT(initiateServerBuffer()),Qt::DirectConnection); - connect(this, SIGNAL(serverBuffersCreated()), this, SLOT(createServerBufferItems())); + connect(&m_view, &QQuickView::sceneGraphInitialized, this, &QmlCompositor::initiateServerBuffer,Qt::DirectConnection); + connect(this, &QmlCompositor::serverBuffersCreated, this, &QmlCompositor::createServerBufferItems); + + connect(&m_view, &QWindow::widthChanged, this, &QmlCompositor::sizeAdjusted); + connect(&m_view, &QWindow::heightChanged, this, &QmlCompositor::sizeAdjusted); + + connect(this, SIGNAL(windowAdded(QVariant)), m_view.rootObject(), SLOT(windowAdded(QVariant))); + connect(this, SIGNAL(windowResized(QVariant)), m_view.rootObject(), SLOT(windowResized(QVariant))); + connect(this, SIGNAL(serverBufferItemCreated(QVariant)), m_view.rootObject(), SLOT(serverBufferItemCreated(QVariant))); + connect(this, &QWaylandCompositor::surfaceCreated, this, &QmlCompositor::onSurfaceCreated); + + m_view.setTitle(QLatin1String("QML Compositor")); + m_view.setGeometry(0, 0, 1024, 768); + m_view.rootContext()->setContextProperty("compositor", this); + + m_view.show(); } - Q_INVOKABLE QWaylandSurfaceItem *item(QWaylandSurface *surf) + Q_INVOKABLE QWaylandQuickItem *item(QWaylandSurface *surf) { - return static_cast<QWaylandSurfaceItem *>(surf->views().first()); + return static_cast<QWaylandQuickItem *>(surf->views().first()->renderObject()); } signals: @@ -118,17 +132,17 @@ private slots: } void sendCallbacks() { - sendFrameCallbacks(surfaces()); + m_output->sendFrameCallbacks(); } void initiateServerBuffer() { - if (!QWaylandCompositor::handle()->serverBufferIntegration()) + if (!QWaylandCompositorPrivate::get(this)->serverBufferIntegration()) return; - openglContext()->makeCurrent(this); + m_view.openglContext()->makeCurrent(&m_view); - QtWayland::ServerBufferIntegration *sbi = QWaylandCompositor::handle()->serverBufferIntegration(); + QtWayland::ServerBufferIntegration *sbi = QWaylandCompositorPrivate::get(this)->serverBufferIntegration(); if (!sbi) { qWarning("Could not find a Server Buffer Integration"); return; @@ -197,14 +211,15 @@ private slots: } } protected: - void resizeEvent(QResizeEvent *event) + void sizeAdjusted() { - QQuickView::resizeEvent(event); - QWaylandCompositor::setOutputGeometry(QRect(0, 0, width(), height())); + defaultOutput()->setGeometry(QRect(QPoint(0, 0), m_view.size())); } - void surfaceCreated(QWaylandSurface *surface) { - connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped())); + void onSurfaceCreated(QWaylandSurface *surface) { + QWaylandQuickItem *item = new QWaylandQuickItem(); + item->setSurface(surface); + connect(surface, &QWaylandSurface::mappedChanged, this, &QmlCompositor::surfaceMapped); } void share_buffer_bind_resource(Resource *resource) Q_DECL_OVERRIDE @@ -224,6 +239,8 @@ protected: } private: + QQuickView m_view; + QWaylandOutput *m_output; QtWayland::ServerBuffer *m_server_buffer_32_bit; ServerBufferItem *m_server_buffer_item_32_bit; QtWayland::ServerBuffer *m_server_buffer_8_bit; @@ -242,18 +259,8 @@ int main(int argc, char *argv[]) qmlRegisterType<ServerBufferItem>(); QmlCompositor compositor; - compositor.setTitle(QLatin1String("QML Compositor")); - compositor.setGeometry(0, 0, 1024, 768); - compositor.show(); - - compositor.rootContext()->setContextProperty("compositor", &compositor); - - QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant))); - QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant))); - QObject::connect(&compositor, SIGNAL(serverBufferItemCreated(QVariant)), compositor.rootObject(), SLOT(serverBufferItemCreated(QVariant))); - app.exec(); - qDebug() << "ending" << glGetError(); + return app.exec(); } #include "main.moc" diff --git a/examples/wayland/server-buffer/compositor/qml/main.qml b/examples/wayland/server-buffer/compositor/qml/main.qml index 536065a6a..55c0ffc13 100644 --- a/examples/wayland/server-buffer/compositor/qml/main.qml +++ b/examples/wayland/server-buffer/compositor/qml/main.qml @@ -39,7 +39,7 @@ ****************************************************************************/ import QtQuick 2.0 -import QtCompositor 1.0 +import QtWayland.Compositor 1.0 Item { id: root diff --git a/examples/wayland/server-buffer/compositor/serverbufferitem.cpp b/examples/wayland/server-buffer/compositor/serverbufferitem.cpp index 96ceed0a1..4cf5f71ff 100644 --- a/examples/wayland/server-buffer/compositor/serverbufferitem.cpp +++ b/examples/wayland/server-buffer/compositor/serverbufferitem.cpp @@ -45,7 +45,7 @@ #include <QtQuick/QSGSimpleTextureNode> #include <QtQuick/QQuickWindow> -#include <QtCompositor/private/qwlserverbufferintegration_p.h> +#include <QtWaylandCompositor/private/qwlserverbufferintegration_p.h> QT_BEGIN_NAMESPACE diff --git a/examples/wayland/wayland.pro b/examples/wayland/wayland.pro index d633fb924..503190c8a 100644 --- a/examples/wayland/wayland.pro +++ b/examples/wayland/wayland.pro @@ -1,13 +1,13 @@ TEMPLATE=subdirs -#Only build compositor examples if we are building -#the QtCompositor API -contains(CONFIG, wayland-compositor) { - SUBDIRS += qwindow-compositor +SUBDIRS += qwindow-compositor +SUBDIRS += minimal-cpp - qtHaveModule(quick) { - SUBDIRS += qml-compositor - } - - SUBDIRS += server-buffer +qtHaveModule(quick) { + SUBDIRS += minimal-qml + SUBDIRS += pure-qml + SUBDIRS += multi-output + SUBDIRS += custom-extension } + +SUBDIRS += server-buffer |