diff options
author | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2015-12-02 14:00:44 +0100 |
---|---|---|
committer | Paul Olav Tvete <paul.tvete@theqtcompany.com> | 2015-12-02 14:01:08 +0100 |
commit | 05bf419b206f3cd078364cf67af2df4e4d1477c0 (patch) | |
tree | c942e884e8f75a29bd9f281c993fbc85a0b832ed /examples | |
parent | dd5e1ffd3e9e379574325193c8546d453c11303e (diff) | |
parent | 3698b116a1973146b76319673cdb6787f13f2de6 (diff) | |
download | qtwayland-05bf419b206f3cd078364cf67af2df4e4d1477c0.tar.gz |
Merge branch 'wip-compositor-api' into dev
This introduces the new compositor API, removing the
old API (which was never officially supported).
Change-Id: I1dc01f0fb4edc749e34ed8356e56ad87d7d64913
Diffstat (limited to 'examples')
57 files changed, 2339 insertions, 1634 deletions
diff --git a/examples/wayland/custom-extension/client/.gitignore b/examples/wayland/custom-extension/client/.gitignore new file mode 100644 index 00000000..b4961e18 --- /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 00000000..7aab544e --- /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 00000000..03056f22 --- /dev/null +++ b/examples/wayland/custom-extension/client/client.pro @@ -0,0 +1,18 @@ +PLUGIN_TYPE = platforms +load(qt_plugin) + +CONFIG += wayland-scanner + +TARGET = custom-wayland + +QT += waylandclient-private + +WAYLANDCLIENTSOURCES += ../protocol/custom.xml + +OTHER_FILES += client.json + +SOURCES += main.cpp \ + customextension.cpp + +HEADERS += customextension.h + diff --git a/examples/wayland/custom-extension/client/customextension.cpp b/examples/wayland/custom-extension/client/customextension.cpp new file mode 100644 index 00000000..81694fda --- /dev/null +++ b/examples/wayland/custom-extension/client/customextension.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 + +namespace QtWaylandClient { + +CustomExtension::CustomExtension(QWaylandIntegration *wayland_integration) + : m_display(0) +{ + // TODO: add a simpler API for this + + QtWaylandClient::QWaylandDisplay *wayland_display = wayland_integration->display(); + struct ::wl_registry *registry = wl_display_get_registry(wayland_display->wl_display()); + QtWayland::wl_registry::init(registry); +} + +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); +} + +void CustomExtension::registry_global(uint32_t id, const QString &interface, uint32_t version) +{ + if (interface == QStringLiteral("qt_example_extension")) { + QtWayland::qt_example_extension::init(QtWayland::wl_registry::object(), id, version); + } +} + +} + +QT_END_NAMESPACE diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.h b/examples/wayland/custom-extension/client/customextension.h index cb70369c..d8797a9e 100644 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.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,80 +38,46 @@ ** ****************************************************************************/ -#ifndef QWINDOWCOMPOSITOR_H -#define QWINDOWCOMPOSITOR_H +#ifndef CUSTOMEXTENSION_H +#define CUSTOMEXTENSION_H -#include "qwaylandcompositor.h" -#include "qwaylandsurface.h" -#include "textureblitter.h" -#include "compositorwindow.h" - -#include <QtGui/private/qopengltexturecache_p.h> -#include <QObject> -#include <QTimer> +#include <qpa/qwindowsysteminterface.h> +#include <QtWaylandClient/private/qwayland-wayland.h> +#include "qwayland-custom.h" QT_BEGIN_NAMESPACE -class QWaylandSurfaceView; -class QOpenGLTexture; +namespace QtWaylandClient { + +class QWaylandDisplay; +class QWaylandIntegration; -class QWindowCompositor : public QObject, public QWaylandCompositor +class CustomExtension : public QObject, QtWayland::qt_example_extension, public QtWayland::wl_registry { Q_OBJECT public: - QWindowCompositor(CompositorWindow *window); - ~QWindowCompositor(); - -private slots: - void surfaceDestroyed(); - void surfaceMapped(); - void surfaceUnmapped(); - void surfaceCommitted(); - void surfacePosChanged(); - - void render(); -protected: - void surfaceCommitted(QWaylandSurface *surface); - void surfaceCreated(QWaylandSurface *surface); - - QWaylandSurfaceView* viewAt(const QPointF &point, QPointF *local = 0); + CustomExtension(QWaylandIntegration *wayland_integration); - bool eventFilter(QObject *obj, QEvent *event); - QPointF toView(QWaylandSurfaceView *view, const QPointF &pos) const; +public slots: + void sendRequest(const QString &text, int value); - void setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY); - - void ensureKeyboardFocusSurface(QWaylandSurface *oldSurface); - QImage makeBackgroundImage(const QString &fileName); - -private slots: - void sendExpose(); - void updateCursor(bool hasBuffer); +signals: + void eventReceived(const QString &text, uint value); private: - void drawSubSurface(const QPoint &offset, QWaylandSurface *surface); + QWaylandDisplay *m_display; - CompositorWindow *m_window; - QImage m_backgroundImage; - QOpenGLTexture *m_backgroundTexture; - QList<QWaylandSurface *> m_surfaces; - TextureBlitter *m_textureBlitter; - GLuint m_surface_fbo; - QTimer m_renderScheduler; + void example_extension_qtevent(struct wl_surface *surface, + uint32_t time, + const QString &text, + uint32_t value) Q_DECL_OVERRIDE; - //Dragging windows around - QWaylandSurfaceView *m_draggingWindow; - bool m_dragKeyIsPressed; - QPointF m_drag_diff; + void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE; - //Cursor - QWaylandSurface *m_cursorSurface; - int m_cursorHotspotX; - int m_cursorHotspotY; - - Qt::KeyboardModifiers m_modifiers; }; +} + QT_END_NAMESPACE -#endif // QWINDOWCOMPOSITOR_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 00000000..90705388 --- /dev/null +++ b/examples/wayland/custom-extension/client/main.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 + +namespace QtWaylandClient { + +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 ************"; + + QWaylandIntegration *integration = new QWaylandIntegration(); + + extension_global = new CustomExtension(integration); + + // 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 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 00000000..2532eb22 --- /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 00000000..4ffafdb8 --- /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 00000000..db3a8075 --- /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 00000000..bc2b676e --- /dev/null +++ b/examples/wayland/custom-extension/compositor/customextension.cpp @@ -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 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(QWaylandCompositor *compositor) +{ + 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 00000000..e9ace6e9 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/customextension.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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/QWaylandExtensionTemplate> +#include <QtWaylandCompositor/QWaylandCompositor> +#include "qwayland-server-custom.h" + +namespace QtWayland { + +class CustomExtension : public QWaylandExtensionTemplate<CustomExtension>, public QtWaylandServer::qt_example_extension +{ + Q_OBJECT +public: + CustomExtension(); + Q_INVOKABLE void initialize(QWaylandCompositor *compositor); + 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; +}; + +} + +#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 00000000..2429df11 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/images/background.png diff --git a/examples/wayland/custom-extension/compositor/main.cpp b/examples/wayland/custom-extension/compositor/main.cpp new file mode 100644 index 00000000..1970e5a6 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/main.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 <QtCore/QUrl> +#include <QtCore/QDebug> +#include <QtGui/QGuiApplication> +#include <QtQml/QQmlApplicationEngine> + +#include <QtQml/qqml.h> +#include <QtQml/QQmlEngine> +#include "customextension.h" + +static void registerTypes() +{ + qmlRegisterType<QtWayland::CustomExtension>("com.theqtcompany.customextension", 1, 0, "CustomExtension"); +} + +int main(int argc, char *argv[]) +{ + 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 00000000..3173c7a0 --- /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 00000000..88871de8 --- /dev/null +++ b/examples/wayland/custom-extension/compositor/qml/main.qml @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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: [ + Shell { + id: defaultShell + + onCreateShellSurface: { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "surface": surface } ); + item.shellSurface.initialize(defaultShell, surface, client, id); + lastItem = item; + } + + Component.onCompleted: { + initialize(); + } + }, + CustomExtension { + id: custom + onRequestReceived: { + console.log("Compositor received a request: \"" + text + "\", " + value) + } + + Component.onCompleted: { + initialize(comp); + } + } + + ] + +} diff --git a/examples/wayland/custom-extension/custom-extension.pro b/examples/wayland/custom-extension/custom-extension.pro new file mode 100644 index 00000000..c44464a3 --- /dev/null +++ b/examples/wayland/custom-extension/custom-extension.pro @@ -0,0 +1,7 @@ +TEMPLATE=subdirs + +SUBDIRS += client +SUBDIRS += compositor +SUBDIRS += testapp + +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 00000000..bda67829 --- /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/testapp/main.cpp b/examples/wayland/custom-extension/testapp/main.cpp new file mode 100644 index 00000000..59738128 --- /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 00000000..062210e9 --- /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/multi-output/doc/src/multi-output.qdoc b/examples/wayland/multi-output/doc/src/multi-output.qdoc new file mode 100644 index 00000000..32b9aa69 --- /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 445567fb..445567fb 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 5a29032d..7ee6779d 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 00000000..468dc2e0 --- /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 00000000..86df8817 --- /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 00000000..6b1d574c --- /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 00000000..83f883da --- /dev/null +++ b/examples/wayland/multi-output/qml/ShellChrome.qml @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 + + shellSurface: ShellSurface { + } + + 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 00000000..77fbeb82 --- /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/multi-output/qml/main.qml b/examples/wayland/multi-output/qml/main.qml new file mode 100644 index 00000000..9fd29fc2 --- /dev/null +++ b/examples/wayland/multi-output/qml/main.qml @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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 + + defaultOutput: shellScreen + ShellScreen { + id: shellScreen + compositor: comp + } + + GridScreen { + id: gridScreen + compositor: comp + } + + Component { + id: chromeComponent + ShellChrome { + } + } + + 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; + } + } + } + } + } + } + + extensions: [ + Shell { + id: defaultShell + + onCreateShellSurface: { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "surface": surface } ); + item.shellSurface.initialize(defaultShell, surface, client, id); + surface.activated.connect(item.raise); + } + + Component.onCompleted: { + initialize(); + } + } + ] + + 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 00000000..18ca73ec --- /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 00000000..445567fb --- /dev/null +++ b/examples/wayland/pure-qml/images/background.jpg diff --git a/examples/wayland/qwindow-compositor/textureblitter.h b/examples/wayland/pure-qml/main.cpp index 85e2bbfb..7ee6779d 100644 --- a/examples/wayland/qwindow-compositor/textureblitter.h +++ b/examples/wayland/pure-qml/main.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** ** 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 Qt Compositor. +** 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: @@ -38,38 +38,18 @@ ** ****************************************************************************/ -#ifndef TEXTUREBLITTER_H -#define TEXTUREBLITTER_H +#include <QtCore/QUrl> +#include <QtCore/QDebug> -#include <QtGui/QMatrix4x4> +#include <QtGui/QGuiApplication> -QT_BEGIN_NAMESPACE +#include <QtQml/QQmlApplicationEngine> -class QOpenGLShaderProgram; -class TextureBlitter +int main(int argc, char *argv[]) { -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); + QGuiApplication app(argc, argv); -private: - QOpenGLShaderProgram *m_shaderProgram; - QOpenGLShaderProgram *m_shaderProgramExternal; - QOpenGLShaderProgram *m_currentProgram; - QMatrix4x4 m_transformMatrix; + QQmlApplicationEngine appEngine(QUrl("qrc:///qml/main.qml")); - int m_matrixLocation; - int m_vertexCoordEntry; - int m_textureCoordEntry; - - quint32 m_currentTarget; -}; - -QT_END_NAMESPACE - -#endif // TEXTUREBLITTER_H + 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 00000000..d643d3ee --- /dev/null +++ b/examples/wayland/pure-qml/pure-qml.pro @@ -0,0 +1,17 @@ +QT += gui qml + +SOURCES += \ + main.cpp + +OTHER_FILES = \ + qml/main.qml \ + qml/Screen.qml \ + qml/Chrome.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 00000000..65ccf947 --- /dev/null +++ b/examples/wayland/pure-qml/pure-qml.qrc @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>images/background.jpg</file> + <file>qml/main.qml</file> + <file>qml/Screen.qml</file> + <file>qml/Chrome.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 00000000..83f883da --- /dev/null +++ b/examples/wayland/pure-qml/qml/Chrome.qml @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 + + shellSurface: ShellSurface { + } + + 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/pure-qml/qml/Screen.qml b/examples/wayland/pure-qml/qml/Screen.qml new file mode 100644 index 00000000..669d39c0 --- /dev/null +++ b/examples/wayland/pure-qml/qml/Screen.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 { + 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 + } + 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/pure-qml/qml/main.qml index 562d637e..0a72f7dd 100644 --- a/examples/wayland/qml-compositor/ContrastEffect.qml +++ b/examples/wayland/pure-qml/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,48 @@ ****************************************************************************/ 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); - } + property var primarySurfacesArea: null + + Screen { + 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 + Chrome { + } } - " - 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 { + } } - " - vertexShader: source && source.isYInverted ? vShaderInvertedY : vShader + extensions: [ + Shell { + id: defaultShell + + + onCreateShellSurface: { + var item = chromeComponent.createObject(defaultOutput.surfaceArea, { "surface": surface } ); + item.shellSurface.initialize(defaultShell, surface, client, id); + } + + Component.onCompleted: { + initialize(); + } + } + ] + + onCreateSurface: { + var surface = surfaceComponent.createObject(comp, { } ); + surface.initialize(comp, client, id, version); - 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); } - " } diff --git a/examples/wayland/qml-compositor/WindowContainer.qml b/examples/wayland/qml-compositor/WindowContainer.qml deleted file mode 100644 index 017e2699..00000000 --- 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 5b5616e9..00000000 --- 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 8baa2dd0..00000000 --- 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 6e634563..00000000 --- a/examples/wayland/qml-compositor/main.cpp +++ /dev/null @@ -1,160 +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() { - 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 5c1a2a67..00000000 --- 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 f908a2f2..00000000 --- a/examples/wayland/qml-compositor/qml-compositor.pro +++ /dev/null @@ -1,22 +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 - -OTHER_FILES = ContrastEffect.qml main.qml WindowChrome.qml WindowContainer.qml background.jpg closebutton.png compositor.js - -target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor -sources.files = $$OTHER_FILES $$SOURCES $$HEADERS $$RESOURCES $$FORMS qml-compositor.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor -INSTALLS += target sources diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp index 7d855016..a902a7d0 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.cpp +++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp @@ -39,23 +39,215 @@ ****************************************************************************/ #include "compositorwindow.h" -#include <QTouchEvent> -CompositorWindow::CompositorWindow(const QSurfaceFormat &format, const QRect &geometry) - : m_format(format) +#include <QMouseEvent> +#include <QOpenGLWindow> +#include <QOpenGLTexture> +#include <QOpenGLFunctions> +#include <QMatrix4x4> + +#include "windowcompositor.h" +#include <QtWaylandCompositor/qwaylandinput.h> + +CompositorWindow::CompositorWindow() + : m_backgroundTexture(0) + , m_compositor(0) + , m_grabState(NoGrab) + , m_dragIconView(0) +{ +} + +void CompositorWindow::setCompositor(WindowCompositor *comp) { + m_compositor = comp; + connect(m_compositor, &WindowCompositor::startMove, this, &CompositorWindow::startMove); + connect(m_compositor, &WindowCompositor::startResize, this, &CompositorWindow::startResize); + connect(m_compositor, &WindowCompositor::dragStarted, this, &CompositorWindow::startDrag); + connect(m_compositor, &WindowCompositor::frameOffset, this, &CompositorWindow::setFrameOffset); +} + +void CompositorWindow::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 CompositorWindow::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); + } + } +} + +void CompositorWindow::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); + + Q_FOREACH (WindowCompositorView *view, m_compositor->views()) { + if (view->isCursor()) + continue; + GLuint textureId = view->getTexture(); + QWaylandSurface *surface = view->surface(); + if (surface && surface->isMapped()) { + QSize s = surface->size(); + if (!s.isEmpty()) { + QRectF surfaceGeometry(view->position(), 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(); +} + +WindowCompositorView *CompositorWindow::viewAt(const QPointF &point) +{ + WindowCompositorView *ret = 0; + Q_FOREACH (WindowCompositorView *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 CompositorWindow::startMove() +{ + m_grabState = MoveGrab; +} + +void CompositorWindow::startResize(int edge) +{ + m_initialSize = m_mouseView->surface()->size(); + m_grabState = ResizeGrab; + m_resizeEdge = edge; +} + +void CompositorWindow::startDrag(WindowCompositorView *dragIcon) +{ + m_grabState = DragGrab; + m_dragIconView = dragIcon; + m_compositor->raise(dragIcon); +} + +void CompositorWindow::setFrameOffset(const QPoint &offset) +{ + if (m_mouseView) + m_mouseView->setPosition(m_mouseView->position() + offset); +} + +void CompositorWindow::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 CompositorWindow::mouseReleaseEvent(QMouseEvent *e) +{ + if (!mouseGrab()) + sendMouseEvent(e, m_mouseView); + if (e->buttons() == Qt::NoButton) { + if (m_grabState == DragGrab) { + WindowCompositorView *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + } + m_mouseView = 0; + m_grabState = NoGrab; + } +} + +void CompositorWindow::mouseMoveEvent(QMouseEvent *e) +{ + switch (m_grabState) { + case NoGrab: { + WindowCompositorView *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: { + WindowCompositorView *view = viewAt(e->localPos()); + m_compositor->handleDrag(view, e); + if (m_dragIconView) { + m_dragIconView->setPosition(e->localPos()); + update(); + } + } + break; + } +} + +void CompositorWindow::sendMouseEvent(QMouseEvent *e, WindowCompositorView *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 CompositorWindow::keyPressEvent(QKeyEvent *e) { - setSurfaceType(QWindow::OpenGLSurface); - setGeometry(geometry); - setFormat(format); - create(); - m_context = new QOpenGLContext; - m_context->setFormat(format); - m_context->create(); + m_compositor->defaultInputDevice()->sendKeyPressEvent(e->nativeScanCode()); } -void CompositorWindow::touchEvent(QTouchEvent *event) +void CompositorWindow::keyReleaseEvent(QKeyEvent *e) { - // Do not want any automatically synthesized mouse events - // so make sure the touch is always accepted. - event->accept(); + m_compositor->defaultInputDevice()->sendKeyReleaseEvent(e->nativeScanCode()); } diff --git a/examples/wayland/qwindow-compositor/compositorwindow.h b/examples/wayland/qwindow-compositor/compositorwindow.h index 24c50c53..720db5bc 100644 --- a/examples/wayland/qwindow-compositor/compositorwindow.h +++ b/examples/wayland/qwindow-compositor/compositorwindow.h @@ -41,24 +41,61 @@ #ifndef COMPOSITORWINDOW_H #define COMPOSITORWINDOW_H -#include <QWindow> -#include <QOpenGLContext> -#include <QSurfaceFormat> +#include <QOpenGLWindow> +#include <QPointer> +#include <QtGui/private/qopengltextureblitter_p.h> -class CompositorWindow : public QWindow +QT_BEGIN_NAMESPACE + +class WindowCompositor; +class WindowCompositorView; +class QOpenGLTexture; + +class CompositorWindow : 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); } + CompositorWindow(); + + void setCompositor(WindowCompositor *comp); protected: - void touchEvent(QTouchEvent *event); + void initializeGL() Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void keyReleaseEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + +private slots: + void startMove(); + void startResize(int edge); + void startDrag(WindowCompositorView *dragIcon); + void setFrameOffset(const QPoint &offset); private: - QOpenGLContext *m_context; - QSurfaceFormat m_format; + enum GrabState { NoGrab, MoveGrab, ResizeGrab, DragGrab }; + + WindowCompositorView *viewAt(const QPointF &point); + bool mouseGrab() const { return m_grabState != NoGrab ;} + void drawBackground(); + void sendMouseEvent(QMouseEvent *e, WindowCompositorView *target); + + QOpenGLTextureBlitter m_textureBlitter; + QSize m_backgroundImageSize; + QOpenGLTexture *m_backgroundTexture; + WindowCompositor *m_compositor; + QPointer<WindowCompositorView> m_mouseView; + GrabState m_grabState; + QSize m_initialSize; + int m_resizeEdge; + QPointF m_mouseOffset; + QPointF m_initialMousePos; + WindowCompositorView *m_dragIconView; }; +QT_END_NAMESPACE + #endif // COMPOSITORWINDOW_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 00000000..d268aca4 --- /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 b4be143b..c4fa4325 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 "compositorwindow.h" +#include "windowcompositor.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); + CompositorWindow window; + WindowCompositor 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 4bab000b..994276d9 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 + windowcompositor.h SOURCES += main.cpp \ compositorwindow.cpp \ - qwindowcompositor.cpp \ - textureblitter.cpp + windowcompositor.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 20dd10a5..688dd900 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 58df7ead..00000000 --- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp +++ /dev/null @@ -1,485 +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) - , 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()); - } - } - - 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(); -} - -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 df4fa18d..00000000 --- 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/windowcompositor.cpp b/examples/wayland/qwindow-compositor/windowcompositor.cpp new file mode 100644 index 00000000..24a0e0f5 --- /dev/null +++ b/examples/wayland/qwindow-compositor/windowcompositor.cpp @@ -0,0 +1,300 @@ +/**************************************************************************** +** +** 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 "windowcompositor.h" + +#include <QMouseEvent> +#include <QKeyEvent> +#include <QTouchEvent> + +#include <QtWaylandCompositor/QWaylandShellSurface> +#include <QtWaylandCompositor/qwaylandinput.h> +#include <QtWaylandCompositor/qwaylanddrag.h> + +#include <QDebug> + +GLuint WindowCompositorView::getTexture() { + if (advance()) { + if (m_texture) + glDeleteTextures(1, &m_texture); + + glGenTextures(1, &m_texture); + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + currentBuffer().bindToTexture(); + } + return m_texture; +} + +bool WindowCompositorView::isCursor() const +{ + return surface()->isCursorSurface(); +} + +WindowCompositor::WindowCompositor(QWindow *window) + : QWaylandCompositor() + , m_window(window) + , m_shell(new QWaylandShell(this)) +{ + connect(m_shell, &QWaylandShell::createShellSurface, this, &WindowCompositor::onCreateShellSurface); +} + +WindowCompositor::~WindowCompositor() +{ +} + +void WindowCompositor::create() +{ + new QWaylandOutput(this, m_window); + QWaylandCompositor::create(); + + connect(this, &QWaylandCompositor::surfaceCreated, this, &WindowCompositor::onSurfaceCreated); + connect(defaultInputDevice(), &QWaylandInputDevice::cursorSurfaceRequest, this, &WindowCompositor::adjustCursorSurface); + connect(defaultInputDevice()->drag(), &QWaylandDrag::dragStarted, this, &WindowCompositor::startDrag); +} + +void WindowCompositor::onSurfaceCreated(QWaylandSurface *surface) +{ + connect(surface, &QWaylandSurface::surfaceDestroyed, this, &WindowCompositor::surfaceDestroyed); + connect(surface, &QWaylandSurface::mappedChanged, this, &WindowCompositor::surfaceMappedChanged); + connect(surface, &QWaylandSurface::redraw, this, &WindowCompositor::triggerRender); + connect(surface, &QWaylandSurface::offsetForNextFrame, this, &WindowCompositor::frameOffset); + WindowCompositorView *view = new WindowCompositorView; + view->setSurface(surface); + view->setOutput(outputFor(m_window)); + m_views << view; + connect(view, &QWaylandView::surfaceDestroyed, this, &WindowCompositor::viewSurfaceDestroyed); +} + +void WindowCompositor::surfaceMappedChanged() +{ + QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender()); + if (surface->isMapped()) { + if (!surface->isCursorSurface()) + 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 WindowCompositor::surfaceDestroyed() +{ + triggerRender(); +} + +void WindowCompositor::viewSurfaceDestroyed() +{ + WindowCompositorView *view = qobject_cast<WindowCompositorView*>(sender()); + m_views.removeAll(view); + delete view; +} + +void WindowCompositor::surfaceCommittedSlot() +{ + triggerRender(); +} + +WindowCompositorView * WindowCompositor::findView(const QWaylandSurface *s) const +{ + Q_FOREACH (WindowCompositorView* view, m_views) { + if (view->surface() == s) + return view; + } + return Q_NULLPTR; +} + +void WindowCompositor::onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id) +{ + QWaylandSurface *surface = s; + + QWaylandShellSurface *shellSurface = new QWaylandShellSurface(m_shell, surface, client, id); + connect(shellSurface, &QWaylandShellSurface::startMove, this, &WindowCompositor::onStartMove); + connect(shellSurface, &QWaylandShellSurface::startResize, this, &WindowCompositor::onStartResize); + connect(shellSurface, &QWaylandShellSurface::setTransient, this, &WindowCompositor::onSetTransient); + connect(shellSurface, &QWaylandShellSurface::setPopup, this, &WindowCompositor::onSetPopup); + WindowCompositorView *view = findView(s); + Q_ASSERT(view); + view->m_shellSurface = shellSurface; +} + +void WindowCompositor::onStartMove() +{ + closePopups(); + emit startMove(); +} + +void WindowCompositor::onStartResize(QWaylandInputDevice *, QWaylandShellSurface::ResizeEdge edges) +{ + closePopups(); + emit startResize(int(edges)); +} + +void WindowCompositor::onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, QWaylandShellSurface::FocusPolicy focusPolicy) +{ + qDebug() << "Transient window support not implemented" << parentSurface << relativeToParent << focusPolicy; +} + +void WindowCompositor::onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent) +{ + Q_UNUSED(inputDevice); + QWaylandShellSurface *surface = qobject_cast<QWaylandShellSurface*>(sender()); + WindowCompositorView *view = findView(surface->surface()); + m_popupViews << view; + if (view) { + raise(view); + WindowCompositorView *parentView = findView(parent); + if (parentView) + view->setPosition(parentView->position() + relativeToParent); + } +} + +void WindowCompositor::triggerRender() +{ + m_window->requestUpdate(); +} + +void WindowCompositor::startRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->frameStarted(); +} + +void WindowCompositor::endRender() +{ + QWaylandOutput *out = defaultOutput(); + if (out) + out->sendFrameCallbacks(); +} + +void WindowCompositor::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 WindowCompositor::adjustCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY) +{ + if ((m_cursorView.surface() != surface)) { + if (m_cursorView.surface()) + disconnect(m_cursorView.surface(), &QWaylandSurface::redraw, this, &WindowCompositor::updateCursor); + if (surface) + connect(surface, &QWaylandSurface::redraw, this, &WindowCompositor::updateCursor); + } + + m_cursorView.setSurface(surface); + m_cursorHotspotX = hotspotX; + m_cursorHotspotY = hotspotY; +} + +void WindowCompositor::closePopups() +{ + Q_FOREACH (WindowCompositorView *view, m_popupViews) + view->m_shellSurface->sendPopupDone(); + m_popupViews.clear(); +} + +void WindowCompositor::handleMouseEvent(QWaylandView *target, QMouseEvent *me) +{ + if (target && popupActive() && me->type() == QEvent::MouseButtonPress + && target->surface()->client() != m_popupViews.first()->surface()->client()) { + closePopups(); + } + QWaylandInputDevice *input = defaultInputDevice(); + switch (me->type()) { + case QEvent::MouseButtonPress: + input->sendMousePressEvent(me->button()); + break; + case QEvent::MouseButtonRelease: + input->sendMouseReleaseEvent(me->button()); + break; + case QEvent::MouseMove: + input->sendMouseMoveEvent(target, me->localPos(), me->globalPos()); + default: + break; + } +} + +void WindowCompositor::handleResize(WindowCompositorView *target, const QSize &initialSize, const QPoint &delta, int edge) +{ + QWaylandShellSurface *shellSurface = target->m_shellSurface; + if (!shellSurface) + return; + QWaylandShellSurface::ResizeEdge edges = QWaylandShellSurface::ResizeEdge(edge); + QSize newSize = shellSurface->sizeForResize(initialSize, delta, edges); + shellSurface->sendConfigure(newSize, edges); +} + +void WindowCompositor::startDrag() +{ + QWaylandDrag *currentDrag = defaultInputDevice()->drag(); + Q_ASSERT(currentDrag); + WindowCompositorView *iconView = findView(currentDrag->icon()); + + emit dragStarted(iconView); +} + +void WindowCompositor::handleDrag(WindowCompositorView *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) + currentDrag->drop(); +} + +void WindowCompositor::raise(WindowCompositorView *view) +{ + m_views.removeOne(view); + m_views.append(view); +} diff --git a/examples/wayland/qwindow-compositor/windowcompositor.h b/examples/wayland/qwindow-compositor/windowcompositor.h new file mode 100644 index 00000000..6f878d3a --- /dev/null +++ b/examples/wayland/qwindow-compositor/windowcompositor.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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/QWaylandShellSurface> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QWaylandShell; +class QWaylandShellSurface; + +class WindowCompositorView : public QWaylandView +{ + Q_OBJECT +public: + WindowCompositorView() : m_texture(0), m_shellSurface(0) {} + GLuint getTexture(); + QPointF position() const { return m_position; } + void setPosition(const QPointF &pos) { m_position = pos; } + bool isCursor() const; + bool hasShell() const { return m_shellSurface; } +private: + friend class WindowCompositor; + GLuint m_texture; + QPointF m_position; + QWaylandShellSurface *m_shellSurface; +}; + +class WindowCompositor : public QWaylandCompositor +{ + Q_OBJECT +public: + WindowCompositor(QWindow *window); + ~WindowCompositor(); + void create() Q_DECL_OVERRIDE; + + void startRender(); + void endRender(); + + QList<WindowCompositorView*> views() const { return m_views; } + void raise(WindowCompositorView *view); + + void handleMouseEvent(QWaylandView *target, QMouseEvent *me); + void handleResize(WindowCompositorView *target, const QSize &initialSize, const QPoint &delta, int edge); + void handleDrag(WindowCompositorView *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); + void dragStarted(WindowCompositorView *dragIcon); + void frameOffset(const QPoint &offset); + +private slots: + void surfaceMappedChanged(); + void surfaceDestroyed(); + void surfaceCommittedSlot(); + void viewSurfaceDestroyed(); + void onStartMove(); + void onStartResize(QWaylandInputDevice *inputDevice, QWaylandShellSurface::ResizeEdge edges); + + void startDrag(); + + void triggerRender(); + + void onSurfaceCreated(QWaylandSurface *surface); + void onCreateShellSurface(QWaylandSurface *s, QWaylandClient *client, uint id); + void onSetTransient(QWaylandSurface *parentSurface, const QPoint &relativeToParent, QWaylandShellSurface::FocusPolicy focusPolicy); + void onSetPopup(QWaylandInputDevice *inputDevice, QWaylandSurface *parent, const QPoint &relativeToParent); + + void updateCursor(); +private: + WindowCompositorView *findView(const QWaylandSurface *s) const; + QWindow *m_window; + QList<WindowCompositorView*> m_views; + QList<WindowCompositorView*> m_popupViews; + QWaylandShell *m_shell; + QWaylandView m_cursorView; + int m_cursorHotspotX; + int m_cursorHotspotY; +}; + + +QT_END_NAMESPACE + +#endif // WINDOWCOMPOSITOR_H diff --git a/examples/wayland/server-buffer/client/client.pro b/examples/wayland/server-buffer/client/client.pro index 9d408d9e..6c2c9285 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 8d7f4882..f391d3a1 100644 --- a/examples/wayland/server-buffer/compositor/compositor.pro +++ b/examples/wayland/server-buffer/compositor/compositor.pro @@ -1,20 +1,23 @@ -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 \ + serverbufferitem.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 diff --git a/examples/wayland/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp index 312cff2c..57ca647b 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/serverbufferitem.cpp b/examples/wayland/server-buffer/compositor/serverbufferitem.cpp index 96ceed0a..4cf5f71f 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 be50cc78..91c68b89 100644 --- a/examples/wayland/wayland.pro +++ b/examples/wayland/wayland.pro @@ -1,15 +1,11 @@ TEMPLATE=subdirs -#Only build compositor examples if we are building -#the QtCompositor API -contains(CONFIG, wayland-compositor) { - SUBDIRS += qwindow-compositor +SUBDIRS += qwindow-compositor - qtHaveModule(quick) { - SUBDIRS += qml-compositor - } - - SUBDIRS += server-buffer +qtHaveModule(quick) { + SUBDIRS += pure-qml + SUBDIRS += multi-output + SUBDIRS += custom-extension } -SUBDIRS += subsurface +SUBDIRS += server-buffer |