diff options
117 files changed, 1253 insertions, 538 deletions
diff --git a/.gitignore b/.gitignore index c0b505301..b33ca9077 100644 --- a/.gitignore +++ b/.gitignore @@ -27,19 +27,19 @@ lib/ include/ bin/ /plugins/ -examples/qml-compositor/qml-compositor -examples/qwidget-compositor/qwidget-compositor -examples/qwindow-compositor/qwindow-compositor -examples/server-buffer/client/client -examples/server-buffer/client/qwayland-*.cpp -examples/server-buffer/client/qwayland-*.h -examples/server-buffer/client/*-client-protocol.h -examples/server-buffer/client/*-protocol.c -examples/server-buffer/compositor/compositor -examples/server-buffer/compositor/qwayland-server-*.cpp -examples/server-buffer/compositor/qwayland-server-*.h -examples/server-buffer/compositor/*-server-protocol.h -examples/server-buffer/compositor/*-protocol.c +examples/wayland/qml-compositor/qml-compositor +examples/wayland/qwidget-compositor/qwidget-compositor +examples/wayland/qwindow-compositor/qwindow-compositor +examples/wayland/server-buffer/client/client +examples/wayland/server-buffer/client/qwayland-*.cpp +examples/wayland/server-buffer/client/qwayland-*.h +examples/wayland/server-buffer/client/*-client-protocol.h +examples/wayland/server-buffer/client/*-protocol.c +examples/wayland/server-buffer/compositor/compositor +examples/wayland/server-buffer/compositor/qwayland-server-*.cpp +examples/wayland/server-buffer/compositor/qwayland-server-*.h +examples/wayland/server-buffer/compositor/*-server-protocol.h +examples/wayland/server-buffer/compositor/*-protocol.c src/client/qwayland*.cpp src/client/*-protocol.c src/compositor/*-server-protocol.h diff --git a/examples/examples.pro b/examples/examples.pro index d633fb924..24350f359 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -1,13 +1,2 @@ -TEMPLATE=subdirs - -#Only build compositor examples if we are building -#the QtCompositor API -contains(CONFIG, wayland-compositor) { - SUBDIRS += qwindow-compositor - - qtHaveModule(quick) { - SUBDIRS += qml-compositor - } - - SUBDIRS += server-buffer -} +TEMPLATE = subdirs +SUBDIRS += wayland diff --git a/examples/qml-compositor/ContrastEffect.qml b/examples/wayland/qml-compositor/ContrastEffect.qml index c284b2907..c284b2907 100644 --- a/examples/qml-compositor/ContrastEffect.qml +++ b/examples/wayland/qml-compositor/ContrastEffect.qml diff --git a/examples/qml-compositor/WindowChrome.qml b/examples/wayland/qml-compositor/WindowChrome.qml index fe9f5d78d..fe9f5d78d 100644 --- a/examples/qml-compositor/WindowChrome.qml +++ b/examples/wayland/qml-compositor/WindowChrome.qml diff --git a/examples/qml-compositor/WindowContainer.qml b/examples/wayland/qml-compositor/WindowContainer.qml index 5e073298f..5e073298f 100644 --- a/examples/qml-compositor/WindowContainer.qml +++ b/examples/wayland/qml-compositor/WindowContainer.qml diff --git a/examples/qml-compositor/background.jpg b/examples/wayland/qml-compositor/background.jpg Binary files differindex 445567fbd..445567fbd 100644 --- a/examples/qml-compositor/background.jpg +++ b/examples/wayland/qml-compositor/background.jpg diff --git a/examples/qml-compositor/closebutton.png b/examples/wayland/qml-compositor/closebutton.png Binary files differindex 5b5616e98..5b5616e98 100644 --- a/examples/qml-compositor/closebutton.png +++ b/examples/wayland/qml-compositor/closebutton.png diff --git a/examples/qml-compositor/compositor.js b/examples/wayland/qml-compositor/compositor.js index f24d849c1..f24d849c1 100644 --- a/examples/qml-compositor/compositor.js +++ b/examples/wayland/qml-compositor/compositor.js diff --git a/examples/qml-compositor/main.cpp b/examples/wayland/qml-compositor/main.cpp index 26e730d43..26e730d43 100644 --- a/examples/qml-compositor/main.cpp +++ b/examples/wayland/qml-compositor/main.cpp diff --git a/examples/qml-compositor/main.qml b/examples/wayland/qml-compositor/main.qml index a6b54c312..a6b54c312 100644 --- a/examples/qml-compositor/main.qml +++ b/examples/wayland/qml-compositor/main.qml diff --git a/examples/qml-compositor/qml-compositor.pro b/examples/wayland/qml-compositor/qml-compositor.pro index e397002c3..f908a2f2f 100644 --- a/examples/qml-compositor/qml-compositor.pro +++ b/examples/wayland/qml-compositor/qml-compositor.pro @@ -16,7 +16,7 @@ SOURCES += main.cpp OTHER_FILES = ContrastEffect.qml main.qml WindowChrome.qml WindowContainer.qml background.jpg closebutton.png compositor.js -target.path = $$[QT_INSTALL_EXAMPLES]/qtwayland/qml-compositor +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor sources.files = $$OTHER_FILES $$SOURCES $$HEADERS $$RESOURCES $$FORMS qml-compositor.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/qtwayland/qml-compositor +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/qml-compositor INSTALLS += target sources diff --git a/examples/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp index 6f8f2321d..6f8f2321d 100644 --- a/examples/qwindow-compositor/compositorwindow.cpp +++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp diff --git a/examples/qwindow-compositor/compositorwindow.h b/examples/wayland/qwindow-compositor/compositorwindow.h index dc87b31a3..dc87b31a3 100644 --- a/examples/qwindow-compositor/compositorwindow.h +++ b/examples/wayland/qwindow-compositor/compositorwindow.h diff --git a/examples/qwindow-compositor/main.cpp b/examples/wayland/qwindow-compositor/main.cpp index a0288982e..a0288982e 100644 --- a/examples/qwindow-compositor/main.cpp +++ b/examples/wayland/qwindow-compositor/main.cpp diff --git a/examples/qwindow-compositor/qwindow-compositor.pro b/examples/wayland/qwindow-compositor/qwindow-compositor.pro index 7b0e24c43..4bab000b5 100644 --- a/examples/qwindow-compositor/qwindow-compositor.pro +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.pro @@ -23,7 +23,7 @@ INCLUDEPATH += $$PWD/../../include RESOURCES += qwindow-compositor.qrc -target.path = $$[QT_INSTALL_EXAMPLES]/qtwayland/qwindow-compositor +target.path = $$[QT_INSTALL_EXAMPLES]/wayland/qwindow-compositor sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS qwindow-compositor.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/qtwayland/qwindow-compositor +sources.path = $$[QT_INSTALL_EXAMPLES]/wayland/qwindow-compositor INSTALLS += target sources diff --git a/examples/qwindow-compositor/qwindow-compositor.qrc b/examples/wayland/qwindow-compositor/qwindow-compositor.qrc index 20dd10a53..20dd10a53 100644 --- a/examples/qwindow-compositor/qwindow-compositor.qrc +++ b/examples/wayland/qwindow-compositor/qwindow-compositor.qrc diff --git a/examples/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp index c933152d8..c933152d8 100644 --- a/examples/qwindow-compositor/qwindowcompositor.cpp +++ b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp diff --git a/examples/qwindow-compositor/qwindowcompositor.h b/examples/wayland/qwindow-compositor/qwindowcompositor.h index 57f3e8536..57f3e8536 100644 --- a/examples/qwindow-compositor/qwindowcompositor.h +++ b/examples/wayland/qwindow-compositor/qwindowcompositor.h diff --git a/examples/qwindow-compositor/textureblitter.cpp b/examples/wayland/qwindow-compositor/textureblitter.cpp index 813fd8966..813fd8966 100644 --- a/examples/qwindow-compositor/textureblitter.cpp +++ b/examples/wayland/qwindow-compositor/textureblitter.cpp diff --git a/examples/qwindow-compositor/textureblitter.h b/examples/wayland/qwindow-compositor/textureblitter.h index 7426c6f29..7426c6f29 100644 --- a/examples/qwindow-compositor/textureblitter.h +++ b/examples/wayland/qwindow-compositor/textureblitter.h diff --git a/examples/server-buffer/README b/examples/wayland/server-buffer/README index 762db4238..762db4238 100644 --- a/examples/server-buffer/README +++ b/examples/wayland/server-buffer/README diff --git a/examples/server-buffer/client/client.pro b/examples/wayland/server-buffer/client/client.pro index ce4a04f91..ce4a04f91 100644 --- a/examples/server-buffer/client/client.pro +++ b/examples/wayland/server-buffer/client/client.pro diff --git a/examples/server-buffer/client/main.cpp b/examples/wayland/server-buffer/client/main.cpp index 54c586ce6..54c586ce6 100644 --- a/examples/server-buffer/client/main.cpp +++ b/examples/wayland/server-buffer/client/main.cpp diff --git a/examples/server-buffer/client/serverbufferrenderer.cpp b/examples/wayland/server-buffer/client/serverbufferrenderer.cpp index 2f0d204d3..2f0d204d3 100644 --- a/examples/server-buffer/client/serverbufferrenderer.cpp +++ b/examples/wayland/server-buffer/client/serverbufferrenderer.cpp diff --git a/examples/server-buffer/client/serverbufferrenderer.h b/examples/wayland/server-buffer/client/serverbufferrenderer.h index 7e8999b1c..7e8999b1c 100644 --- a/examples/server-buffer/client/serverbufferrenderer.h +++ b/examples/wayland/server-buffer/client/serverbufferrenderer.h diff --git a/examples/server-buffer/compositor/compositor.pro b/examples/wayland/server-buffer/compositor/compositor.pro index 9f7751a09..9f7751a09 100644 --- a/examples/server-buffer/compositor/compositor.pro +++ b/examples/wayland/server-buffer/compositor/compositor.pro diff --git a/examples/server-buffer/compositor/compositor.qrc b/examples/wayland/server-buffer/compositor/compositor.qrc index dbbbfb1cf..dbbbfb1cf 100644 --- a/examples/server-buffer/compositor/compositor.qrc +++ b/examples/wayland/server-buffer/compositor/compositor.qrc diff --git a/examples/server-buffer/compositor/images/background.jpg b/examples/wayland/server-buffer/compositor/images/background.jpg Binary files differindex 445567fbd..445567fbd 100644 --- a/examples/server-buffer/compositor/images/background.jpg +++ b/examples/wayland/server-buffer/compositor/images/background.jpg diff --git a/examples/server-buffer/compositor/main.cpp b/examples/wayland/server-buffer/compositor/main.cpp index 85503c62b..9f86539fd 100644 --- a/examples/server-buffer/compositor/main.cpp +++ b/examples/wayland/server-buffer/compositor/main.cpp @@ -71,7 +71,7 @@ class QmlCompositor public: QmlCompositor() : QWaylandQuickCompositor(this, 0, DefaultExtensions | SubSurfaceExtension) - , QtWaylandServer::qt_share_buffer(QWaylandCompositor::handle()->wl_display()) + , QtWaylandServer::qt_share_buffer(QWaylandCompositor::handle()->wl_display(), 1) , m_server_buffer_32_bit(0) , m_server_buffer_item_32_bit(0) , m_server_buffer_8_bit(0) diff --git a/examples/server-buffer/compositor/qml/ServerBufferContainer.qml b/examples/wayland/server-buffer/compositor/qml/ServerBufferContainer.qml index 7c7306e36..7c7306e36 100644 --- a/examples/server-buffer/compositor/qml/ServerBufferContainer.qml +++ b/examples/wayland/server-buffer/compositor/qml/ServerBufferContainer.qml diff --git a/examples/server-buffer/compositor/qml/main.qml b/examples/wayland/server-buffer/compositor/qml/main.qml index c9d62be55..c9d62be55 100644 --- a/examples/server-buffer/compositor/qml/main.qml +++ b/examples/wayland/server-buffer/compositor/qml/main.qml diff --git a/examples/server-buffer/compositor/serverbufferitem.cpp b/examples/wayland/server-buffer/compositor/serverbufferitem.cpp index 4a47c279d..4a47c279d 100644 --- a/examples/server-buffer/compositor/serverbufferitem.cpp +++ b/examples/wayland/server-buffer/compositor/serverbufferitem.cpp diff --git a/examples/server-buffer/compositor/serverbufferitem.h b/examples/wayland/server-buffer/compositor/serverbufferitem.h index 31fad4e86..31fad4e86 100644 --- a/examples/server-buffer/compositor/serverbufferitem.h +++ b/examples/wayland/server-buffer/compositor/serverbufferitem.h diff --git a/examples/server-buffer/compositor/serverbuffertextureprovider.h b/examples/wayland/server-buffer/compositor/serverbuffertextureprovider.h index 76ff5a4ac..76ff5a4ac 100644 --- a/examples/server-buffer/compositor/serverbuffertextureprovider.h +++ b/examples/wayland/server-buffer/compositor/serverbuffertextureprovider.h diff --git a/examples/server-buffer/server-buffer.pro b/examples/wayland/server-buffer/server-buffer.pro index 16c556251..16c556251 100644 --- a/examples/server-buffer/server-buffer.pro +++ b/examples/wayland/server-buffer/server-buffer.pro diff --git a/examples/server-buffer/share-buffer.xml b/examples/wayland/server-buffer/share-buffer.xml index 57a1fd2c5..57a1fd2c5 100644 --- a/examples/server-buffer/share-buffer.xml +++ b/examples/wayland/server-buffer/share-buffer.xml diff --git a/examples/wayland/wayland.pro b/examples/wayland/wayland.pro new file mode 100644 index 000000000..d633fb924 --- /dev/null +++ b/examples/wayland/wayland.pro @@ -0,0 +1,13 @@ +TEMPLATE=subdirs + +#Only build compositor examples if we are building +#the QtCompositor API +contains(CONFIG, wayland-compositor) { + SUBDIRS += qwindow-compositor + + qtHaveModule(quick) { + SUBDIRS += qml-compositor + } + + SUBDIRS += server-buffer +} diff --git a/src/client/client.pro b/src/client/client.pro index 22271ee45..ef3cff054 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -5,7 +5,8 @@ QT_FOR_PRIVATE += platformsupport-private MODULE=waylandclient MODULE_PLUGIN_TYPES = \ wayland-graphics-integration-client \ - wayland-inputdevice-integration + wayland-inputdevice-integration \ + wayland-decoration-client load(qt_module) @@ -71,7 +72,9 @@ SOURCES += qwaylandintegration.cpp \ qwaylandtouch.cpp \ qwaylandqtkey.cpp \ ../shared/qwaylandmimehelper.cpp \ - qwaylanddecoration.cpp \ + qwaylandabstractdecoration.cpp \ + qwaylanddecorationfactory.cpp \ + qwaylanddecorationplugin.cpp \ qwaylandeventthread.cpp\ qwaylandwindowmanagerintegration.cpp \ qwaylandinputcontext.cpp \ @@ -102,7 +105,9 @@ HEADERS += qwaylandintegration_p.h \ qwaylandtouch_p.h \ qwaylandqtkey_p.h \ ../shared/qwaylandmimehelper.h \ - qwaylanddecoration_p.h \ + qwaylandabstractdecoration_p.h \ + qwaylanddecorationfactory_p.h \ + qwaylanddecorationplugin_p.h \ qwaylandeventthread_p.h \ qwaylandwindowmanagerintegration_p.h \ qwaylandinputcontext_p.h \ diff --git a/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h index 255a66854..5fa187e69 100644 --- a/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h +++ b/src/client/inputdeviceintegration/qwaylandinputdeviceintegration_p.h @@ -56,7 +56,7 @@ public: QWaylandInputDeviceIntegration() {} virtual ~QWaylandInputDeviceIntegration() {} - virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *d, uint32_t id) = 0; + virtual QWaylandInputDevice *createInputDevice(QWaylandDisplay *d, int version, uint32_t id) = 0; }; QT_END_NAMESPACE diff --git a/src/client/qwaylandabstractdecoration.cpp b/src/client/qwaylandabstractdecoration.cpp new file mode 100644 index 000000000..e4b81bb83 --- /dev/null +++ b/src/client/qwaylandabstractdecoration.cpp @@ -0,0 +1,187 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandabstractdecoration_p.h" + +#include <private/qobject_p.h> +#include "qwaylandwindow_p.h" +#include "qwaylandshellsurface_p.h" +#include "qwaylandinputdevice_p.h" +#include "qwaylandscreen_p.h" + +#include <QtGui/QImage> + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecorationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QWaylandAbstractDecoration) + +public: + QWaylandAbstractDecorationPrivate(); + ~QWaylandAbstractDecorationPrivate(); + + QWindow *m_window; + QWaylandWindow *m_wayland_window; + + bool m_isDirty; + QImage m_decorationContentImage; + + Qt::MouseButtons m_mouseButtons; +}; + +QWaylandAbstractDecorationPrivate::QWaylandAbstractDecorationPrivate() + : m_window(0) + , m_wayland_window(0) + , m_isDirty(true) + , m_decorationContentImage(0) + , m_mouseButtons(Qt::NoButton) +{ +} + +QWaylandAbstractDecorationPrivate::~QWaylandAbstractDecorationPrivate() +{ +} + +QWaylandAbstractDecoration::QWaylandAbstractDecoration() + : QObject(*new QWaylandAbstractDecorationPrivate) +{ +} + +QWaylandAbstractDecoration::~QWaylandAbstractDecoration() +{ +} + +// we do this as a setter to get around plugin factory creates not really +// being a great way to pass arguments +void QWaylandAbstractDecoration::setWaylandWindow(QWaylandWindow *window) +{ + Q_D(QWaylandAbstractDecoration); + + // double initialization is probably not great + Q_ASSERT(!d->m_window && !d->m_wayland_window); + + d->m_window = window->window(); + d->m_wayland_window = window; +} + +const QImage &QWaylandAbstractDecoration::contentImage() +{ + Q_D(QWaylandAbstractDecoration); + if (d->m_isDirty) { + //Update the decoration backingstore + + d->m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); + d->m_decorationContentImage.fill(Qt::transparent); + this->paint(&d->m_decorationContentImage); + + d->m_isDirty = false; + } + + return d->m_decorationContentImage; +} + +void QWaylandAbstractDecoration::update() +{ + Q_D(QWaylandAbstractDecoration); + d->m_isDirty = true; +} + +void QWaylandAbstractDecoration::setMouseButtons(Qt::MouseButtons mb) +{ + Q_D(QWaylandAbstractDecoration); + d->m_mouseButtons = mb; +} + +void QWaylandAbstractDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) +{ + Q_D(QWaylandAbstractDecoration); + if (isLeftClicked(buttons)) { + d->m_wayland_window->shellSurface()->resize(inputDevice, resize); + inputDevice->removeMouseButtonFromState(Qt::LeftButton); + } +} + +void QWaylandAbstractDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) +{ + Q_D(QWaylandAbstractDecoration); + if (isLeftClicked(buttons)) { + d->m_wayland_window->shellSurface()->move(inputDevice); + inputDevice->removeMouseButtonFromState(Qt::LeftButton); + } +} + +bool QWaylandAbstractDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) +{ + Q_D(QWaylandAbstractDecoration); + if ((!d->m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) + return true; + return false; +} + +bool QWaylandAbstractDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) +{ + Q_D(QWaylandAbstractDecoration); + if ((d->m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) + return true; + return false; +} + +bool QWaylandAbstractDecoration::isDirty() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_isDirty; +} + +QWindow *QWaylandAbstractDecoration::window() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_window; +} + +QWaylandWindow *QWaylandAbstractDecoration::waylandWindow() const +{ + Q_D(const QWaylandAbstractDecoration); + return d->m_wayland_window; +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylanddecoration_p.h b/src/client/qwaylandabstractdecoration_p.h index c240b9c9d..6171cab14 100644 --- a/src/client/qwaylanddecoration_p.h +++ b/src/client/qwaylandabstractdecoration_p.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -39,8 +40,8 @@ ** ****************************************************************************/ -#ifndef QWAYLANDDECORATION_H -#define QWAYLANDDECORATION_H +#ifndef QWAYLANDABSTRACTDECORATION_H +#define QWAYLANDABSTRACTDECORATION_H #include <QtCore/QMargins> #include <QtCore/QPointF> @@ -64,77 +65,41 @@ class QEvent; class QWaylandScreen; class QWaylandWindow; class QWaylandInputDevice; +class QWaylandAbstractDecorationPrivate; -class Q_WAYLAND_CLIENT_EXPORT QWaylandDecoration +class Q_WAYLAND_CLIENT_EXPORT QWaylandAbstractDecoration : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QWaylandAbstractDecoration) public: - QWaylandDecoration(QWaylandWindow *window); - virtual ~QWaylandDecoration(); + QWaylandAbstractDecoration(); + virtual ~QWaylandAbstractDecoration(); + + void setWaylandWindow(QWaylandWindow *window); + QWaylandWindow *waylandWindow() const; void update(); bool isDirty() const; - bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods); - bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods); - bool inMouseButtonPressedState() const; - - void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); - void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons); - QMargins margins() const; + virtual QMargins margins() const = 0; QWindow *window() const; - QWaylandWindow *waylandWindow() const; const QImage &contentImage(); + virtual bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) = 0; + virtual bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) = 0; + protected: - void paint(QPaintDevice *device); + virtual void paint(QPaintDevice *device) = 0; + + void setMouseButtons(Qt::MouseButtons mb); -private: - void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); - void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void startResize(QWaylandInputDevice *inputDevice,enum wl_shell_surface_resize resize, Qt::MouseButtons buttons); + void startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons); bool isLeftClicked(Qt::MouseButtons newMouseButtonState); bool isLeftReleased(Qt::MouseButtons newMouseButtonState); - - QRectF closeButtonRect() const; - QRectF maximizeButtonRect() const; - QRectF minimizeButtonRect() const; - - QWindow *m_window; - QWaylandWindow *m_wayland_window; - - bool m_isDirty; - QImage m_decorationContentImage; - - QMargins m_margins; - Qt::MouseButtons m_mouseButtons; - - QColor m_foregroundColor; - QColor m_backgroundColor; - QStaticText m_windowTitle; }; -inline bool QWaylandDecoration::isDirty() const -{ - return m_isDirty; -} - -inline QMargins QWaylandDecoration::margins() const -{ - return m_margins; -} - -inline QWindow *QWaylandDecoration::window() const -{ - return m_window; -} - -inline QWaylandWindow *QWaylandDecoration::waylandWindow() const -{ - return m_wayland_window; -} - QT_END_NAMESPACE -#endif // QWAYLANDDECORATION_H +#endif // QWAYLANDABSTRACTDECORATION_H diff --git a/src/client/qwaylandcursor.cpp b/src/client/qwaylandcursor.cpp index 90789b0df..2a1339a79 100644 --- a/src/client/qwaylandcursor.cpp +++ b/src/client/qwaylandcursor.cpp @@ -66,12 +66,15 @@ QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) if (!hasCursorSize || cursorSize <= 0) cursorSize = 32; mCursorTheme = wl_cursor_theme_load(cursorTheme, cursorSize, mDisplay->shm()); + if (!mCursorTheme) + qDebug() << "Could not load theme" << cursorTheme; initCursorMap(); } QWaylandCursor::~QWaylandCursor() { - wl_cursor_theme_destroy(mCursorTheme); + if (mCursorTheme) + wl_cursor_theme_destroy(mCursorTheme); } struct wl_cursor_image *QWaylandCursor::cursorImage(Qt::CursorShape newShape) @@ -160,6 +163,9 @@ wl_cursor *QWaylandCursor::requestCursor(WaylandCursor shape) //If the cursor has not been loaded already, load it if (!cursor) { + if (!mCursorTheme) + return NULL; + QList<QByteArray> cursorNames = mCursorNamesMap.values(shape); foreach (QByteArray name, cursorNames) { cursor = wl_cursor_theme_get_cursor(mCursorTheme, name.constData()); diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index 74f879f97..83e74ce6c 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -60,6 +60,7 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWaylandInputDevice *inputDevice) : QtWayland::wl_data_device(manager->get_data_device(inputDevice->wl_seat())) , m_display(manager->display()) + , m_inputDevice(inputDevice) , m_enterSerial(0) , m_dragWindow(0) , m_dragPoint() @@ -92,7 +93,7 @@ void QWaylandDataDevice::setSelectionSource(QWaylandDataSource *source) m_selectionSource.reset(source); if (source) connect(source, &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::selectionSourceCancelled); - set_selection(source ? source->object() : 0, 0 /* TODO m_display->serial() */); + set_selection(source ? source->object() : Q_NULLPTR, m_inputDevice->serial()); } QWaylandDataOffer *QWaylandDataDevice::dragOffer() const diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h index dae91290e..ef82d84dd 100644 --- a/src/client/qwaylanddatadevice_p.h +++ b/src/client/qwaylanddatadevice_p.h @@ -88,7 +88,7 @@ private Q_SLOTS: private: QWaylandDisplay *m_display; - + QWaylandInputDevice *m_inputDevice; uint32_t m_enterSerial; QWindow *m_dragWindow; QPoint m_dragPoint; diff --git a/src/client/qwaylanddecorationfactory.cpp b/src/client/qwaylanddecorationfactory.cpp new file mode 100644 index 000000000..6f1f74693 --- /dev/null +++ b/src/client/qwaylanddecorationfactory.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddecorationfactory_p.h" +#include "qwaylanddecorationplugin_p.h" + +#include <QtCore/private/qfactoryloader_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QWaylandDecorationFactoryInterface_iid, QLatin1String("/wayland-decoration-client"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QWaylandDecorationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) +#endif + +QStringList QWaylandDecorationFactory::keys(const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + QStringList list; + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + list = directLoader()->keyMap().values(); + if (!list.isEmpty()) { + const QString postFix = QStringLiteral(" (from ") + + QDir::toNativeSeparators(pluginPath) + + QLatin1Char(')'); + const QStringList::iterator end = list.end(); + for (QStringList::iterator it = list.begin(); it != end; ++it) + (*it).append(postFix); + } + } + list.append(loader()->keyMap().values()); + return list; +#else + return QStringList(); +#endif +} + +QWaylandAbstractDecoration *QWaylandDecorationFactory::create(const QString &name, const QStringList &args, const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + // Try loading the plugin from platformPluginPath first: + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + if (QWaylandAbstractDecoration *ret = qLoadPlugin1<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(directLoader(), name, args)) + return ret; + } + if (QWaylandAbstractDecoration *ret = qLoadPlugin1<QWaylandAbstractDecoration, QWaylandDecorationPlugin>(loader(), name, args)) + return ret; +#endif + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylanddecorationfactory_p.h b/src/client/qwaylanddecorationfactory_p.h new file mode 100644 index 000000000..a7729bcaf --- /dev/null +++ b/src/client/qwaylanddecorationfactory_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDECORATIONFACTORY_H +#define QWAYLANDDECORATIONFACTORY_H + +#include <QtWaylandClient/private/qwaylandclientexport_p.h> +#include <QtCore/QStringList> + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecoration; + +class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static QWaylandAbstractDecoration *create(const QString &name, const QStringList &args, const QString &pluginPath = QString()); +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDDECORATIONFACTORY_H diff --git a/src/client/qwaylanddecorationplugin.cpp b/src/client/qwaylanddecorationplugin.cpp new file mode 100644 index 000000000..edad5f5f0 --- /dev/null +++ b/src/client/qwaylanddecorationplugin.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddecorationplugin_p.h" + +QT_BEGIN_NAMESPACE + +QWaylandDecorationPlugin::QWaylandDecorationPlugin(QObject *parent) + : QObject(parent) +{ +} +QWaylandDecorationPlugin::~QWaylandDecorationPlugin() +{ +} + +QT_END_NAMESPACE diff --git a/src/client/qwaylanddecorationplugin_p.h b/src/client/qwaylanddecorationplugin_p.h new file mode 100644 index 000000000..6ed8935db --- /dev/null +++ b/src/client/qwaylanddecorationplugin_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDECORATIONPLUGIN_H +#define QWAYLANDDECORATIONPLUGIN_H + +#include <QtWaylandClient/private/qwaylandclientexport_p.h> + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> +#include <QtCore/QObject> + +QT_BEGIN_NAMESPACE + +class QWaylandAbstractDecoration; + +#define QWaylandDecorationFactoryInterface_iid "org.qt-project.Qt.WaylandClient.QWaylandDecorationFactoryInterface.5.4" + +class Q_WAYLAND_CLIENT_EXPORT QWaylandDecorationPlugin : public QObject +{ + Q_OBJECT +public: + explicit QWaylandDecorationPlugin(QObject *parent = 0); + ~QWaylandDecorationPlugin(); + + virtual QWaylandAbstractDecoration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +QT_END_NAMESPACE + +#endif // QWAYLANDDECORATIONPLUGIN_H diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index c4a702d74..023050326 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -159,6 +159,7 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) init(registry); connect(mEventThreadObject, SIGNAL(newEventsRead()), this, SLOT(flushRequests())); + connect(mEventThreadObject, &QWaylandEventThread::fatalError, this, &QWaylandDisplay::exitWithError); mWindowManagerIntegration.reset(new QWaylandWindowManagerIntegration(this)); @@ -177,8 +178,10 @@ QWaylandDisplay::~QWaylandDisplay(void) void QWaylandDisplay::flushRequests() { - if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) - mEventThreadObject->checkErrorAndExit(); + if (wl_display_dispatch_queue_pending(mDisplay, mEventQueue) < 0) { + mEventThreadObject->checkError(); + exitWithError(); + } wl_display_flush(mDisplay); } @@ -186,8 +189,15 @@ void QWaylandDisplay::flushRequests() void QWaylandDisplay::blockingReadEvents() { - if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) - mEventThreadObject->checkErrorAndExit(); + if (wl_display_dispatch_queue(mDisplay, mEventQueue) < 0) { + mEventThreadObject->checkError(); + exitWithError(); + } +} + +void QWaylandDisplay::exitWithError() +{ + ::exit(1); } QWaylandScreen *QWaylandDisplay::screenForOutput(struct wl_output *output) const @@ -226,13 +236,14 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin struct ::wl_registry *registry = object(); if (interface == QStringLiteral("wl_output")) { - QWaylandScreen *screen = new QWaylandScreen(this, id); + QWaylandScreen *screen = new QWaylandScreen(this, version, id); mScreens.append(screen); // We need to get the output events before creating surfaces forceRoundTrip(); mWaylandIntegration->screenAdded(screen); } else if (interface == QStringLiteral("wl_compositor")) { - mCompositor.init(registry, id, 3); + mCompositorVersion = qMin((int)version, 3); + mCompositor.init(registry, id, mCompositorVersion); } else if (interface == QStringLiteral("wl_shm")) { mShm = static_cast<struct wl_shm *>(wl_registry_bind(registry, id, &wl_shm_interface,1)); } else if (interface == QStringLiteral("xdg_shell") @@ -241,7 +252,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin } else if (interface == QStringLiteral("wl_shell")){ mShell.reset(new QtWayland::wl_shell(registry, id, 1)); } else if (interface == QStringLiteral("wl_seat")) { - QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, id); + QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id); mInputDevices.append(inputDevice); } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 05bd7f15a..2f12ee7f9 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -117,6 +117,7 @@ public: const struct wl_compositor *wl_compositor() const { return mCompositor.object(); } QtWayland::wl_compositor *compositor() { return &mCompositor; } + int compositorVersion() const { return mCompositorVersion; } QtWayland::wl_shell *shell() { return mShell.data(); } QtWayland::xdg_shell *shellXdg(); @@ -165,6 +166,7 @@ public slots: private: void waitForScreens(); + void exitWithError(); struct Listener { RegistryListener listener; @@ -198,6 +200,7 @@ private: int mWritableNotificationFd; bool mScreensInitialized; QList<RegistryGlobal> mGlobals; + int mCompositorVersion; void registry_global(uint32_t id, const QString &interface, uint32_t version) Q_DECL_OVERRIDE; void registry_global_remove(uint32_t id) Q_DECL_OVERRIDE; diff --git a/src/client/qwaylandeventthread.cpp b/src/client/qwaylandeventthread.cpp index b7266765e..22efd6a2a 100644 --- a/src/client/qwaylandeventthread.cpp +++ b/src/client/qwaylandeventthread.cpp @@ -73,7 +73,7 @@ void QWaylandEventThread::displayConnect() // ### be careful what you do, this function may also be called from other // threads to clean up & exit. -void QWaylandEventThread::checkErrorAndExit() +void QWaylandEventThread::checkError() const { int ecode = wl_display_get_error(m_display); if ((ecode == EPIPE || ecode == ECONNRESET)) { @@ -82,13 +82,16 @@ void QWaylandEventThread::checkErrorAndExit() } else { qErrnoWarning(ecode, "The Wayland connection experienced a fatal error"); } - ::exit(1); } void QWaylandEventThread::readWaylandEvents() { - if (wl_display_dispatch(m_display) < 0) - checkErrorAndExit(); + if (wl_display_dispatch(m_display) < 0) { + checkError(); + m_readNotifier->setEnabled(false); + emit fatalError(); + return; + } emit newEventsRead(); } diff --git a/src/client/qwaylandeventthread_p.h b/src/client/qwaylandeventthread_p.h index d51d627b9..2df4b05c2 100644 --- a/src/client/qwaylandeventthread_p.h +++ b/src/client/qwaylandeventthread_p.h @@ -63,7 +63,7 @@ public: wl_display *display() const; - void checkErrorAndExit(); + void checkError() const; private slots: void readWaylandEvents(); @@ -72,6 +72,7 @@ private slots: signals: void newEventsRead(); + void fatalError(); private: diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index 4f72d6146..43c5807d4 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -157,9 +157,9 @@ QWaylandInputDevice::Touch::~Touch() wl_touch_destroy(object()); } -QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) +QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id) : QObject() - , QtWayland::wl_seat(display->wl_registry(), id, 2) + , QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 2)) , mQDisplay(display) , mDisplay(display->wl_display()) , mCaps(0) @@ -771,6 +771,17 @@ void QWaylandInputDevice::Keyboard::repeatKey() { mRepeatTimer.setInterval(25); QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(), + mRepeatTime, QEvent::KeyRelease, mRepeatKey, + modifiers(), + mRepeatCode, +#ifndef QT_NO_WAYLAND_XKB + mRepeatSym, mNativeModifiers, +#else + 0, 0, +#endif + mRepeatText, true); + + QWindowSystemInterface::handleExtendedKeyEvent(mFocus->window(), mRepeatTime, QEvent::KeyPress, mRepeatKey, modifiers(), mRepeatCode, diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index 0c6ecfb64..f1c264545 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -81,7 +81,7 @@ public: class Pointer; class Touch; - QWaylandInputDevice(QWaylandDisplay *display, uint32_t id); + QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id); ~QWaylandInputDevice(); uint32_t capabilities() const { return mCaps; } diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index ad99c67b9..27613eef7 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -181,12 +181,14 @@ QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) cons return new QWaylandShmWindow(window); } +#ifndef QT_NO_OPENGL QPlatformOpenGLContext *QWaylandIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { if (mDisplay->clientBufferIntegration()) return mDisplay->clientBufferIntegration()->createPlatformOpenGLContext(context->format(), context->shareHandle()); return 0; } +#endif // QT_NO_OPENGL QPlatformBackingStore *QWaylandIntegration::createPlatformBackingStore(QWindow *window) const { @@ -367,12 +369,12 @@ void QWaylandIntegration::initializeShellIntegration() } } -QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, uint32_t id) +QWaylandInputDevice *QWaylandIntegration::createInputDevice(QWaylandDisplay *display, int version, uint32_t id) { if (mInputDeviceIntegration) { - return mInputDeviceIntegration->createInputDevice(display, id); + return mInputDeviceIntegration->createInputDevice(display, version, id); } - return new QWaylandInputDevice(display, id); + return new QWaylandInputDevice(display, version, id); } void QWaylandIntegration::initializeInputDeviceIntegration() diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h index 9741b1a78..c0909418e 100644 --- a/src/client/qwaylandintegration_p.h +++ b/src/client/qwaylandintegration_p.h @@ -63,7 +63,9 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; +#ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; +#endif QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; QAbstractEventDispatcher *createEventDispatcher() const; @@ -91,7 +93,7 @@ public: QPlatformTheme *createPlatformTheme(const QString &name) const; - QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, uint32_t id); + QWaylandInputDevice *createInputDevice(QWaylandDisplay *display, int version, uint32_t id); virtual QWaylandClientBufferIntegration *clientBufferIntegration() const; virtual QWaylandServerBufferIntegration *serverBufferIntegration() const; diff --git a/src/client/qwaylandscreen.cpp b/src/client/qwaylandscreen.cpp index 88667ae0d..6e48c442e 100644 --- a/src/client/qwaylandscreen.cpp +++ b/src/client/qwaylandscreen.cpp @@ -53,14 +53,15 @@ QT_BEGIN_NAMESPACE -QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id) +QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id) : QPlatformScreen() - , QtWayland::wl_output(waylandDisplay->wl_registry(), id, 2) + , QtWayland::wl_output(waylandDisplay->wl_registry(), id, qMin(version, 2)) , m_outputId(id) , mWaylandDisplay(waylandDisplay) , mExtendedOutput(0) , mDepth(32) , mRefreshRate(60000) + , mTransform(-1) , mFormat(QImage::Format_ARGB32_Premultiplied) , mOutputName(QStringLiteral("Screen%1").arg(id)) , m_orientation(Qt::PrimaryOrientation) @@ -178,29 +179,7 @@ void QWaylandScreen::output_geometry(int32_t x, int32_t y, Q_UNUSED(subpixel); Q_UNUSED(make); - bool isPortrait = height > width; - switch (transform) { - case WL_OUTPUT_TRANSFORM_NORMAL: - m_orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation; - break; - case WL_OUTPUT_TRANSFORM_90: - m_orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation; - break; - case WL_OUTPUT_TRANSFORM_180: - m_orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation; - break; - case WL_OUTPUT_TRANSFORM_270: - m_orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation; - break; - // Ignore these ones, at least for now - case WL_OUTPUT_TRANSFORM_FLIPPED: - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - break; - } - - QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + mTransform = transform; if (!model.isEmpty()) mOutputName = model; @@ -214,6 +193,33 @@ void QWaylandScreen::output_done() // the done event is sent after all the geometry and the mode events are sent, // and the last mode event to be sent is the active one, so we can trust the // values of mGeometry and mRefreshRate here + + if (mTransform >= 0) { + bool isPortrait = mGeometry.height() > mGeometry.width(); + switch (mTransform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + m_orientation = isPortrait ? Qt::PortraitOrientation : Qt::LandscapeOrientation; + break; + case WL_OUTPUT_TRANSFORM_90: + m_orientation = isPortrait ? Qt::InvertedLandscapeOrientation : Qt::PortraitOrientation; + break; + case WL_OUTPUT_TRANSFORM_180: + m_orientation = isPortrait ? Qt::InvertedPortraitOrientation : Qt::InvertedLandscapeOrientation; + break; + case WL_OUTPUT_TRANSFORM_270: + m_orientation = isPortrait ? Qt::LandscapeOrientation : Qt::InvertedPortraitOrientation; + break; + // Ignore these ones, at least for now + case WL_OUTPUT_TRANSFORM_FLIPPED: + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + break; + } + + QWindowSystemInterface::handleScreenOrientationChange(screen(), m_orientation); + mTransform = -1; + } QWindowSystemInterface::handleScreenGeometryChange(screen(), mGeometry, mGeometry); QWindowSystemInterface::handleScreenRefreshRateChange(screen(), refreshRate()); } diff --git a/src/client/qwaylandscreen_p.h b/src/client/qwaylandscreen_p.h index 866ac26ea..d3173e0c9 100644 --- a/src/client/qwaylandscreen_p.h +++ b/src/client/qwaylandscreen_p.h @@ -56,7 +56,7 @@ class QWaylandExtendedOutput; class Q_WAYLAND_CLIENT_EXPORT QWaylandScreen : public QPlatformScreen, QtWayland::wl_output { public: - QWaylandScreen(QWaylandDisplay *waylandDisplay, uint32_t id); + QWaylandScreen(QWaylandDisplay *waylandDisplay, int version, uint32_t id); ~QWaylandScreen(); QWaylandDisplay *display() const; @@ -103,6 +103,7 @@ private: QRect mGeometry; int mDepth; int mRefreshRate; + int mTransform; QImage::Format mFormat; QSize mPhysicalSize; QString mOutputName; diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp index 14e1285d3..d407335d3 100644 --- a/src/client/qwaylandshmbackingstore.cpp +++ b/src/client/qwaylandshmbackingstore.cpp @@ -42,7 +42,7 @@ #include "qwaylandwindow_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandscreen_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include <QtCore/qdebug.h> #include <QtGui/QPainter> @@ -140,6 +140,9 @@ QWaylandShmBackingStore::QWaylandShmBackingStore(QWindow *window) QWaylandShmBackingStore::~QWaylandShmBackingStore() { + if (QWaylandWindow *w = waylandWindow()) + w->setBackingStore(Q_NULLPTR); + if (mFrameCallback) wl_callback_destroy(mFrameCallback); @@ -175,6 +178,14 @@ void QWaylandShmBackingStore::endPaint() waylandWindow()->setCanResize(true); } +void QWaylandShmBackingStore::hidden() +{ + if (mFrameCallback) { + wl_callback_destroy(mFrameCallback); + mFrameCallback = Q_NULLPTR; + } +} + void QWaylandShmBackingStore::ensureSize() { waylandWindow()->setBackingStore(this); @@ -295,7 +306,7 @@ void QWaylandShmBackingStore::updateDecorations() decorationPainter.drawImage(target, sourceImage, target); } -QWaylandDecoration *QWaylandShmBackingStore::windowDecoration() const +QWaylandAbstractDecoration *QWaylandShmBackingStore::windowDecoration() const { return waylandWindow()->decoration(); } @@ -312,6 +323,7 @@ QWaylandWindow *QWaylandShmBackingStore::waylandWindow() const return static_cast<QWaylandWindow *>(window()->handle()); } +#ifndef QT_NO_OPENGL QImage QWaylandShmBackingStore::toImage() const { // Invoked from QPlatformBackingStore::composeAndFlush() that is called @@ -320,6 +332,7 @@ QImage QWaylandShmBackingStore::toImage() const return *contentSurface(); } +#endif // QT_NO_OPENGL void QWaylandShmBackingStore::done(void *data, wl_callback *callback, uint32_t time) { diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h index 33f363f68..1212e52fe 100644 --- a/src/client/qwaylandshmbackingstore_p.h +++ b/src/client/qwaylandshmbackingstore_p.h @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE class QWaylandDisplay; -class QWaylandDecoration; +class QWaylandAbstractDecoration; class QWaylandWindow; class Q_WAYLAND_CLIENT_EXPORT QWaylandShmBuffer : public QWaylandBuffer { @@ -82,8 +82,9 @@ public: void resize(const QSize &size); void beginPaint(const QRegion &); void endPaint(); + void hidden(); - QWaylandDecoration *windowDecoration() const; + QWaylandAbstractDecoration *windowDecoration() const; QMargins windowDecorationMargins() const; QImage *entireSurface() const; @@ -93,7 +94,9 @@ public: QWaylandWindow *waylandWindow() const; void iterateBuffer(); +#ifndef QT_NO_OPENGL QImage toImage() const Q_DECL_OVERRIDE; +#endif private: void updateDecorations(); diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index ec00d1af6..9f7bdda1f 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -50,9 +50,11 @@ #include "qwaylandwlshellsurface_p.h" #include "qwaylandxdgsurface_p.h" #include "qwaylandsubsurface_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandwindowmanagerintegration_p.h" #include "qwaylandnativeinterface_p.h" +#include "qwaylanddecorationfactory_p.h" +#include "qwaylandshmbackingstore_p.h" #include <QtCore/QFileInfo> #include <QtCore/QPointer> @@ -90,6 +92,7 @@ QWaylandWindow::QWaylandWindow(QWindow *window) , mMouseSerial(0) , mState(Qt::WindowNoState) , mMask() + , mBackingStore(Q_NULLPTR) { init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this))); @@ -249,6 +252,9 @@ void QWaylandWindow::setVisible(bool visible) if (!deleteGuard.isNull()) { attach(static_cast<QWaylandBuffer *>(0), 0, 0); commit(); + if (mBackingStore) { + mBackingStore->hidden(); + } } } } @@ -443,6 +449,9 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { + if (mDisplay->compositorVersion() < 2) + return; + wl_output_transform transform; bool isPortrait = window()->screen() && window()->screen()->primaryOrientation() == Qt::PortraitOrientation; switch (orientation) { @@ -506,6 +515,7 @@ bool QWaylandWindow::createDecoration() if (!mDisplay->supportsWindowDecoration()) return false; + static bool decorationPluginFailed = false; bool decoration = false; switch (window()->type()) { case Qt::Window: @@ -523,9 +533,40 @@ bool QWaylandWindow::createDecoration() if (window()->flags() & Qt::BypassWindowManagerHint) decoration = false; - if (decoration) { - if (!mWindowDecoration) - mWindowDecoration = new QWaylandDecoration(this); + if (decoration && !decorationPluginFailed) { + if (!mWindowDecoration) { + QStringList decorations = QWaylandDecorationFactory::keys(); + if (decorations.empty()) { + qWarning() << "No decoration plugins available. Running with no decorations."; + decorationPluginFailed = true; + return false; + } + + QString targetKey; + QByteArray decorationPluginName = qgetenv("QT_WAYLAND_DECORATION"); + if (!decorationPluginName.isEmpty()) { + targetKey = QString::fromLocal8Bit(decorationPluginName); + if (!decorations.contains(targetKey)) { + qWarning() << "Requested decoration " << targetKey << " not found, falling back to default"; + targetKey = QString(); // fallthrough + } + } + + if (targetKey.isEmpty()) + targetKey = decorations.first(); // first come, first served. + + + mWindowDecoration = QWaylandDecorationFactory::create(targetKey, QStringList()); + if (!mWindowDecoration) { + qWarning() << "Could not create decoration from factory! Running with no decorations."; + decorationPluginFailed = true; + return false; + } + mWindowDecoration->setWaylandWindow(this); + if (subSurfaceWindow()) { + subSurfaceWindow()->adjustPositionOfChildren(); + } + } } else { delete mWindowDecoration; mWindowDecoration = 0; @@ -534,19 +575,11 @@ bool QWaylandWindow::createDecoration() return mWindowDecoration; } -QWaylandDecoration *QWaylandWindow::decoration() const +QWaylandAbstractDecoration *QWaylandWindow::decoration() const { return mWindowDecoration; } -void QWaylandWindow::setDecoration(QWaylandDecoration *decoration) -{ - mWindowDecoration = decoration; - if (subSurfaceWindow()) { - subSurfaceWindow()->adjustPositionOfChildren(); - } -} - static QWindow *topLevelWindow(QWindow *window) { while (QWindow *parent = window->parent()) @@ -695,7 +728,6 @@ bool QWaylandWindow::setWindowStateInternal(Qt::WindowState state) // QPlatformWindow::setWindowState returns, so we cannot rely on QWindow::windowState // here. We use then this mState variable. mState = state; - createDecoration(); if (mShellSurface) { switch (state) { diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 7da43c7b9..0c55cd88d 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -60,7 +60,7 @@ class QWaylandDisplay; class QWaylandBuffer; class QWaylandShellSurface; class QWaylandSubSurface; -class QWaylandDecoration; +class QWaylandAbstractDecoration; class QWaylandInputDevice; class QWaylandScreen; class QWaylandShmBackingStore; @@ -146,9 +146,7 @@ public: bool isExposed() const Q_DECL_OVERRIDE; void unfocus(); - QWaylandDecoration *decoration() const; - void setDecoration(QWaylandDecoration *decoration); - + QWaylandAbstractDecoration *decoration() const; void handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, @@ -201,7 +199,7 @@ protected: QWaylandShellSurface *mShellSurface; QWaylandSubSurface *mSubSurfaceWindow; - QWaylandDecoration *mWindowDecoration; + QWaylandAbstractDecoration *mWindowDecoration; bool mMouseEventsInContentArea; Qt::MouseButtons mMousePressedInContentArea; Qt::CursorShape m_cursorShape; diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp index a8e89ec98..86115fa38 100644 --- a/src/client/qwaylandwlshellsurface.cpp +++ b/src/client/qwaylandwlshellsurface.cpp @@ -44,7 +44,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandscreen_p.h" #include "qwaylandextendedsurface_p.h" diff --git a/src/client/qwaylandxdgshell.cpp b/src/client/qwaylandxdgshell.cpp index 8a96a0304..f31d63f42 100644 --- a/src/client/qwaylandxdgshell.cpp +++ b/src/client/qwaylandxdgshell.cpp @@ -44,7 +44,6 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" #include "qwaylandscreen_p.h" #include <QtCore/QDebug> diff --git a/src/client/qwaylandxdgsurface.cpp b/src/client/qwaylandxdgsurface.cpp index 126c9db72..318ff86d9 100644 --- a/src/client/qwaylandxdgsurface.cpp +++ b/src/client/qwaylandxdgsurface.cpp @@ -44,7 +44,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandwindow_p.h" #include "qwaylandinputdevice_p.h" -#include "qwaylanddecoration_p.h" +#include "qwaylandabstractdecoration_p.h" #include "qwaylandscreen_p.h" #include "qwaylandextendedsurface_p.h" diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index cccca2e7a..1333100c6 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -61,7 +61,7 @@ public: void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE { - QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); + QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, wl_resource_get_version(resource->handle), static_cast<QWaylandQuickCompositor *>(m_qt_compositor)); m_surfaces << surface->handle(); //BUG: This may not be an on-screen window surface though m_qt_compositor->surfaceCreated(surface); diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index 1ce229d21..ae3dfbb5d 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -124,8 +124,8 @@ public: class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate { public: - QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) - : QWaylandSurfacePrivate(client, id, c, surf) + QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) + : QWaylandSurfacePrivate(client, id, version, c, surf) , buffer(new BufferAttacher) , compositor(c) , useTextureAlpha(true) @@ -158,8 +158,8 @@ public: bool clientRenderingEnabled; }; -QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor) - : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, compositor, this)) +QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *compositor) + : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, version, compositor, this)) { Q_D(QWaylandQuickSurface); d->buffer->surface = this; diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h index 63a25b3de..d65a98273 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.h +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -62,7 +62,7 @@ class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged) Q_PROPERTY(QObject *windowProperties READ windowPropertyMap CONSTANT) public: - QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor); + QWaylandQuickSurface(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *compositor); ~QWaylandQuickSurface(); QSGTexture *texture() const; diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 9e1ffc546..b5c38d88e 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE -QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface) - : QtWayland::Surface(wlClient, id, compositor, surface) +QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface) + : QtWayland::Surface(wlClient, id, version, compositor, surface) , closing(false) , refCount(1) , client(QWaylandClient::fromWlClient(wlClient)) @@ -73,8 +73,8 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, -QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor) - : QObject(*new QWaylandSurfacePrivate(client, id, compositor, this)) +QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor) + : QObject(*new QWaylandSurfacePrivate(client, id, version, compositor, this)) { } @@ -330,14 +330,7 @@ void QWaylandSurface::destroySurface() { QWaylandSurfaceOp op(QWaylandSurfaceOp::Close); if (!sendInterfaceOp(op)) - destroySurfaceByForce(); -} - -void QWaylandSurface::destroySurfaceByForce() -{ - Q_D(QWaylandSurface); - wl_resource *surface_resource = d->resource()->handle; - wl_resource_destroy(surface_resource); + emit surfaceDestroyed(); } /*! diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index aa5cfeeb8..4b802d778 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -93,7 +93,6 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject Q_PROPERTY(QString title READ title NOTIFY titleChanged) Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged) Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged) - Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) Q_PROPERTY(QWaylandSurface *transientParent READ transientParent) Q_PROPERTY(QPointF transientOffset READ transientOffset) @@ -121,7 +120,7 @@ public: Texture }; - QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor); + QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor); virtual ~QWaylandSurface(); QWaylandClient *client() const; @@ -175,7 +174,6 @@ public: Q_INVOKABLE void destroy(); Q_INVOKABLE void destroySurface(); - Q_INVOKABLE void destroySurfaceByForce(); Q_INVOKABLE void ping(); void ref(); diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h index d6377f21e..2e6f75a64 100644 --- a/src/compositor/compositor_api/qwaylandsurface_p.h +++ b/src/compositor/compositor_api/qwaylandsurface_p.h @@ -59,7 +59,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public { Q_DECLARE_PUBLIC(QWaylandSurface) public: - QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface); + QWaylandSurfacePrivate(wl_client *wlClient, quint32 id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface); void setType(QWaylandSurface::WindowType type); void setTitle(const QString &title); void setClassName(const QString &className); diff --git a/src/compositor/hardware_integration/qwlhwintegration.cpp b/src/compositor/hardware_integration/qwlhwintegration.cpp index 62614c4d4..e71bb652b 100644 --- a/src/compositor/hardware_integration/qwlhwintegration.cpp +++ b/src/compositor/hardware_integration/qwlhwintegration.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { HardwareIntegration::HardwareIntegration(Compositor *compositor) - : qt_hardware_integration(compositor->wl_display()) + : qt_hardware_integration(compositor->wl_display(), 1) { } void HardwareIntegration::setClientBufferIntegration(const QString &name) diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp index a792d5531..91fd1818a 100644 --- a/src/compositor/wayland_wrapper/qwlcompositor.cpp +++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp @@ -140,7 +140,7 @@ void Compositor::init() if (socketArg != -1 && socketArg + 1 < arguments.size()) m_socket_name = arguments.at(socketArg + 1).toLocal8Bit(); - wl_compositor::init(m_display->handle()); + wl_compositor::init(m_display->handle(), 3); m_data_device_manager = new DataDeviceManager(this); @@ -244,7 +244,7 @@ void Compositor::cleanupGraphicsResources() void Compositor::compositor_create_surface(Resource *resource, uint32_t id) { - QWaylandSurface *surface = new QWaylandSurface(resource->client(), id, m_qt_compositor); + QWaylandSurface *surface = new QWaylandSurface(resource->client(), id, resource->version(), m_qt_compositor); m_surfaces << surface->handle(); //BUG: This may not be an on-screen window surface though m_qt_compositor->surfaceCreated(surface); @@ -466,7 +466,7 @@ void Compositor::sendDragEndEvent() void Compositor::bindGlobal(wl_client *client, void *data, uint32_t version, uint32_t id) { QWaylandGlobalInterface *iface = static_cast<QWaylandGlobalInterface *>(data); - iface->bind(client, version, id); + iface->bind(client, qMin(iface->version(), version), id); }; void Compositor::loadClientBufferIntegration() diff --git a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp index 2c59f1b52..ab4c3fec0 100644 --- a/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp +++ b/src/compositor/wayland_wrapper/qwldatadevicemanager.cpp @@ -60,7 +60,7 @@ namespace QtWayland { DataDeviceManager::DataDeviceManager(Compositor *compositor) : QObject(0) - , wl_data_device_manager(compositor->wl_display()) + , wl_data_device_manager(compositor->wl_display(), 1) , m_compositor(compositor) , m_current_selection_source(0) , m_retainedReadNotifier(0) diff --git a/src/compositor/wayland_wrapper/qwldataoffer.cpp b/src/compositor/wayland_wrapper/qwldataoffer.cpp index 312e53858..02da4ec92 100644 --- a/src/compositor/wayland_wrapper/qwldataoffer.cpp +++ b/src/compositor/wayland_wrapper/qwldataoffer.cpp @@ -51,7 +51,7 @@ namespace QtWayland { DataOffer::DataOffer(DataSource *dataSource, QtWaylandServer::wl_data_device::Resource *target) - : QtWaylandServer::wl_data_offer(target->client(), 0) + : QtWaylandServer::wl_data_offer(target->client(), 0, 1) , m_dataSource(dataSource) { // FIXME: connect to dataSource and reset m_dataSource on destroy diff --git a/src/compositor/wayland_wrapper/qwldatasource.cpp b/src/compositor/wayland_wrapper/qwldatasource.cpp index 679693c32..21e622703 100644 --- a/src/compositor/wayland_wrapper/qwldatasource.cpp +++ b/src/compositor/wayland_wrapper/qwldatasource.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { DataSource::DataSource(struct wl_client *client, uint32_t id, uint32_t time) - : QtWaylandServer::wl_data_source(client, id) + : QtWaylandServer::wl_data_source(client, id, 1) , m_time(time) , m_device(0) , m_manager(0) diff --git a/src/compositor/wayland_wrapper/qwlextendedoutput.cpp b/src/compositor/wayland_wrapper/qwlextendedoutput.cpp index 3517a99d3..8bf69ff41 100644 --- a/src/compositor/wayland_wrapper/qwlextendedoutput.cpp +++ b/src/compositor/wayland_wrapper/qwlextendedoutput.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { OutputExtensionGlobal::OutputExtensionGlobal(Compositor *compositor) - : QtWaylandServer::qt_output_extension(compositor->wl_display()) + : QtWaylandServer::qt_output_extension(compositor->wl_display(), 1) , m_compositor(compositor) { } @@ -59,7 +59,7 @@ void OutputExtensionGlobal::output_extension_get_extended_output(qt_output_exten Output *output = static_cast<Output *>(OutputGlobal::Resource::fromResource(output_resource)); Q_ASSERT(output->extendedOutput == 0); - ExtendedOutput *extendedOutput = static_cast<ExtendedOutput *>(qt_extended_output::add(resource->client(), id)); + ExtendedOutput *extendedOutput = static_cast<ExtendedOutput *>(qt_extended_output::add(resource->client(), id, resource->version())); Q_ASSERT(!output->extendedOutput); output->extendedOutput = extendedOutput; diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp index a2ee34e36..55878295d 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlextendedsurface.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { SurfaceExtensionGlobal::SurfaceExtensionGlobal(Compositor *compositor) - : QtWaylandServer::qt_surface_extension(compositor->wl_display()) + : QtWaylandServer::qt_surface_extension(compositor->wl_display(), 1) { } @@ -57,12 +57,12 @@ void SurfaceExtensionGlobal::surface_extension_get_extended_surface(Resource *re struct wl_resource *surface_resource) { Surface *surface = Surface::fromResource(surface_resource); - new ExtendedSurface(resource->client(),id,surface); + new ExtendedSurface(resource->client(),id, wl_resource_get_version(resource->handle), surface); } -ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, Surface *surface) +ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, int version, Surface *surface) : QWaylandSurfaceInterface(surface->waylandSurface()) - , QtWaylandServer::qt_extended_surface(client,id) + , QtWaylandServer::qt_extended_surface(client, id, version) , m_surface(surface) , m_windowFlags(0) { @@ -72,7 +72,8 @@ ExtendedSurface::ExtendedSurface(struct wl_client *client, uint32_t id, Surface ExtendedSurface::~ExtendedSurface() { - m_surface->setExtendedSurface(0); + if (m_surface) + m_surface->setExtendedSurface(0); } void ExtendedSurface::sendGenericProperty(const QString &name, const QVariant &variant) @@ -91,6 +92,11 @@ void ExtendedSurface::setVisibility(QWindow::Visibility visibility, bool updateC send_onscreen_visibility(visibility); } +void ExtendedSurface::setParentSurface(Surface *surface) +{ + m_surface = surface; +} + bool ExtendedSurface::runOperation(QWaylandSurfaceOp *op) { switch (op->type()) { @@ -141,7 +147,7 @@ void ExtendedSurface::extended_surface_set_content_orientation_mask(Resource *re Qt::ScreenOrientations oldMask = m_contentOrientationMask; m_contentOrientationMask = mask; - if (mask != oldMask) + if (m_surface && mask != oldMask) emit m_surface->waylandSurface()->orientationUpdateMaskChanged(); } @@ -168,7 +174,7 @@ void ExtendedSurface::extended_surface_set_window_flags(Resource *resource, int3 { Q_UNUSED(resource); QWaylandSurface::WindowFlags windowFlags(flags); - if (windowFlags== m_windowFlags) + if (m_surface || windowFlags == m_windowFlags) return; m_windowFlags = windowFlags; emit m_surface->waylandSurface()->windowFlagsChanged(windowFlags); @@ -181,12 +187,14 @@ void ExtendedSurface::extended_surface_destroy_resource(Resource *) void ExtendedSurface::extended_surface_raise(Resource *) { - emit m_surface->waylandSurface()->raiseRequested(); + if (m_surface) + emit m_surface->waylandSurface()->raiseRequested(); } void ExtendedSurface::extended_surface_lower(Resource *) { - emit m_surface->waylandSurface()->lowerRequested(); + if (m_surface) + emit m_surface->waylandSurface()->lowerRequested(); } } diff --git a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h index c22a42832..9bcb28272 100644 --- a/src/compositor/wayland_wrapper/qwlextendedsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlextendedsurface_p.h @@ -75,7 +75,7 @@ private: class ExtendedSurface : public QWaylandSurfaceInterface, public QtWaylandServer::qt_extended_surface { public: - ExtendedSurface(struct wl_client *client, uint32_t id, Surface *surface); + ExtendedSurface(struct wl_client *client, uint32_t id, int version, Surface *surface); ~ExtendedSurface(); void sendGenericProperty(const QString &name, const QVariant &variant); @@ -87,6 +87,7 @@ public: ExtendedSurface *parent() const; void setParent(ExtendedSurface *parent); QLinkedList<QWaylandSurface *> subSurfaces() const; + void setParentSurface(Surface *s); Qt::ScreenOrientations contentOrientationMask() const; diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp index 8ac629c86..40f21134e 100644 --- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp +++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { InputDevice::InputDevice(QWaylandInputDevice *handle, Compositor *compositor, QWaylandInputDevice::CapabilityFlags caps) - : QtWaylandServer::wl_seat(compositor->wl_display()) + : QtWaylandServer::wl_seat(compositor->wl_display(), 2) , m_handle(handle) , m_dragHandle(new QWaylandDrag(this)) , m_compositor(compositor) @@ -151,21 +151,21 @@ void InputDevice::setCapabilities(QWaylandInputDevice::CapabilityFlags caps) void InputDevice::seat_get_pointer(wl_seat::Resource *resource, uint32_t id) { if (!m_pointer.isNull()) { - m_pointer->add(resource->client(), id); + m_pointer->add(resource->client(), id, resource->version()); } } void InputDevice::seat_get_keyboard(wl_seat::Resource *resource, uint32_t id) { if (!m_keyboard.isNull()) { - m_keyboard->add(resource->client(), id); + m_keyboard->add(resource->client(), id, resource->version()); } } void InputDevice::seat_get_touch(wl_seat::Resource *resource, uint32_t id) { if (!m_touch.isNull()) { - m_touch->add(resource->client(), id); + m_touch->add(resource->client(), id, resource->version()); } } @@ -337,7 +337,7 @@ void InputDevice::clientRequestedDataDevice(DataDeviceManager *, struct wl_clien { if (!m_data_device) m_data_device.reset(new DataDevice(this)); - m_data_device->add(client, id); + m_data_device->add(client, id, 1); } Compositor *InputDevice::compositor() const diff --git a/src/compositor/wayland_wrapper/qwlinputmethod.cpp b/src/compositor/wayland_wrapper/qwlinputmethod.cpp index d1b43992f..ea495b37c 100644 --- a/src/compositor/wayland_wrapper/qwlinputmethod.cpp +++ b/src/compositor/wayland_wrapper/qwlinputmethod.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { InputMethod::InputMethod(Compositor *compositor, InputDevice *seat) - : QtWaylandServer::wl_input_method(seat->compositor()->wl_display()) + : QtWaylandServer::wl_input_method(seat->compositor()->wl_display(), 1) , m_compositor(compositor) , m_seat(seat) , m_resource(0) diff --git a/src/compositor/wayland_wrapper/qwlinputmethodcontext.cpp b/src/compositor/wayland_wrapper/qwlinputmethodcontext.cpp index b8a7859f5..5b9a24db1 100644 --- a/src/compositor/wayland_wrapper/qwlinputmethodcontext.cpp +++ b/src/compositor/wayland_wrapper/qwlinputmethodcontext.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { InputMethodContext::InputMethodContext(wl_client *client, TextInput *textInput) - : QtWaylandServer::wl_input_method_context(client, 0) + : QtWaylandServer::wl_input_method_context(client, 0, 1) , m_textInput(textInput) { } diff --git a/src/compositor/wayland_wrapper/qwlinputpanel.cpp b/src/compositor/wayland_wrapper/qwlinputpanel.cpp index 3848543d7..4dae2749c 100644 --- a/src/compositor/wayland_wrapper/qwlinputpanel.cpp +++ b/src/compositor/wayland_wrapper/qwlinputpanel.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { InputPanel::InputPanel(Compositor *compositor) - : QtWaylandServer::wl_input_panel(compositor->wl_display()) + : QtWaylandServer::wl_input_panel(compositor->wl_display(), 1) , m_compositor(compositor) , m_handle(new QWaylandInputPanel(this)) , m_focus() diff --git a/src/compositor/wayland_wrapper/qwlinputpanelsurface.cpp b/src/compositor/wayland_wrapper/qwlinputpanelsurface.cpp index fd258bcb5..138e57032 100644 --- a/src/compositor/wayland_wrapper/qwlinputpanelsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlinputpanelsurface.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { InputPanelSurface::InputPanelSurface(wl_client *client, int id, Surface *surface) - : QtWaylandServer::wl_input_panel_surface(client, id) + : QtWaylandServer::wl_input_panel_surface(client, id, 1) , m_surface(surface) , m_type(Invalid) , m_output(0) diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp index 67ad3b727..748639c8d 100644 --- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp +++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp @@ -84,11 +84,13 @@ Keyboard::Keyboard(Compositor *compositor, InputDevice *seat) Keyboard::~Keyboard() { #ifndef QT_NO_WAYLAND_XKB - if (m_keymap_area) - munmap(m_keymap_area, m_keymap_size); - close(m_keymap_fd); - xkb_context_unref(m_context); - xkb_state_unref(m_state); + if (m_context) { + if (m_keymap_area) + munmap(m_keymap_area, m_keymap_size); + close(m_keymap_fd); + xkb_context_unref(m_context); + xkb_state_unref(m_state); + } #endif } @@ -183,14 +185,16 @@ QtWaylandServer::wl_keyboard::Resource *Keyboard::focusResource() const void Keyboard::keyboard_bind_resource(wl_keyboard::Resource *resource) { #ifndef QT_NO_WAYLAND_XKB - send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - m_keymap_fd, m_keymap_size); -#else + if (m_context) { + send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + m_keymap_fd, m_keymap_size); + return; + } +#endif int null_fd = open("/dev/null", O_RDONLY); send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */, null_fd, 0); close(null_fd); -#endif } void Keyboard::keyboard_destroy_resource(wl_keyboard::Resource *resource) @@ -240,6 +244,9 @@ void Keyboard::modifiers(uint32_t serial, uint32_t mods_depressed, void Keyboard::updateModifierState(uint code, uint32_t state) { #ifndef QT_NO_WAYLAND_XKB + if (!m_context) + return; + xkb_state_update_key(m_state, code, state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); uint32_t modsDepressed = xkb_state_serialize_mods(m_state, (xkb_state_component)XKB_STATE_DEPRESSED); @@ -269,6 +276,9 @@ void Keyboard::updateKeymap() { m_pendingKeymap = false; #ifndef QT_NO_WAYLAND_XKB + if (!m_context) + return; + createXKBKeymap(); foreach (Resource *res, resourceMap()) { send_keymap(res->handle, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, m_keymap_fd, m_keymap_size); @@ -303,8 +313,10 @@ static int createAnonymousFile(size_t size) if (fd < 0) return -1; - if (ftruncate(fd, size) < 0) + if (ftruncate(fd, size) < 0) { + close(fd); return -1; + } return fd; } @@ -312,11 +324,19 @@ static int createAnonymousFile(size_t size) void Keyboard::initXKB() { m_context = xkb_context_new(static_cast<xkb_context_flags>(0)); + if (!m_context) { + qWarning("Failed to create a XKB context: keymap will not be supported"); + return; + } + createXKBKeymap(); } void Keyboard::createXKBKeymap() { + if (!m_context) + return; + if (m_state) xkb_state_unref(m_state); diff --git a/src/compositor/wayland_wrapper/qwloutput.cpp b/src/compositor/wayland_wrapper/qwloutput.cpp index 09e2abc87..7638370bc 100644 --- a/src/compositor/wayland_wrapper/qwloutput.cpp +++ b/src/compositor/wayland_wrapper/qwloutput.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { OutputGlobal::OutputGlobal(struct ::wl_display *display) - : QtWaylandServer::wl_output(display) + : QtWaylandServer::wl_output(display, 2) , m_displayId(-1) , m_numQueued(0) , m_transform(WL_OUTPUT_TRANSFORM_NORMAL) @@ -70,7 +70,9 @@ void OutputGlobal::output_bind_resource(Resource *resource) wl_output_send_mode(resource->handle, WL_OUTPUT_MODE_CURRENT|WL_OUTPUT_MODE_PREFERRED, size().width(), size().height(), refreshRate()); - wl_output_send_done(resource->handle); + + if (resource->version() >= 2) + wl_output_send_done(resource->handle); } void OutputGlobal::setPhysicalSize(const QSize &size) @@ -81,7 +83,9 @@ void OutputGlobal::setPhysicalSize(const QSize &size) foreach (Resource *res, resourceMap()) { wl_output_send_geometry(res->handle, 0, 0, m_physicalSize.width(), m_physicalSize.height(), 0, "", "", m_transform); - wl_output_send_done(res->handle); + + if (res->version() >= 2) + wl_output_send_done(res->handle); } } } @@ -121,7 +125,8 @@ void OutputGlobal::sendOutputOrientation(Qt::ScreenOrientation orientation) foreach (Resource *res, resourceMap()) { wl_output_send_geometry(res->handle, 0, 0, m_physicalSize.width(), m_physicalSize.height(), 0, "", "", m_transform); - wl_output_send_done(res->handle); + if (res->version() >= 2) + wl_output_send_done(res->handle); } } diff --git a/src/compositor/wayland_wrapper/qwlqtkey.cpp b/src/compositor/wayland_wrapper/qwlqtkey.cpp index 74c21b6a8..285709064 100644 --- a/src/compositor/wayland_wrapper/qwlqtkey.cpp +++ b/src/compositor/wayland_wrapper/qwlqtkey.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { QtKeyExtensionGlobal::QtKeyExtensionGlobal(Compositor *compositor) - : QtWaylandServer::qt_key_extension(compositor->wl_display()) + : QtWaylandServer::qt_key_extension(compositor->wl_display(), 2) , m_compositor(compositor) { } diff --git a/src/compositor/wayland_wrapper/qwlqttouch.cpp b/src/compositor/wayland_wrapper/qwlqttouch.cpp index 335ee1489..0110c433b 100644 --- a/src/compositor/wayland_wrapper/qwlqttouch.cpp +++ b/src/compositor/wayland_wrapper/qwlqttouch.cpp @@ -51,7 +51,7 @@ namespace QtWayland { static const int maxRawPos = 24; TouchExtensionGlobal::TouchExtensionGlobal(Compositor *compositor) - : QtWaylandServer::qt_touch_extension(compositor->wl_display()) + : QtWaylandServer::qt_touch_extension(compositor->wl_display(), 1) , m_compositor(compositor) , m_flags(0) , m_resources() diff --git a/src/compositor/wayland_wrapper/qwlregion.cpp b/src/compositor/wayland_wrapper/qwlregion.cpp index fdbc5390d..f9bcde380 100644 --- a/src/compositor/wayland_wrapper/qwlregion.cpp +++ b/src/compositor/wayland_wrapper/qwlregion.cpp @@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { Region::Region(struct wl_client *client, uint32_t id) - : QtWaylandServer::wl_region(client, id) + : QtWaylandServer::wl_region(client, id, 1) { } diff --git a/src/compositor/wayland_wrapper/qwlshellsurface.cpp b/src/compositor/wayland_wrapper/qwlshellsurface.cpp index d54a223d6..80304f3cb 100644 --- a/src/compositor/wayland_wrapper/qwlshellsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlshellsurface.cpp @@ -67,8 +67,7 @@ const wl_interface *Shell::interface() const void Shell::bind(struct wl_client *client, uint32_t version, uint32_t id) { - Q_UNUSED(version) - add(client, id); + add(client, id, version); } ShellSurfacePopupGrabber *Shell::getPopupGrabber(InputDevice *input) @@ -89,10 +88,9 @@ void Shell::shell_get_shell_surface(Resource *resource, uint32_t id, struct ::wl ShellSurface::ShellSurface(Shell *shell, wl_client *client, uint32_t id, Surface *surface) : QWaylandSurfaceInterface(surface->waylandSurface()) - , wl_shell_surface(client, id) + , wl_shell_surface(client, id, 1) , m_shell(shell) , m_surface(surface) - , m_deleting(false) , m_resizeGrabber(0) , m_moveGrabber(0) , m_popupGrabber(0) @@ -105,13 +103,6 @@ ShellSurface::ShellSurface(Shell *shell, wl_client *client, uint32_t id, Surface ShellSurface::~ShellSurface() { - // We must destroy the wl_resource here, but be careful not to do it - // if we're here from shell_surface_destroy_resource(), i.e. if the - // wl_resource was destroyed already - if (!m_deleting) { - m_deleting = true; - wl_resource_destroy(resource()->handle); - } } void ShellSurface::sendConfigure(uint32_t edges, int32_t width, int32_t height) @@ -201,11 +192,7 @@ void ShellSurface::shell_surface_destroy_resource(Resource *) if (m_popupGrabber) m_popupGrabber->removePopup(this); - // If we're here from the destructor don't delete this again - if (!m_deleting) { - m_deleting = true; - delete this; - } + delete this; } void ShellSurface::shell_surface_move(Resource *resource, diff --git a/src/compositor/wayland_wrapper/qwlshellsurface_p.h b/src/compositor/wayland_wrapper/qwlshellsurface_p.h index f724ef290..92405bbc9 100644 --- a/src/compositor/wayland_wrapper/qwlshellsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlshellsurface_p.h @@ -112,7 +112,6 @@ private: Shell *m_shell; Surface *m_surface; QWaylandSurfaceView *m_view; - bool m_deleting; ShellSurfaceResizeGrabber *m_resizeGrabber; ShellSurfaceMoveGrabber *m_moveGrabber; diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index b494b3e01..ee8197013 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -109,8 +109,8 @@ static QRegion infiniteRegion() { QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max()))); } -Surface::Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface) - : QtWaylandServer::wl_surface(client, id) +Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface) + : QtWaylandServer::wl_surface(client, id, version) , m_compositor(compositor->handle()) , m_waylandSurface(surface) , m_buffer(0) @@ -340,8 +340,7 @@ Qt::ScreenOrientation Surface::contentOrientation() const void Surface::surface_destroy_resource(Resource *) { if (m_extendedSurface) { - if (m_extendedSurface->resource()) - wl_resource_destroy(m_extendedSurface->resource()->handle); + m_extendedSurface->setParentSurface(Q_NULLPTR); m_extendedSurface = 0; } diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 70b86aec6..bbab57a4d 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -76,7 +76,7 @@ class FrameCallback; class Q_COMPOSITOR_EXPORT Surface : public QtWaylandServer::wl_surface { public: - Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface); + Surface(struct wl_client *client, uint32_t id, int version, QWaylandCompositor *compositor, QWaylandSurface *surface); ~Surface(); static Surface *fromResource(struct ::wl_resource *resource); diff --git a/src/compositor/wayland_wrapper/qwltextinput.cpp b/src/compositor/wayland_wrapper/qwltextinput.cpp index 35bce8327..9aba674f4 100644 --- a/src/compositor/wayland_wrapper/qwltextinput.cpp +++ b/src/compositor/wayland_wrapper/qwltextinput.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { TextInput::TextInput(Compositor *compositor, struct ::wl_client *client, int id) - : wl_text_input(client, id) + : wl_text_input(client, id, 1) , m_compositor(compositor) , m_focus() , m_inputPanelVisible() diff --git a/src/compositor/wayland_wrapper/qwltextinputmanager.cpp b/src/compositor/wayland_wrapper/qwltextinputmanager.cpp index 87b6e54e5..92062944b 100644 --- a/src/compositor/wayland_wrapper/qwltextinputmanager.cpp +++ b/src/compositor/wayland_wrapper/qwltextinputmanager.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE namespace QtWayland { TextInputManager::TextInputManager(Compositor *compositor) - : QtWaylandServer::wl_text_input_manager(compositor->wl_display()) + : QtWaylandServer::wl_text_input_manager(compositor->wl_display(), 1) , m_compositor(compositor) { } diff --git a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp index b91d1fb61..150a04e5b 100644 --- a/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp +++ b/src/compositor/windowmanagerprotocol/waylandwindowmanagerintegration.cpp @@ -66,7 +66,7 @@ WindowManagerServerIntegration::~WindowManagerServerIntegration() void WindowManagerServerIntegration::initialize(QtWayland::Display *waylandDisplay) { - init(waylandDisplay->handle()); + init(waylandDisplay->handle(), 1); } void WindowManagerServerIntegration::setShowIsFullScreen(bool value) diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp index 89ccd9390..99a32018f 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.cpp @@ -56,7 +56,7 @@ static const char *qwaylandegl_threadedgl_blacklist_vendor[] = { }; QWaylandEglClientBufferIntegration::QWaylandEglClientBufferIntegration() - : m_waylandDisplay(0) + : m_display(0) , m_eglDisplay(EGL_NO_DISPLAY) , m_supportsThreading(false) { @@ -76,10 +76,10 @@ void QWaylandEglClientBufferIntegration::initialize(QWaylandDisplay *display) setenv("EGL_PLATFORM","wayland",true); } - m_waylandDisplay = display->wl_display(); + m_display = display; EGLint major,minor; - m_eglDisplay = eglGetDisplay((EGLNativeDisplayType) m_waylandDisplay); + m_eglDisplay = eglGetDisplay((EGLNativeDisplayType) display->wl_display()); if (m_eglDisplay == EGL_NO_DISPLAY) { qWarning("EGL not available"); return; @@ -126,7 +126,7 @@ QWaylandWindow *QWaylandEglClientBufferIntegration::createEglWindow(QWindow *win QPlatformOpenGLContext *QWaylandEglClientBufferIntegration::createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const { - return new QWaylandGLContext(m_eglDisplay, glFormat, share); + return new QWaylandGLContext(m_eglDisplay, m_display, glFormat, share); } EGLDisplay QWaylandEglClientBufferIntegration::eglDisplay() const diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.h index 9d3d15094..75053190d 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglclientbufferintegration.h @@ -68,7 +68,7 @@ public: EGLDisplay eglDisplay() const; private: - struct wl_display *m_waylandDisplay; + QWaylandDisplay *m_display; EGLDisplay m_eglDisplay; bool m_supportsThreading; diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 5feed543c..9b445e10c 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -104,7 +104,6 @@ void QWaylandEglWindow::setGeometry(const QRect &rect) void QWaylandEglWindow::updateSurface(bool create) { - createDecoration(); QMargins margins = frameMargins(); QRect rect = geometry(); QSize sizeWithMargins = rect.size() + QSize(margins.left() + margins.right(), margins.top() + margins.bottom()); diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp index b2db1ad0c..81c74a7d5 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.cpp @@ -43,7 +43,7 @@ #include <QtWaylandClient/private/qwaylanddisplay_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h> -#include <QtWaylandClient/private/qwaylanddecoration_p.h> +#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h> #include <QtWaylandClient/private/qwaylandintegration_p.h> #include "qwaylandeglwindow.h" @@ -56,13 +56,174 @@ #include <qpa/qplatformopenglcontext.h> #include <QtGui/QSurfaceFormat> #include <QtGui/QOpenGLShaderProgram> +#include <QtGui/QOpenGLFunctions> + +// Constants from EGL_KHR_create_context +#ifndef EGL_CONTEXT_MINOR_VERSION_KHR +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#endif +#ifndef EGL_CONTEXT_FLAGS_KHR +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#endif +#ifndef EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#endif +#ifndef EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#endif +#ifndef EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#endif +#ifndef EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#endif +#ifndef EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#endif + +// Constants for OpenGL which are not available in the ES headers. +#ifndef GL_CONTEXT_FLAGS +#define GL_CONTEXT_FLAGS 0x821E +#endif +#ifndef GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001 +#endif +#ifndef GL_CONTEXT_FLAG_DEBUG_BIT +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#endif +#ifndef GL_CONTEXT_PROFILE_MASK +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#endif +#ifndef GL_CONTEXT_CORE_PROFILE_BIT +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#endif +#ifndef GL_CONTEXT_COMPATIBILITY_PROFILE_BIT +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#endif QT_BEGIN_NAMESPACE -QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share) +class DecorationsBlitter : public QOpenGLFunctions +{ +public: + DecorationsBlitter(QWaylandGLContext *context) + : m_context(context) + { + initializeOpenGLFunctions(); + m_blitProgram = new QOpenGLShaderProgram(); + m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute vec4 position;\n\ + attribute vec4 texCoords;\n\ + varying vec2 outTexCoords;\n\ + void main()\n\ + {\n\ + gl_Position = position;\n\ + outTexCoords = texCoords.xy;\n\ + }"); + m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, "varying highp vec2 outTexCoords;\n\ + uniform sampler2D texture;\n\ + void main()\n\ + {\n\ + gl_FragColor = texture2D(texture, outTexCoords);\n\ + }"); + + m_blitProgram->bindAttributeLocation("position", 0); + m_blitProgram->bindAttributeLocation("texCoords", 1); + + if (!m_blitProgram->link()) { + qDebug() << "Shader Program link failed."; + qDebug() << m_blitProgram->log(); + } + } + ~DecorationsBlitter() + { + delete m_blitProgram; + } + void blit(QWaylandEglWindow *window) + { + QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(m_context->context()); + + QRect windowRect = window->window()->frameGeometry(); + glViewport(0, 0, windowRect.width(), windowRect.height()); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); + glDepthMask(GL_FALSE); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + m_context->mUseNativeDefaultFbo = true; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + m_context->mUseNativeDefaultFbo = false; + + static const GLfloat squareVertices[] = { + -1.f, -1.f, + 1.0f, -1.f, + -1.f, 1.0f, + 1.0f, 1.0f + }; + + static const GLfloat inverseSquareVertices[] = { + -1.f, 1.f, + 1.f, 1.f, + -1.f, -1.f, + 1.f, -1.f + }; + + static const GLfloat textureVertices[] = { + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, + }; + + glBindBuffer(GL_ARRAY_BUFFER, 0); + m_blitProgram->bind(); + + m_blitProgram->enableAttributeArray(0); + m_blitProgram->enableAttributeArray(1); + m_blitProgram->setAttributeArray(1, textureVertices, 2); + + glActiveTexture(GL_TEXTURE0); + + //Draw Decoration + m_blitProgram->setAttributeArray(0, inverseSquareVertices, 2); + QImage decorationImage = window->decoration()->contentImage(); + cache->bindTexture(m_context->context(), decorationImage); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (m_context->context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + } else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + //Draw Content + m_blitProgram->setAttributeArray(0, squareVertices, 2); + glBindTexture(GL_TEXTURE_2D, window->contentTexture()); + QRect r = window->contentsRect(); + glViewport(r.x(), r.y(), r.width(), r.height()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + //Cleanup + m_blitProgram->disableAttributeArray(0); + m_blitProgram->disableAttributeArray(1); + } + + QOpenGLShaderProgram *m_blitProgram; + QWaylandGLContext *m_context; +}; + + + +QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, const QSurfaceFormat &format, QPlatformOpenGLContext *share) : QPlatformOpenGLContext() , m_eglDisplay(eglDisplay) - , m_blitProgram(0) + , m_display(display) + , m_blitter(0) , mUseNativeDefaultFbo(false) { QSurfaceFormat fmt = format; @@ -72,6 +233,36 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat m_format = q_glFormatFromConfig(m_eglDisplay, m_config); m_shareEGLContext = share ? static_cast<QWaylandGLContext *>(share)->eglContext() : EGL_NO_CONTEXT; + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(format.majorVersion()); + const bool hasKHRCreateContext = q_hasEglExtension(m_eglDisplay, "EGL_KHR_create_context"); + if (hasKHRCreateContext) { + eglContextAttrs.append(EGL_CONTEXT_MINOR_VERSION_KHR); + eglContextAttrs.append(format.minorVersion()); + int flags = 0; + // The debug bit is supported both for OpenGL and OpenGL ES. + if (format.testOption(QSurfaceFormat::DebugContext)) + flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + // The fwdcompat bit is only for OpenGL 3.0+. + if (m_format.renderableType() == QSurfaceFormat::OpenGL + && format.majorVersion() >= 3 + && !format.testOption(QSurfaceFormat::DeprecatedFunctions)) + flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; + if (flags) { + eglContextAttrs.append(EGL_CONTEXT_FLAGS_KHR); + eglContextAttrs.append(flags); + } + // Profiles are OpenGL only and mandatory in 3.2+. The value is silently ignored for < 3.2. + if (m_format.renderableType() == QSurfaceFormat::OpenGL) { + eglContextAttrs.append(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR); + eglContextAttrs.append(format.profile() == QSurfaceFormat::CoreProfile + ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR + : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR); + } + } + eglContextAttrs.append(EGL_NONE); + switch (m_format.renderableType()) { case QSurfaceFormat::OpenVG: eglBindAPI(EGL_OPENVG_API); @@ -90,11 +281,6 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat break; } - QVector<EGLint> eglContextAttrs; - eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); - eglContextAttrs.append(format.majorVersion() == 1 ? 1 : 2); - eglContextAttrs.append(EGL_NONE); - m_context = eglCreateContext(m_eglDisplay, m_config, m_shareEGLContext, eglContextAttrs.constData()); if (m_context == EGL_NO_CONTEXT) { @@ -103,13 +289,75 @@ QWaylandGLContext::QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat } EGLint error = eglGetError(); - if (error != EGL_SUCCESS) + if (error != EGL_SUCCESS) { qWarning("QWaylandGLContext: failed to create EGLContext, error=%x", error); + return; + } + + updateGLFormat(); +} + +void QWaylandGLContext::updateGLFormat() +{ + // Have to save & restore to prevent QOpenGLContext::currentContext() from becoming + // inconsistent after QOpenGLContext::create(). + EGLDisplay prevDisplay = eglGetCurrentDisplay(); + if (prevDisplay == EGL_NO_DISPLAY) // when no context is current + prevDisplay = m_eglDisplay; + EGLContext prevContext = eglGetCurrentContext(); + EGLSurface prevSurfaceDraw = eglGetCurrentSurface(EGL_DRAW); + EGLSurface prevSurfaceRead = eglGetCurrentSurface(EGL_READ); + + wl_surface *wlSurface = m_display->createSurface(Q_NULLPTR); + wl_egl_window *eglWindow = wl_egl_window_create(wlSurface, 1, 1); + EGLSurface eglSurface = eglCreateWindowSurface(m_eglDisplay, m_config, eglWindow, 0); + + if (eglMakeCurrent(m_eglDisplay, eglSurface, eglSurface, m_context)) { + if (m_format.renderableType() == QSurfaceFormat::OpenGL + || m_format.renderableType() == QSurfaceFormat::OpenGLES) { + const GLubyte *s = glGetString(GL_VERSION); + if (s) { + QByteArray version = QByteArray(reinterpret_cast<const char *>(s)); + int major, minor; + if (QPlatformOpenGLContext::parseOpenGLVersion(version, major, minor)) { + m_format.setMajorVersion(major); + m_format.setMinorVersion(minor); + } + } + m_format.setProfile(QSurfaceFormat::NoProfile); + m_format.setOptions(QSurfaceFormat::FormatOptions()); + if (m_format.renderableType() == QSurfaceFormat::OpenGL) { + // Check profile and options. + if (m_format.majorVersion() < 3) { + m_format.setOption(QSurfaceFormat::DeprecatedFunctions); + } else { + GLint value = 0; + glGetIntegerv(GL_CONTEXT_FLAGS, &value); + if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)) + m_format.setOption(QSurfaceFormat::DeprecatedFunctions); + if (value & GL_CONTEXT_FLAG_DEBUG_BIT) + m_format.setOption(QSurfaceFormat::DebugContext); + if (m_format.version() >= qMakePair(3, 2)) { + value = 0; + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value); + if (value & GL_CONTEXT_CORE_PROFILE_BIT) + m_format.setProfile(QSurfaceFormat::CoreProfile); + else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) + m_format.setProfile(QSurfaceFormat::CompatibilityProfile); + } + } + } + } + eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); + } + eglDestroySurface(m_eglDisplay, eglSurface); + wl_egl_window_destroy(eglWindow); + wl_surface_destroy(wlSurface); } QWaylandGLContext::~QWaylandGLContext() { - delete m_blitProgram; + delete m_blitter; eglDestroyContext(m_eglDisplay, m_context); } @@ -122,6 +370,13 @@ bool QWaylandGLContext::makeCurrent(QPlatformSurface *surface) return true; window->setCanResize(false); + // Core profiles mandate the use of VAOs when rendering. We would then need to use one + // in DecorationsBlitter, but for that we would need a QOpenGLFunctions_3_2_Core instead + // of the QOpenGLFunctions we use, but that would break when using a lower version context. + // Instead of going crazy, just disable decorations for core profiles until we use + // subsurfaces for them. + if (m_format.profile() != QSurfaceFormat::CoreProfile && !window->decoration()) + window->createDecoration(); if (eglSurface == EGL_NO_SURFACE) { window->updateSurface(true); @@ -253,104 +508,9 @@ void QWaylandGLContext::swapBuffers(QPlatformSurface *surface) // for random context state changes in a swapBuffers() call. StateGuard stateGuard; - if (!m_blitProgram) { - initializeOpenGLFunctions(); - m_blitProgram = new QOpenGLShaderProgram(); - m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute vec4 position;\n\ - attribute vec4 texCoords;\n\ - varying vec2 outTexCoords;\n\ - void main()\n\ - {\n\ - gl_Position = position;\n\ - outTexCoords = texCoords.xy;\n\ - }"); - m_blitProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, "varying highp vec2 outTexCoords;\n\ - uniform sampler2D texture;\n\ - void main()\n\ - {\n\ - gl_FragColor = texture2D(texture, outTexCoords);\n\ - }"); - - m_blitProgram->bindAttributeLocation("position", 0); - m_blitProgram->bindAttributeLocation("texCoords", 1); - - if (!m_blitProgram->link()) { - qDebug() << "Shader Program link failed."; - qDebug() << m_blitProgram->log(); - } - } - - QOpenGLTextureCache *cache = QOpenGLTextureCache::cacheForContext(context()); - - QRect windowRect = window->window()->frameGeometry(); - glViewport(0, 0, windowRect.width(), windowRect.height()); - - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glDisable(GL_CULL_FACE); - glDisable(GL_SCISSOR_TEST); - glDepthMask(GL_FALSE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - mUseNativeDefaultFbo = true; - glBindFramebuffer(GL_FRAMEBUFFER, 0); - mUseNativeDefaultFbo = false; - - static const GLfloat squareVertices[] = { - -1.f, -1.f, - 1.0f, -1.f, - -1.f, 1.0f, - 1.0f, 1.0f - }; - - static const GLfloat inverseSquareVertices[] = { - -1.f, 1.f, - 1.f, 1.f, - -1.f, -1.f, - 1.f, -1.f - }; - - static const GLfloat textureVertices[] = { - 0.0f, 0.0f, - 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, - }; - - glBindBuffer(GL_ARRAY_BUFFER, 0); - m_blitProgram->bind(); - - m_blitProgram->enableAttributeArray(0); - m_blitProgram->enableAttributeArray(1); - m_blitProgram->setAttributeArray(1, textureVertices, 2); - - glActiveTexture(GL_TEXTURE0); - - //Draw Decoration - m_blitProgram->setAttributeArray(0, inverseSquareVertices, 2); - QImage decorationImage = window->decoration()->contentImage(); - cache->bindTexture(context(), decorationImage); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (context()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Draw Content - m_blitProgram->setAttributeArray(0, squareVertices, 2); - glBindTexture(GL_TEXTURE_2D, window->contentTexture()); - QRect r = window->contentsRect(); - glViewport(r.x(), r.y(), r.width(), r.height()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - //Cleanup - m_blitProgram->disableAttributeArray(0); - m_blitProgram->disableAttributeArray(1); + if (!m_blitter) + m_blitter = new DecorationsBlitter(this); + m_blitter->blit(window); } eglSwapBuffers(m_eglDisplay, eglSurface); diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h index 9a1dda014..5528eca7d 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandglcontext.h @@ -45,7 +45,6 @@ #include <QtWaylandClient/private/qwaylanddisplay_p.h> #include <qpa/qplatformopenglcontext.h> -#include <QtGui/QOpenGLFunctions> #include "qwaylandeglinclude.h" @@ -55,11 +54,12 @@ class QWaylandWindow; class QWaylandGLWindowSurface; class QOpenGLShaderProgram; class QOpenGLTextureCache; +class DecorationsBlitter; -class QWaylandGLContext : public QPlatformOpenGLContext, protected QOpenGLFunctions +class QWaylandGLContext : public QPlatformOpenGLContext { public: - QWaylandGLContext(EGLDisplay eglDisplay, const QSurfaceFormat &format, QPlatformOpenGLContext *share); + QWaylandGLContext(EGLDisplay eglDisplay, QWaylandDisplay *display, const QSurfaceFormat &format, QPlatformOpenGLContext *share); ~QWaylandGLContext(); void swapBuffers(QPlatformSurface *surface); @@ -80,14 +80,18 @@ public: EGLContext eglContext() const { return m_context; } private: - EGLDisplay m_eglDisplay; + void updateGLFormat(); + EGLDisplay m_eglDisplay; + QWaylandDisplay *m_display; EGLContext m_context; EGLContext m_shareEGLContext; EGLConfig m_config; QSurfaceFormat m_format; - QOpenGLShaderProgram *m_blitProgram; + DecorationsBlitter *m_blitter; bool mUseNativeDefaultFbo; + + friend class DecorationsBlitter; }; QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmbuffer.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmbuffer.cpp index e4fbfb553..d480b2dae 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmbuffer.cpp +++ b/src/hardwareintegration/compositor/brcm-egl/brcmbuffer.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE BrcmBuffer::BrcmBuffer(struct ::wl_client *client, uint32_t id, const QSize &size, EGLint *data, size_t count) - : QtWaylandServer::wl_buffer(client, id) + : QtWaylandServer::wl_buffer(client, id, 1) , m_handle(count) , m_invertedY(false) , m_size(size) diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp index 66533fecb..9fc8badd5 100644 --- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp +++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp @@ -120,7 +120,7 @@ void BrcmEglIntegration::initializeHardware(QtWayland::Display *waylandDisplay) return; } d->valid = true; - init(waylandDisplay->handle()); + init(waylandDisplay->handle(), 1); } } diff --git a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp index 09588f6ff..4e9a04495 100644 --- a/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp +++ b/src/hardwareintegration/compositor/drm-egl-server/drmeglserverbufferintegration.cpp @@ -95,7 +95,7 @@ struct ::wl_resource *DrmEglServerBuffer::resourceForClient(struct ::wl_client * return 0; } struct ::wl_resource *drm_egl_resource = (*drm_egl_it)->handle; - Resource *resource = add(client); + Resource *resource = add(client, 1, 1); m_integration->send_server_buffer_created(drm_egl_resource, resource->handle, m_name, m_size.width(), m_size.height(), m_stride, m_drm_format); return resource->handle; } @@ -166,7 +166,7 @@ void DrmEglServerBufferIntegration::initializeHardware(QWaylandCompositor *compo return; } - QtWaylandServer::qt_drm_egl_server_buffer::init(compositor->waylandDisplay()); + QtWaylandServer::qt_drm_egl_server_buffer::init(compositor->waylandDisplay(), 1); } bool DrmEglServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const diff --git a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp index c15f3d154..7e7a14ab8 100644 --- a/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp +++ b/src/hardwareintegration/compositor/libhybris-egl-server/libhybriseglserverbufferintegration.cpp @@ -89,7 +89,7 @@ struct ::wl_resource *LibHybrisEglServerBuffer::resourceForClient(struct ::wl_cl return 0; } struct ::wl_resource *egl_resource = (*egl_it)->handle; - Resource *resource = add(client); + Resource *resource = add(client, 1, 1); wl_resource *bufRes = wl_client_new_object(client, &qt_libhybris_buffer_interface, 0, 0); m_integration->send_server_buffer_created(egl_resource, resource->handle, bufRes, m_fds.size(), QByteArray((char *)m_ints.data(), m_ints.size() * sizeof(int32_t)), @@ -174,7 +174,7 @@ void LibHybrisEglServerBufferIntegration::initializeHardware(QWaylandCompositor return; } - QtWaylandServer::qt_libhybris_egl_server_buffer::init(compositor->waylandDisplay()); + QtWaylandServer::qt_libhybris_egl_server_buffer::init(compositor->waylandDisplay(), 1); } bool LibHybrisEglServerBufferIntegration::supportsFormat(QtWayland::ServerBuffer::Format format) const diff --git a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp index 0457214b4..09789d864 100644 --- a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp +++ b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp @@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE XCompositeBuffer::XCompositeBuffer(Window window, const QSize &size, struct ::wl_client *client, uint32_t id) - : QtWaylandServer::wl_buffer(client, id) + : QtWaylandServer::wl_buffer(client, id, 1) , mWindow(window) , mInvertedY(false) , mSize(size) diff --git a/src/hardwareintegration/compositor/xcomposite_share/xcompositehandler.cpp b/src/hardwareintegration/compositor/xcomposite_share/xcompositehandler.cpp index 0f10d38de..5e002377e 100644 --- a/src/hardwareintegration/compositor/xcomposite_share/xcompositehandler.cpp +++ b/src/hardwareintegration/compositor/xcomposite_share/xcompositehandler.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE XCompositeHandler::XCompositeHandler(QtWayland::Compositor *compositor, Display *display) - : QtWaylandServer::qt_xcomposite(compositor->wl_display()) + : QtWaylandServer::qt_xcomposite(compositor->wl_display(), 1) { compositor->window()->create(); diff --git a/src/plugins/decorations/bradient/bradient.json b/src/plugins/decorations/bradient/bradient.json new file mode 100644 index 000000000..e1a5ef24f --- /dev/null +++ b/src/plugins/decorations/bradient/bradient.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "bradient" ] +} diff --git a/src/plugins/decorations/bradient/bradient.pro b/src/plugins/decorations/bradient/bradient.pro new file mode 100644 index 000000000..fd376f4a9 --- /dev/null +++ b/src/plugins/decorations/bradient/bradient.pro @@ -0,0 +1,17 @@ +PLUGIN_TYPE = wayland-decoration-client +load(qt_plugin) + +QT += waylandclient-private + +OTHER_FILES += \ + bradient.json + +SOURCES += main.cpp + +contains(QT_CONFIG, no-pkg-config) { + LIBS += -lwayland-client +} else { + CONFIG += link_pkgconfig + PKGCONFIG += wayland-client +} + diff --git a/src/client/qwaylanddecoration.cpp b/src/plugins/decorations/bradient/main.cpp index ed4978725..c249248c3 100644 --- a/src/client/qwaylanddecoration.cpp +++ b/src/plugins/decorations/bradient/main.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2014 Robin Burchell <robin.burchell@viroteck.net> ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -39,20 +40,18 @@ ** ****************************************************************************/ -#include "qwaylanddecoration_p.h" - -#include "qwaylandwindow_p.h" -#include "qwaylandshellsurface_p.h" -#include "qwaylandinputdevice_p.h" -#include "qwaylandscreen_p.h" - -#include <QtGui/QGuiApplication> -#include <QtGui/QImage> #include <QtGui/QCursor> #include <QtGui/QPainter> #include <QtGui/QPalette> #include <QtGui/QLinearGradient> +#include <qpa/qwindowsysteminterface.h> + +#include <QtWaylandClient/private/qwaylanddecorationplugin_p.h> +#include <QtWaylandClient/private/qwaylandabstractdecoration_p.h> +#include <QtWaylandClient/private/qwaylandwindow_p.h> +#include <QtWaylandClient/private/qwaylandshellsurface_p.h> + QT_BEGIN_NAMESPACE #define BUTTON_SPACING 5 @@ -123,16 +122,35 @@ static const char * const qt_normalizeup_xpm[] = { # define BUTTON_WIDTH 22 #endif -QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) - : m_window(window->window()) - , m_wayland_window(window) - , m_isDirty(true) - , m_decorationContentImage(0) - , m_margins(3,30,3,3) - , m_mouseButtons(Qt::NoButton) +class Q_WAYLAND_CLIENT_EXPORT QWaylandBradientDecoration : public QWaylandAbstractDecoration +{ +public: + QWaylandBradientDecoration(); +protected: + QMargins margins() const Q_DECL_OVERRIDE; + void paint(QPaintDevice *device) Q_DECL_OVERRIDE; + bool handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,Qt::MouseButtons b,Qt::KeyboardModifiers mods) Q_DECL_OVERRIDE; + bool handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) Q_DECL_OVERRIDE; +private: + void processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + void processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b,Qt::KeyboardModifiers mods); + + QRectF closeButtonRect() const; + QRectF maximizeButtonRect() const; + QRectF minimizeButtonRect() const; + + QColor m_foregroundColor; + QColor m_backgroundColor; + QStaticText m_windowTitle; +}; + + + +QWaylandBradientDecoration::QWaylandBradientDecoration() + : QWaylandAbstractDecoration() { - m_wayland_window->setDecoration(this); - QPalette palette; m_foregroundColor = palette.color(QPalette::Active, QPalette::HighlightedText); m_backgroundColor = palette.color(QPalette::Active, QPalette::Highlight); @@ -142,32 +160,30 @@ QWaylandDecoration::QWaylandDecoration(QWaylandWindow *window) m_windowTitle.setTextOption(option); } -QWaylandDecoration::~QWaylandDecoration() +QRectF QWaylandBradientDecoration::closeButtonRect() const { - m_wayland_window->setDecoration(0); + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -const QImage &QWaylandDecoration::contentImage() +QRectF QWaylandBradientDecoration::maximizeButtonRect() const { - if (m_isDirty) { - //Update the decoration backingstore - - m_decorationContentImage = QImage(window()->frameGeometry().size(), QImage::Format_ARGB32_Premultiplied); - m_decorationContentImage.fill(Qt::transparent); - this->paint(&m_decorationContentImage); - - m_isDirty = false; - } + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); +} - return m_decorationContentImage; +QRectF QWaylandBradientDecoration::minimizeButtonRect() const +{ + return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, + (margins().top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); } -void QWaylandDecoration::update() +QMargins QWaylandBradientDecoration::margins() const { - m_isDirty = true; + return QMargins(3, 30, 3, 3); } -void QWaylandDecoration::paint(QPaintDevice *device) +void QWaylandBradientDecoration::paint(QPaintDevice *device) { QRect surfaceRect(QPoint(), window()->frameGeometry().size()); QRect clips[] = @@ -199,7 +215,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) } // Window icon - QIcon icon = m_wayland_window->windowIcon(); + QIcon icon = waylandWindow()->windowIcon(); if (!icon.isNull()) { QPixmap pixmap = icon.pixmap(QSize(128, 128)); QPixmap scaled = pixmap.scaled(22, 22, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); @@ -219,7 +235,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) } QRect titleBar = top; - titleBar.setLeft(m_margins.left() + BUTTON_SPACING + + titleBar.setLeft(margins().left() + BUTTON_SPACING + (icon.isNull() ? 0 : 22 + BUTTON_SPACING)); titleBar.setRight(minimizeButtonRect().left() - BUTTON_SPACING); @@ -234,7 +250,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.setFont(font); QPoint windowTitlePoint(top.topLeft().x() + dx, top.topLeft().y() + dy); - p.drawStaticText(windowTitlePoint,m_windowTitle); + p.drawStaticText(windowTitlePoint, m_windowTitle); p.restore(); } @@ -246,7 +262,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.drawPixmap(closeButtonRect(), closePixmap, closePixmap.rect()); // Maximize button - QPixmap maximizePixmap(m_wayland_window->isMaximized() + QPixmap maximizePixmap(waylandWindow()->isMaximized() ? qt_normalizeup_xpm : qt_maximize_xpm); p.drawPixmap(maximizeButtonRect(), maximizePixmap, maximizePixmap.rect()); @@ -282,7 +298,7 @@ void QWaylandDecoration::paint(QPaintDevice *device) p.save(); p.drawRect(maximizeButtonRect()); rect = maximizeButtonRect().adjusted(5, 5, -5, -5); - if (m_wayland_window->isMaximized()) { + if (waylandWindow()->isMaximized()) { QRectF rect1 = rect.adjusted(rect.width() / 3, 0, 0, -rect.height() / 3); QRectF rect2 = rect.adjusted(0, rect.height() / 4, -rect.width() / 4, 0); p.drawRect(rect1); @@ -305,37 +321,37 @@ void QWaylandDecoration::paint(QPaintDevice *device) #endif } -bool QWaylandDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +bool QWaylandBradientDecoration::handleMouse(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(global); // Figure out what area mouse is in if (closeButtonRect().contains(local) && isLeftClicked(b)) { - QWindowSystemInterface::handleCloseEvent(m_window); + QWindowSystemInterface::handleCloseEvent(window()); } else if (maximizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); } else if (minimizeButtonRect().contains(local) && isLeftClicked(b)) { - m_window->setWindowState(Qt::WindowMinimized); - } else if (local.y() <= m_margins.top()) { + window()->setWindowState(Qt::WindowMinimized); + } else if (local.y() <= margins().top()) { processMouseTop(inputDevice,local,b,mods); - } else if (local.y() > m_window->height() - m_margins.bottom() + m_margins.top()) { + } else if (local.y() > window()->height() - margins().bottom() + margins().top()) { processMouseBottom(inputDevice,local,b,mods); - } else if (local.x() <= m_margins.left()) { + } else if (local.x() <= margins().left()) { processMouseLeft(inputDevice,local,b,mods); - } else if (local.x() > m_window->width() - m_margins.right() + m_margins.left()) { + } else if (local.x() > window()->width() - margins().right() + margins().left()) { processMouseRight(inputDevice,local,b,mods); } else { - m_wayland_window->restoreMouseCursor(inputDevice); - m_mouseButtons = b; + waylandWindow()->restoreMouseCursor(inputDevice); + setMouseButtons(b); return false; } - m_mouseButtons = b; + setMouseButtons(b); return true; } -bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) +bool QWaylandBradientDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods) { Q_UNUSED(inputDevice); Q_UNUSED(global); @@ -343,13 +359,13 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo bool handled = state == Qt::TouchPointPressed; if (handled) { if (closeButtonRect().contains(local)) - QWindowSystemInterface::handleCloseEvent(m_window); + QWindowSystemInterface::handleCloseEvent(window()); else if (maximizeButtonRect().contains(local)) - m_window->setWindowState(m_wayland_window->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); + window()->setWindowState(waylandWindow()->isMaximized() ? Qt::WindowNoState : Qt::WindowMaximized); else if (minimizeButtonRect().contains(local)) - m_window->setWindowState(Qt::WindowMinimized); - else if (local.y() <= m_margins.top()) - m_wayland_window->shellSurface()->move(inputDevice); + window()->setWindowState(Qt::WindowMinimized); + else if (local.y() <= margins().top()) + waylandWindow()->shellSurface()->move(inputDevice); else handled = false; } @@ -357,115 +373,80 @@ bool QWaylandDecoration::handleTouch(QWaylandInputDevice *inputDevice, const QPo return handled; } -bool QWaylandDecoration::inMouseButtonPressedState() const -{ - return m_mouseButtons & Qt::NoButton; -} - -void QWaylandDecoration::startResize(QWaylandInputDevice *inputDevice, enum wl_shell_surface_resize resize, Qt::MouseButtons buttons) -{ - if (isLeftClicked(buttons)) { - m_wayland_window->shellSurface()->resize(inputDevice, resize); - inputDevice->removeMouseButtonFromState(Qt::LeftButton); - } -} - -void QWaylandDecoration::startMove(QWaylandInputDevice *inputDevice, Qt::MouseButtons buttons) -{ - if (isLeftClicked(buttons)) { - m_wayland_window->shellSurface()->move(inputDevice); - inputDevice->removeMouseButtonFromState(Qt::LeftButton); - } -} - -void QWaylandDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseTop(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); - if (local.y() <= m_margins.bottom()) { + if (local.y() <= margins().bottom()) { if (local.x() <= margins().left()) { //top left bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { + } else if (local.x() > window()->width() - margins().right()) { //top right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP_RIGHT,b); } else { //top reszie bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_TOP,b); } } else { - m_wayland_window->restoreMouseCursor(inputDevice); + waylandWindow()->restoreMouseCursor(inputDevice); startMove(inputDevice,b); } } -void QWaylandDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseBottom(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(mods); if (local.x() <= margins().left()) { //bottom left bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeBDiagCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT,b); - } else if (local.x() > m_window->width() - margins().right()) { + } else if (local.x() > window()->width() - margins().right()) { //bottom right bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SizeFDiagCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT,b); } else { //bottom bit - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitVCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitVCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_BOTTOM,b); } } -void QWaylandDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseLeft(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); startResize(inputDevice,WL_SHELL_SURFACE_RESIZE_LEFT,b); } -void QWaylandDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) +void QWaylandBradientDecoration::processMouseRight(QWaylandInputDevice *inputDevice, const QPointF &local, Qt::MouseButtons b, Qt::KeyboardModifiers mods) { Q_UNUSED(local); Q_UNUSED(mods); - m_wayland_window->setMouseCursor(inputDevice, Qt::SplitHCursor); + waylandWindow()->setMouseCursor(inputDevice, Qt::SplitHCursor); startResize(inputDevice, WL_SHELL_SURFACE_RESIZE_RIGHT,b); } -bool QWaylandDecoration::isLeftClicked(Qt::MouseButtons newMouseButtonState) +class QWaylandBradientDecorationPlugin : public QWaylandDecorationPlugin { - if ((!m_mouseButtons & Qt::LeftButton) && (newMouseButtonState & Qt::LeftButton)) - return true; - return false; -} + Q_OBJECT + Q_PLUGIN_METADATA(IID QWaylandDecorationFactoryInterface_iid FILE "bradient.json") +public: + QWaylandAbstractDecoration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; +}; -bool QWaylandDecoration::isLeftReleased(Qt::MouseButtons newMouseButtonState) +QWaylandAbstractDecoration *QWaylandBradientDecorationPlugin::create(const QString& system, const QStringList& paramList) { - if ((m_mouseButtons & Qt::LeftButton) && !(newMouseButtonState & Qt::LeftButton)) - return true; - return false; + Q_UNUSED(paramList); + Q_UNUSED(system); + return new QWaylandBradientDecoration(); } -QRectF QWaylandDecoration::closeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH - BUTTON_SPACING * 2, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} - -QRectF QWaylandDecoration::maximizeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 2 - BUTTON_SPACING * 3, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} - -QRectF QWaylandDecoration::minimizeButtonRect() const -{ - return QRectF(window()->frameGeometry().width() - BUTTON_WIDTH * 3 - BUTTON_SPACING * 4, - (m_margins.top() - BUTTON_WIDTH) / 2, BUTTON_WIDTH, BUTTON_WIDTH); -} QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/decorations/decorations.pro b/src/plugins/decorations/decorations.pro new file mode 100644 index 000000000..6d51a450f --- /dev/null +++ b/src/plugins/decorations/decorations.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS += \ + bradient diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 554dd40cd..a1a8a5b7d 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -1,2 +1,5 @@ TEMPLATE=subdirs -SUBDIRS += platforms hardwareintegration +SUBDIRS += \ + platforms \ + hardwareintegration \ + decorations diff --git a/src/qtwaylandscanner/qtwaylandscanner.cpp b/src/qtwaylandscanner/qtwaylandscanner.cpp index c99bf2b48..ae5ec40db 100644 --- a/src/qtwaylandscanner/qtwaylandscanner.cpp +++ b/src/qtwaylandscanner/qtwaylandscanner.cpp @@ -416,8 +416,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" class %s %s\n {\n", serverExport.constData(), interfaceName); printf(" public:\n"); - printf(" %s(struct ::wl_client *client, int id);\n", interfaceName); - printf(" %s(struct ::wl_display *display);\n", interfaceName); + printf(" %s(struct ::wl_client *client, int id, int version);\n", interfaceName); + printf(" %s(struct ::wl_display *display, int version);\n", interfaceName); printf(" %s();\n", interfaceName); printf("\n"); printf(" virtual ~%s();\n", interfaceName); @@ -432,16 +432,17 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" struct ::wl_resource *handle;\n"); printf("\n"); printf(" struct ::wl_client *client() const { return handle->client; }\n"); + printf(" int version() const { return wl_resource_get_version(handle); }\n"); printf("\n"); printf(" static Resource *fromResource(struct ::wl_resource *resource) { return static_cast<Resource *>(resource->data); }\n"); printf(" };\n"); printf("\n"); - printf(" void init(struct ::wl_client *client, int id);\n"); - printf(" void init(struct ::wl_display *display);\n"); + printf(" void init(struct ::wl_client *client, int id, int version);\n"); + printf(" void init(struct ::wl_display *display, int version);\n"); printf("\n"); - printf(" Resource *add(struct ::wl_client *client);\n"); - printf(" Resource *add(struct ::wl_client *client, int id);\n"); - printf(" Resource *add(struct wl_list *resource_list, struct ::wl_client *client, int id);\n"); + printf(" Resource *add(struct ::wl_client *client, int version);\n"); + printf(" Resource *add(struct ::wl_client *client, int id, int version);\n"); + printf(" Resource *add(struct wl_list *resource_list, struct ::wl_client *client, int id, int version);\n"); printf("\n"); printf(" Resource *resource() { return m_resource; }\n"); printf(" const Resource *resource() const { return m_resource; }\n"); @@ -491,7 +492,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" static void bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id);\n"); printf(" static void destroy_func(struct ::wl_resource *client_resource);\n"); printf("\n"); - printf(" Resource *bind(struct ::wl_client *client, uint32_t id);\n"); + printf(" Resource *bind(struct ::wl_client *client, uint32_t id, int version);\n"); if (hasRequests) { printf("\n"); @@ -511,6 +512,7 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" QMultiMap<struct ::wl_client*, Resource*> m_resource_map;\n"); printf(" Resource *m_resource;\n"); printf(" struct ::wl_global *m_global;\n"); + printf(" uint32_t m_globalVersion;\n"); printf(" };\n"); if (j < interfaces.size() - 1) @@ -551,21 +553,21 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr QByteArray stripped = stripInterfaceName(interface.name, prefix); const char *interfaceNameStripped = stripped.constData(); - printf(" %s::%s(struct ::wl_client *client, int id)\n", interfaceName, interfaceName); + printf(" %s::%s(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName); printf(" : m_resource_map()\n"); printf(" , m_resource(0)\n"); printf(" , m_global(0)\n"); printf(" {\n"); - printf(" init(client, id);\n"); + printf(" init(client, id, version);\n"); printf(" }\n"); printf("\n"); - printf(" %s::%s(struct ::wl_display *display)\n", interfaceName, interfaceName); + printf(" %s::%s(struct ::wl_display *display, int version)\n", interfaceName, interfaceName); printf(" : m_resource_map()\n"); printf(" , m_resource(0)\n"); printf(" , m_global(0)\n"); printf(" {\n"); - printf(" init(display);\n"); + printf(" init(display, version);\n"); printf(" }\n"); printf("\n"); @@ -582,31 +584,32 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" }\n"); printf("\n"); - printf(" void %s::init(struct ::wl_client *client, int id)\n", interfaceName); + printf(" void %s::init(struct ::wl_client *client, int id, int version)\n", interfaceName); printf(" {\n"); - printf(" m_resource = bind(client, id);\n"); + printf(" m_resource = bind(client, id, version);\n"); printf(" }\n"); printf("\n"); - printf(" %s::Resource *%s::add(struct ::wl_client *client)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::add(struct ::wl_client *client, int version)\n", interfaceName, interfaceName); printf(" {\n"); - printf(" Resource *resource = bind(client, 0);\n"); + printf(" Resource *resource = bind(client, 0, version);\n"); printf(" m_resource_map.insert(client, resource);\n"); printf(" return resource;\n"); printf(" }\n"); printf("\n"); - printf(" %s::Resource *%s::add(struct ::wl_client *client, int id)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::add(struct ::wl_client *client, int id, int version)\n", interfaceName, interfaceName); printf(" {\n"); - printf(" Resource *resource = bind(client, id);\n"); + printf(" Resource *resource = bind(client, id, version);\n"); printf(" m_resource_map.insert(client, resource);\n"); printf(" return resource;\n"); printf(" }\n"); printf("\n"); - printf(" void %s::init(struct ::wl_display *display)\n", interfaceName); + printf(" void %s::init(struct ::wl_display *display, int version)\n", interfaceName); printf(" {\n"); - printf(" m_global = wl_global_create(display, &::%s_interface, ::%s_interface.version, this, bind_func);\n", interfaceName, interfaceName); + printf(" m_global = wl_global_create(display, &::%s_interface, version, this, bind_func);\n", interfaceName); + printf(" m_globalVersion = version;\n"); printf(" }\n"); printf("\n"); @@ -628,8 +631,8 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr printf(" void %s::bind_func(struct ::wl_client *client, void *data, uint32_t version, uint32_t id)\n", interfaceName); printf(" {\n"); - printf(" Q_UNUSED(version);\n"); - printf(" static_cast<%s *>(data)->add(client, id);\n", interfaceName); + printf(" %s *that = static_cast<%s *>(data);\n", interfaceName, interfaceName); + printf(" that->add(client, id, qMin(that->m_globalVersion, version));\n"); printf(" }\n"); printf("\n"); @@ -652,12 +655,12 @@ void process(QXmlStreamReader &xml, const QByteArray &headerPath, const QByteArr //We should consider changing bind so that it doesn't special case id == 0 //and use function overloading instead. Jan do you have a lot of code dependent on this behavior? - printf(" %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id)\n", interfaceName, interfaceName); + printf(" %s::Resource *%s::bind(struct ::wl_client *client, uint32_t id, int version)\n", interfaceName, interfaceName); printf(" {\n"); printf(" Resource *resource = %s_allocate();\n", interfaceNameStripped); printf(" resource->%s_object = this;\n", interfaceNameStripped); printf("\n"); - printf(" struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, ::%s_interface.version, id);\n", interfaceName, interfaceName); + printf(" struct ::wl_resource *handle = wl_resource_create(client, &::%s_interface, version, id);\n", interfaceName); printf(" wl_resource_set_implementation(handle, %s, resource, destroy_func);", interfaceMember.constData()); printf("\n"); printf(" resource->handle = handle;\n"); diff --git a/tests/auto/client/mockcompositor.cpp b/tests/auto/client/mockcompositor.cpp index cb0e6576e..665b7dd73 100644 --- a/tests/auto/client/mockcompositor.cpp +++ b/tests/auto/client/mockcompositor.cpp @@ -238,7 +238,7 @@ void Compositor::dispatchEvents(int timeout) static void compositor_create_surface(wl_client *client, wl_resource *compositorResource, uint32_t id) { Compositor *compositor = static_cast<Compositor *>(compositorResource->data); - compositor->addSurface(new Surface(client, id, compositor)); + compositor->addSurface(new Surface(client, id, wl_resource_get_version(compositorResource), compositor)); } static void compositor_create_region(wl_client *client, wl_resource *compositorResource, uint32_t id) diff --git a/tests/auto/client/mockinput.cpp b/tests/auto/client/mockinput.cpp index fbe44de41..754aa4590 100644 --- a/tests/auto/client/mockinput.cpp +++ b/tests/auto/client/mockinput.cpp @@ -101,7 +101,7 @@ void Compositor::sendKeyRelease(void *data, const QList<QVariant> ¶meters) } Seat::Seat(Compositor *compositor, struct ::wl_display *display) - : wl_seat(display) + : wl_seat(display, 2) , m_compositor(compositor) , m_keyboard(new Keyboard(compositor)) , m_pointer(new Pointer(compositor)) @@ -119,12 +119,12 @@ void Seat::seat_bind_resource(Resource *resource) void Seat::seat_get_keyboard(Resource *resource, uint32_t id) { - m_keyboard->add(resource->client(), id); + m_keyboard->add(resource->client(), id, resource->version()); } void Seat::seat_get_pointer(Resource *resource, uint32_t id) { - m_pointer->add(resource->client(), id); + m_pointer->add(resource->client(), id, resource->version()); } Keyboard::Keyboard(Compositor *compositor) @@ -240,7 +240,7 @@ DataDevice::~DataDevice() } DataDeviceManager::DataDeviceManager(Compositor *compositor, wl_display *display) - : wl_data_device_manager(display) + : wl_data_device_manager(display, 1) , m_compositor(compositor) { @@ -255,7 +255,7 @@ void DataDeviceManager::data_device_manager_get_data_device(Resource *resource, { if (!m_data_device) m_data_device.reset(new DataDevice(m_compositor)); - m_data_device->add(resource->client(), id); + m_data_device->add(resource->client(), id, 1); } } diff --git a/tests/auto/client/mocksurface.cpp b/tests/auto/client/mocksurface.cpp index 2e4c2bc73..330213bde 100644 --- a/tests/auto/client/mocksurface.cpp +++ b/tests/auto/client/mocksurface.cpp @@ -44,8 +44,8 @@ namespace Impl { -Surface::Surface(wl_client *client, uint32_t id, Compositor *compositor) - : QtWaylandServer::wl_surface(client, id) +Surface::Surface(wl_client *client, uint32_t id, int v, Compositor *compositor) + : QtWaylandServer::wl_surface(client, id, v) , m_buffer(Q_NULLPTR) , m_compositor(compositor) , m_mockSurface(new MockSurface(this)) diff --git a/tests/auto/client/mocksurface.h b/tests/auto/client/mocksurface.h index f2a2f4eb3..33ced4385 100644 --- a/tests/auto/client/mocksurface.h +++ b/tests/auto/client/mocksurface.h @@ -50,7 +50,7 @@ namespace Impl { class Surface : public QtWaylandServer::wl_surface { public: - Surface(wl_client *client, uint32_t id, Compositor *compositor); + Surface(wl_client *client, uint32_t id, int v, Compositor *compositor); ~Surface(); Compositor *compositor() const { return m_compositor; } |